lapillus 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|