lapillus 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/examples/guest_book.rb +5 -5
- data/examples/hello_world.rb +1 -1
- data/examples/{persons.rb → personspage.rb} +4 -4
- data/examples/tc_hello_world.rb +11 -11
- data/examples/{tc_persons.rb → tc_personspage.rb} +2 -2
- data/html/{Persons.html → Personspage.html} +0 -0
- data/lib/changelog.txt +10 -0
- data/lib/lapillus/base.rb +82 -82
- data/lib/lapillus/behaviours.rb +53 -38
- data/lib/lapillus/components.rb +9 -7
- data/lib/lapillus/containers.rb +32 -49
- data/lib/lapillus/dispatcher.rb +35 -24
- data/lib/lapillus/form_components.rb +11 -7
- data/lib/lapillus/html_visitor.rb +68 -0
- data/lib/lapillus/pager.rb +8 -8
- data/test/tc_base.rb +2 -2
- data/test/tc_behaviours.rb +29 -7
- data/test/tc_bookmarkablepagelink.rb +5 -5
- data/test/tc_components.rb +42 -21
- data/test/tc_containers.rb +22 -18
- data/test/tc_examples.rb +18 -18
- data/test/tc_form.rb +15 -15
- data/test/tc_fragments.rb +8 -6
- data/test/tc_hierarchy.rb +1 -1
- data/test/tc_lapillus.rb +2 -2
- data/test/tc_lapillus_testers.rb +6 -6
- data/test/tc_multiview.rb +7 -7
- data/test/tc_pager.rb +5 -3
- data/test/tc_rendering.rb +4 -4
- data/test/ts_all_test.rb +0 -1
- metadata +6 -5
data/examples/guest_book.rb
CHANGED
@@ -16,7 +16,7 @@ end
|
|
16
16
|
|
17
17
|
class CommentForm < Form
|
18
18
|
attr_reader :comment
|
19
|
-
textarea
|
19
|
+
textarea :text, :model => :comment, :property => :text
|
20
20
|
def initialize(id)
|
21
21
|
super(id)
|
22
22
|
@comment = Comment.new
|
@@ -30,14 +30,14 @@ end
|
|
30
30
|
|
31
31
|
class GuestBook < Webpage
|
32
32
|
attr_reader :comments
|
33
|
-
listview
|
34
|
-
add(Label.new(
|
35
|
-
add(MultiLineLabel.new(
|
33
|
+
listview :commentslist, :model => :comments do |comment|
|
34
|
+
add(Label.new(:date, comment.date.to_s))
|
35
|
+
add(MultiLineLabel.new(:text, comment.text))
|
36
36
|
end
|
37
37
|
def initialize
|
38
38
|
super()
|
39
39
|
@comments = []
|
40
|
-
add(CommentForm.new(
|
40
|
+
add(CommentForm.new(:commentform))
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
data/examples/hello_world.rb
CHANGED
@@ -10,10 +10,10 @@ class Person
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
class
|
13
|
+
class Personspage < Webpage
|
14
14
|
attr_reader :persons
|
15
|
-
listview
|
16
|
-
label
|
15
|
+
listview :personlist, :model => :persons do |person|
|
16
|
+
label :name, :model => person, :property => :name
|
17
17
|
end
|
18
18
|
|
19
19
|
def initialize
|
@@ -25,6 +25,6 @@ class Persons < Webpage
|
|
25
25
|
end
|
26
26
|
|
27
27
|
if __FILE__ == $0
|
28
|
-
server = LapillusServer.new(:root_url => "/", :port => 2000, :homepage =>
|
28
|
+
server = LapillusServer.new(:root_url => "/", :port => 2000, :homepage => Personspage)
|
29
29
|
server.start
|
30
30
|
end
|
data/examples/tc_hello_world.rb
CHANGED
@@ -10,15 +10,15 @@ class TC_HelloWorld < Test::Unit::TestCase
|
|
10
10
|
assert_equal("Hello world!", page.message.value)
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
def test_html
|
14
|
+
hello_world = HelloWorld.new
|
15
|
+
result = <<EOF
|
16
|
+
<html>
|
17
|
+
<body>
|
18
|
+
<span lapillus:id="message">Hello world!</span>
|
19
|
+
</body>
|
20
|
+
</html>
|
21
|
+
EOF
|
22
|
+
assert_equal( result.strip, hello_world.render )
|
23
|
+
end
|
24
24
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
require 'examples/
|
2
|
+
require 'examples/personspage'
|
3
3
|
|
4
4
|
class TC_Persons < Test::Unit::TestCase
|
5
5
|
def test_persons
|
6
|
-
page =
|
6
|
+
page = Personspage.new
|
7
7
|
assert_equal(1, page.components.size)
|
8
8
|
assert_equal(2, page.personlist.size)
|
9
9
|
assert_equal("jantje", page.personlist[0].name.value)
|
File without changes
|
data/lib/changelog.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
Changes Lapillus 0.0.2 --> 0.0.3
|
2
|
+
- Refactoring: Component identifiers have become Symbols instead of Strings
|
3
|
+
- Refactoring: use named parameters in Component constructor to set options (like :visible=false)
|
4
|
+
- Refactoring: Persons example renamed to PersonsPage example
|
5
|
+
- Refactoring: Lapillus now works with ruby 1.8.6 (version contains some changes in the REXML API)
|
6
|
+
- Refactoring: HTML rendering is now done using the visitor pattern instead of recursion
|
7
|
+
- First version of the Lapillus website (Thanks to Joris van Zundert)
|
8
|
+
URL: http://hi3.huygensinstituut.nl:2000/
|
9
|
+
|
10
|
+
|
1
11
|
Changes Lapillus 0.0.1 --> 0.0.2
|
2
12
|
- Applied mini-patch from Willem van den Ende to the examples
|
3
13
|
- Added processUpload helper module
|
data/lib/lapillus/base.rb
CHANGED
@@ -1,14 +1,76 @@
|
|
1
1
|
module Lapillus
|
2
2
|
|
3
|
-
|
3
|
+
|
4
|
+
class RenderableComponent
|
5
|
+
def initialize
|
6
|
+
@behaviours = {}
|
7
|
+
@visible = true
|
8
|
+
end
|
9
|
+
def render_container(visitor, element)
|
10
|
+
on_render
|
11
|
+
return if !visible?
|
12
|
+
new_element = REXML::Element.new(element)
|
13
|
+
visitor.container_output.add(new_element)
|
14
|
+
visitor.container_output = new_element
|
15
|
+
render_children(visitor, element)
|
16
|
+
visitor.container_output = new_element.parent
|
17
|
+
render_to_element(new_element)
|
18
|
+
render_behaviours(new_element)
|
19
|
+
end
|
20
|
+
|
21
|
+
def visible?
|
22
|
+
@visible
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_behaviours(element)
|
26
|
+
@behaviours.each_value {|behaviour| behaviour.render_to_element(element)}
|
27
|
+
end
|
28
|
+
|
29
|
+
#NOTE: override in subclasses
|
30
|
+
def render_children(visitor, element)
|
31
|
+
end
|
32
|
+
|
33
|
+
#NOTE: override in subclasses
|
34
|
+
def render_to_element(new_element)
|
35
|
+
end
|
36
|
+
|
37
|
+
#NOTE: override in subclasses
|
38
|
+
def on_render
|
39
|
+
end
|
40
|
+
|
41
|
+
# this method is meant for AJAX
|
42
|
+
def render_component
|
43
|
+
doc = REXML::Document.new webpage.default_htmlfile
|
44
|
+
visitor = HtmlVisitor.new(webpage)
|
45
|
+
doc.root.accept(visitor)
|
46
|
+
result_dom = visitor.container_output.root
|
47
|
+
element = REXML::XPath.first( result_dom, "//*[@id=\"#{path}\"]" )
|
48
|
+
if element == nil
|
49
|
+
message = "Identifier "+path+" not found! in "+doc.to_s
|
50
|
+
raise message
|
51
|
+
end
|
52
|
+
formatter = REXML::Formatters::Default.new
|
53
|
+
to_send = element.children.inject("") {|result, child|
|
54
|
+
formatter.write(child, result)
|
55
|
+
}
|
56
|
+
#puts "DEBUG: "+to_send
|
57
|
+
return to_send
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
class Component < RenderableComponent
|
4
64
|
attr_reader :identifier, :property, :behaviours
|
5
65
|
attr_writer :visible, :model
|
6
|
-
def initialize(id,
|
66
|
+
def initialize(id, options={})
|
67
|
+
super()
|
68
|
+
raise "FATAL: use a symbol as identifier! #{id.class}: #{id}" if id!=""&&!id.kind_of?(Symbol)
|
69
|
+
raise "FATAL: use named parameters! #{options.class}" if !options.kind_of?(Hash)
|
7
70
|
@identifier = id
|
8
|
-
@model = model
|
9
|
-
@property = property
|
10
|
-
@
|
11
|
-
@visible = true
|
71
|
+
@model = options[:model]
|
72
|
+
@property = options[:property]
|
73
|
+
@visible = options[:visible]||true
|
12
74
|
end
|
13
75
|
#TODO: make model defensive!
|
14
76
|
def model
|
@@ -30,13 +92,6 @@ module Lapillus
|
|
30
92
|
end
|
31
93
|
end
|
32
94
|
|
33
|
-
def on_render
|
34
|
-
end
|
35
|
-
|
36
|
-
def visible?
|
37
|
-
@visible
|
38
|
-
end
|
39
|
-
|
40
95
|
def has_model?
|
41
96
|
!@model.nil?
|
42
97
|
end
|
@@ -87,21 +142,6 @@ module Lapillus
|
|
87
142
|
return @behaviours[behaviour_class]
|
88
143
|
end
|
89
144
|
|
90
|
-
# this method is meant for AJAX
|
91
|
-
def render_component
|
92
|
-
doc = REXML::Document.new webpage.default_htmlfile
|
93
|
-
result_dom = webpage.render_container(doc.root)
|
94
|
-
element = REXML::XPath.first( result_dom, "//*[@id=\"#{path}\"]" )
|
95
|
-
if element == nil
|
96
|
-
message = "Identifier "+identifier+" not found! in "+doc.to_s
|
97
|
-
raise message
|
98
|
-
end
|
99
|
-
to_send = element.children.inject("") {|result, child|
|
100
|
-
child.write(result)
|
101
|
-
}
|
102
|
-
# puts "DEBUG: "+to_send
|
103
|
-
return to_send
|
104
|
-
end
|
105
145
|
|
106
146
|
protected
|
107
147
|
def hierarchy
|
@@ -109,17 +149,6 @@ module Lapillus
|
|
109
149
|
[self]
|
110
150
|
end
|
111
151
|
|
112
|
-
def render_container(container_element)
|
113
|
-
new_element = REXML::Element.new(container_element)
|
114
|
-
render_to_element(new_element)
|
115
|
-
render_behaviours(new_element)
|
116
|
-
return new_element
|
117
|
-
end
|
118
|
-
|
119
|
-
def render_behaviours(element)
|
120
|
-
@behaviours.each_value {|behaviour| behaviour.render_to_element(element)}
|
121
|
-
end
|
122
|
-
|
123
152
|
#TODO: not here!
|
124
153
|
def post(values)
|
125
154
|
end
|
@@ -128,7 +157,7 @@ module Lapillus
|
|
128
157
|
@parent = parent
|
129
158
|
end
|
130
159
|
|
131
|
-
private
|
160
|
+
# private
|
132
161
|
def remove_behaviour(behaviour_class)
|
133
162
|
@behaviours.delete(behaviour_class)
|
134
163
|
end
|
@@ -158,8 +187,8 @@ module Lapillus
|
|
158
187
|
end
|
159
188
|
|
160
189
|
public
|
161
|
-
def initialize(id,
|
162
|
-
super(id,
|
190
|
+
def initialize(id, options={})
|
191
|
+
super(id, options)
|
163
192
|
@components = []
|
164
193
|
classes_to_process.each {|clazz|
|
165
194
|
clazz.stored_components.each {|stored_component|
|
@@ -191,6 +220,7 @@ module Lapillus
|
|
191
220
|
|
192
221
|
#deprecated
|
193
222
|
def component(identifier)
|
223
|
+
identifier = identifier.intern if identifier.kind_of?(String)
|
194
224
|
result = components.find{|component|
|
195
225
|
component.identifier.eql?(identifier)
|
196
226
|
}
|
@@ -201,49 +231,19 @@ module Lapillus
|
|
201
231
|
#NOTE: is this really the responsibility of container?
|
202
232
|
def post(values)
|
203
233
|
components.each {|component| component.post(values)}
|
204
|
-
end
|
205
|
-
|
206
|
-
def render_container(container)
|
207
|
-
new_element = REXML::Element.new(container)
|
208
|
-
render_children(container, new_element)
|
209
|
-
render_to_element(new_element)
|
210
|
-
render_behaviours(new_element)
|
211
|
-
return new_element
|
212
234
|
end
|
213
235
|
|
214
|
-
protected
|
215
|
-
def render_children(container_input,container_output)
|
216
|
-
container_input.children.each do |child|
|
217
|
-
case child.node_type
|
218
|
-
when :text
|
219
|
-
container_output.add_text(child.value)
|
220
|
-
when :element
|
221
|
-
#puts "processing element: "+child.name
|
222
|
-
if child.name!="fragment"
|
223
|
-
component_id = child.attributes['lapillus:id']
|
224
|
-
if !component_id.nil?
|
225
|
-
child_component = self[component_id]
|
226
|
-
child_component.on_render
|
227
|
-
container_output.add(child_component.render_container(child)) if child_component.visible?
|
228
|
-
else
|
229
|
-
new_element = REXML::Element.new(child)
|
230
|
-
container_output.add(new_element)
|
231
|
-
render_children(child, new_element)
|
232
|
-
end
|
233
|
-
end
|
234
|
-
when :comment
|
235
|
-
comment = REXML::Comment.new(child)
|
236
|
-
container_output.add(comment)
|
237
|
-
else
|
238
|
-
puts "unknown node type: "+child.node_type.to_s
|
239
|
-
end
|
240
|
-
end
|
241
|
-
return container_output
|
242
|
-
end
|
243
236
|
|
244
|
-
|
237
|
+
#TODO: duplicate with NullComponent.render_children!
|
238
|
+
def render_children(visitor, element)
|
239
|
+
visitor.current_container = self #NOTE: Added!
|
240
|
+
element.children.each do |child|
|
241
|
+
# puts child.class
|
242
|
+
child.accept(visitor)
|
243
|
+
end
|
244
|
+
visitor.current_container = self.parent #NOTE: Added!
|
245
245
|
end
|
246
|
-
|
246
|
+
|
247
247
|
private
|
248
248
|
def classes_to_process
|
249
249
|
classes = []
|
@@ -266,7 +266,7 @@ module Lapillus
|
|
266
266
|
#Note: Internal
|
267
267
|
class StoredComponent
|
268
268
|
attr_reader :identifier, :block
|
269
|
-
|
269
|
+
|
270
270
|
def initialize(id, block)
|
271
271
|
@identifier = id
|
272
272
|
@block = block
|
data/lib/lapillus/behaviours.rb
CHANGED
@@ -1,11 +1,26 @@
|
|
1
1
|
require 'rexml/attribute'
|
2
2
|
require 'yaml'
|
3
3
|
|
4
|
+
module REXML
|
5
|
+
class Element
|
6
|
+
def add_javascript(javascript)
|
7
|
+
script = REXML::Element.new('script')
|
8
|
+
script.add_attributes({'type'=>'text/javascript', 'language'=>'javascript'})
|
9
|
+
text=REXML::Text.new("\n// <![CDATA[\n#{javascript}\n// ]]>\n")
|
10
|
+
def text.to_s
|
11
|
+
@normalized=@string
|
12
|
+
end
|
13
|
+
script.add_text(text)
|
14
|
+
self.add_element(script)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
4
19
|
module Lapillus
|
5
20
|
|
6
21
|
class Behaviour < Component
|
7
|
-
def initialize(id="",
|
8
|
-
super(id,
|
22
|
+
def initialize(id="", options={})
|
23
|
+
super(id, options)
|
9
24
|
end
|
10
25
|
|
11
26
|
# def add_javascript_to_header root, src
|
@@ -27,10 +42,10 @@ end
|
|
27
42
|
|
28
43
|
class AttributeModifier < Behaviour
|
29
44
|
def render_to_element(element)
|
30
|
-
attribute = REXML::Attribute.new(identifier, value)
|
31
|
-
def attribute.to_string
|
32
|
-
return "#@expanded_name=\"#@value\""
|
33
|
-
end
|
45
|
+
attribute = REXML::Attribute.new(identifier.to_s, value)
|
46
|
+
# def attribute.to_string
|
47
|
+
# return "#@expanded_name=\"#@value\""
|
48
|
+
# end
|
34
49
|
element.add_attribute(attribute)
|
35
50
|
end
|
36
51
|
end
|
@@ -38,7 +53,7 @@ end
|
|
38
53
|
#TODO test
|
39
54
|
class UniqueIdentifier < AttributeModifier
|
40
55
|
def initialize
|
41
|
-
super(
|
56
|
+
super(:id)
|
42
57
|
end
|
43
58
|
def value
|
44
59
|
parent.path
|
@@ -47,10 +62,10 @@ end
|
|
47
62
|
|
48
63
|
class FadeIn < Behaviour
|
49
64
|
def render_to_element(element)
|
50
|
-
attribute = REXML::Attribute.new(identifier, "new Effect.Appear('#{value}');")
|
51
|
-
def attribute.to_string
|
52
|
-
return "#@expanded_name=\"#@value\""
|
53
|
-
end
|
65
|
+
attribute = REXML::Attribute.new(identifier.to_s, "new Effect.Appear('#{value}');")
|
66
|
+
# def attribute.to_string
|
67
|
+
# return "#@expanded_name=\"#@value\""
|
68
|
+
# end
|
54
69
|
element.add_attribute(attribute)
|
55
70
|
end
|
56
71
|
end
|
@@ -108,15 +123,8 @@ class Draggable < UniqueIdentifier
|
|
108
123
|
#add_javascript_to_header(element.root_node,"/editiemachine/context/javascript/prototype.js")
|
109
124
|
#add_javascript_to_header(element.root_node,"/editiemachine/context/javascript/scriptaculous.js")
|
110
125
|
|
111
|
-
script = REXML::Element.new('script')
|
112
|
-
script.add_attributes({'type'=>'text/javascript', 'language'=>'javascript'})
|
113
126
|
options=@option.to_a.collect{|o| "#{o[0]}:#{o[1]}" }.sort.concat(@extra_options).join(",")
|
114
|
-
|
115
|
-
def text.to_s
|
116
|
-
@normalized=@string
|
117
|
-
end
|
118
|
-
script.add_text(text)
|
119
|
-
element.add_element(script)
|
127
|
+
element.add_javascript("new Draggable('#{parent.path}', {#{options}});")
|
120
128
|
end
|
121
129
|
end
|
122
130
|
|
@@ -124,7 +132,7 @@ end
|
|
124
132
|
# todo: add test
|
125
133
|
class OnClick < Behaviour
|
126
134
|
def initialize(component_to_refresh=nil)
|
127
|
-
super(
|
135
|
+
super("", :model => component_to_refresh)
|
128
136
|
component_to_refresh.add_behaviour(UniqueIdentifier.new) if has_model?
|
129
137
|
end
|
130
138
|
|
@@ -135,20 +143,34 @@ class OnClick < Behaviour
|
|
135
143
|
javascript = "new Ajax.Request('', { method: 'get', parameters: { listener:'#{parent.path}' }}); return false;"
|
136
144
|
end
|
137
145
|
attribute = REXML::Attribute.new("onclick", javascript)
|
138
|
-
# TODO: this should be the default for attributes in
|
139
|
-
# Lapillus somewhere!
|
140
|
-
def attribute.to_string
|
141
|
-
return "#@expanded_name=\"#@value\""
|
142
|
-
end
|
146
|
+
# # TODO: this should be the default for attributes in
|
147
|
+
# # Lapillus somewhere!
|
148
|
+
# def attribute.to_string
|
149
|
+
# return "#@expanded_name=\"#@value\""
|
150
|
+
# end
|
143
151
|
element.add_attribute(attribute)
|
144
152
|
end
|
145
153
|
end
|
146
154
|
|
155
|
+
class PostWithAjax < AttributeModifier
|
156
|
+
attr_accessor :component_to_refresh
|
157
|
+
def initialize(component_to_refresh=nil)
|
158
|
+
super(:onsubmit)
|
159
|
+
@component_to_refresh = component_to_refresh
|
160
|
+
component_to_refresh.add_behaviour(UniqueIdentifier.new) if !component_to_refresh.nil?
|
161
|
+
end
|
162
|
+
|
163
|
+
def value
|
164
|
+
updateScript = "new Ajax.Updater('#{component_to_refresh.path}', '', { evalScripts: true, method: 'post', parameters:Form.serialize(this)}); return false;"
|
165
|
+
return updateScript
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
147
169
|
# value is the component to rerender when a link is clicked
|
148
170
|
# the component should have an id attribute which is set to its path
|
149
171
|
class AjaxLink < Container
|
150
|
-
def initialize(id,
|
151
|
-
super(id,
|
172
|
+
def initialize(id, options={})
|
173
|
+
super(id, options)
|
152
174
|
value.add_behaviour(UniqueIdentifier.new) if has_model?
|
153
175
|
end
|
154
176
|
|
@@ -159,9 +181,9 @@ class AjaxLink < Container
|
|
159
181
|
javascript = "new Ajax.Request('', { method: 'get', parameters: { listener:'#{path}' }}); return false;"
|
160
182
|
end
|
161
183
|
attribute = REXML::Attribute.new("onclick", javascript)
|
162
|
-
def attribute.to_string
|
163
|
-
return "#@expanded_name=\"#@value\""
|
164
|
-
end
|
184
|
+
# def attribute.to_string
|
185
|
+
# return "#@expanded_name=\"#@value\""
|
186
|
+
# end
|
165
187
|
element.add_attribute(attribute)
|
166
188
|
element.add_attribute("href","#")
|
167
189
|
end
|
@@ -194,14 +216,7 @@ class Droppable < UniqueIdentifier
|
|
194
216
|
});
|
195
217
|
EOF
|
196
218
|
super
|
197
|
-
|
198
|
-
script.add_attributes({'type'=>'text/javascript', 'language'=>'javascript'})
|
199
|
-
text=REXML::Text.new("\n// <![CDATA[\n#{javascript}\n// ]]>\n")
|
200
|
-
def text.to_s
|
201
|
-
@normalized=@string
|
202
|
-
end
|
203
|
-
script.add_text(text)
|
204
|
-
element.add_element(script)
|
219
|
+
element.add_javascript(javascript)
|
205
220
|
end
|
206
221
|
end
|
207
222
|
|
data/lib/lapillus/components.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'lapillus/base'
|
2
|
+
require 'uri'
|
2
3
|
|
3
4
|
module Lapillus
|
4
5
|
|
@@ -23,7 +24,7 @@ module Lapillus
|
|
23
24
|
options.keys.each {|key|
|
24
25
|
raise "Unknown key: #{key}" if key!=:model and key!=:property
|
25
26
|
}
|
26
|
-
internal_add_component(id) { Label.new(id, options
|
27
|
+
internal_add_component(id) { Label.new(id, options) }
|
27
28
|
end
|
28
29
|
|
29
30
|
#TODO: Add test!
|
@@ -32,7 +33,7 @@ module Lapillus
|
|
32
33
|
options.keys.each {|key|
|
33
34
|
raise "Unknown key: #{key}" if key!=:model and key!=:property
|
34
35
|
}
|
35
|
-
add(Label.new(id, options
|
36
|
+
add(Label.new(id, options))
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
@@ -84,14 +85,15 @@ module Lapillus
|
|
84
85
|
class Image < Component
|
85
86
|
attr_reader :root_url
|
86
87
|
|
87
|
-
def initialize(id,
|
88
|
-
super(id,
|
88
|
+
def initialize(id, options={})
|
89
|
+
super(id, options)
|
90
|
+
root_url = options[:root_url]
|
89
91
|
raise "root_url is not set!" if root_url.nil?
|
90
92
|
@root_url = root_url
|
91
93
|
end
|
92
94
|
|
93
95
|
def render_to_element(element)
|
94
|
-
url = "/images/#{value}"
|
96
|
+
url = "/images/#{URI::escape(value)}"
|
95
97
|
url = root_url + url if root_url != "/"
|
96
98
|
element.add_attribute("src", url)
|
97
99
|
end
|
@@ -101,7 +103,7 @@ module Lapillus
|
|
101
103
|
options.keys.each {|key|
|
102
104
|
raise "Unknown key: #{key}" if key!=:model and key!=:root_url
|
103
105
|
}
|
104
|
-
internal_add_component(id) { Image.new(id, options
|
106
|
+
internal_add_component(id) { Image.new(id, options) }
|
105
107
|
end
|
106
108
|
|
107
109
|
class ListItem < Container
|
@@ -109,7 +111,7 @@ module Lapillus
|
|
109
111
|
options.keys.each {|key|
|
110
112
|
raise "Unknown key: #{key}" if key!=:model and key!=:root_url
|
111
113
|
}
|
112
|
-
add(Image.new(id, options
|
114
|
+
add(Image.new(id, options))
|
113
115
|
end
|
114
116
|
end
|
115
117
|
|