wee 0.4.0 → 0.5.0
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/ChangeLog +75 -0
- data/README +17 -9
- data/Rakefile +2 -2
- data/TODO +20 -0
- data/benchmark/Makefile +14 -9
- data/benchmark/counter.rb +11 -30
- data/benchmark/report_req.rb +12 -0
- data/doc/rdoc/classes/Array.html +12 -12
- data/doc/rdoc/classes/Cache/StorageCache.html +38 -38
- data/doc/rdoc/classes/Cache/Strategy/CapacityBounded.html +30 -30
- data/doc/rdoc/classes/Cache/Strategy/LFU.html +24 -24
- data/doc/rdoc/classes/Cache/Strategy/LRU.html +24 -24
- data/doc/rdoc/classes/Cache/Strategy/Unbounded.html +24 -24
- data/doc/rdoc/classes/Enumerable.html +6 -6
- data/doc/rdoc/classes/Object.html +12 -12
- data/doc/rdoc/classes/OgApplication.html +126 -0
- data/doc/rdoc/classes/OgScaffolder.html +401 -0
- data/doc/rdoc/classes/OgSession.html +172 -0
- data/doc/rdoc/classes/String.html +12 -12
- data/doc/rdoc/classes/Struct.html +12 -12
- data/doc/rdoc/classes/Wee.html +5 -62
- data/doc/rdoc/classes/Wee/AnswerDecoration.html +9 -9
- data/doc/rdoc/classes/Wee/Application.html +107 -39
- data/doc/rdoc/classes/Wee/Brush.html +22 -18
- data/doc/rdoc/classes/Wee/Brush/ActionCallbackMixin.html +17 -11
- data/doc/rdoc/classes/Wee/Brush/ActionURLCallbackMixin.html +18 -10
- data/doc/rdoc/classes/Wee/Brush/AnchorTag.html +30 -64
- data/doc/rdoc/classes/Wee/Brush/FileUploadTag.html +8 -10
- data/doc/rdoc/classes/Wee/Brush/FormTag.html +27 -79
- data/doc/rdoc/classes/Wee/Brush/GenericEncodedTextBrush.html +12 -12
- data/doc/rdoc/classes/Wee/Brush/GenericSingleTagBrush.html +146 -0
- data/doc/rdoc/classes/Wee/Brush/GenericTagBrush.html +179 -65
- data/doc/rdoc/classes/Wee/Brush/GenericTextBrush.html +12 -12
- data/doc/rdoc/classes/Wee/Brush/ImageButtonTag.html +16 -18
- data/doc/rdoc/classes/Wee/Brush/ImageTag.html +203 -0
- data/doc/rdoc/classes/Wee/Brush/InputCallbackMixin.html +17 -11
- data/doc/rdoc/classes/Wee/Brush/InputTag.html +15 -15
- data/doc/rdoc/classes/Wee/Brush/JavascriptTag.html +147 -0
- data/doc/rdoc/classes/Wee/Brush/Page.html +17 -17
- data/doc/rdoc/classes/Wee/Brush/SelectListTag.html +25 -50
- data/doc/rdoc/classes/Wee/Brush/SelectOptionTag.html +7 -38
- data/doc/rdoc/classes/Wee/Brush/SubmitButtonTag.html +7 -7
- data/doc/rdoc/classes/Wee/Brush/TableDataTag.html +15 -16
- data/doc/rdoc/classes/Wee/Brush/TableHeaderTag.html +7 -7
- data/doc/rdoc/classes/Wee/Brush/TableRowTag.html +65 -50
- data/doc/rdoc/classes/Wee/Brush/TableTag.html +7 -7
- data/doc/rdoc/classes/Wee/Brush/TextAreaTag.html +14 -64
- data/doc/rdoc/classes/Wee/Brush/TextInputTag.html +7 -7
- data/doc/rdoc/classes/Wee/Brush/ToCallback.html +146 -0
- data/doc/rdoc/classes/Wee/CallbackRegistry.html +40 -40
- data/doc/rdoc/classes/Wee/CallbackStream.html +18 -18
- data/doc/rdoc/classes/Wee/Canvas.html +24 -24
- data/doc/rdoc/classes/Wee/Component.html +232 -149
- data/doc/rdoc/classes/Wee/Component/OnAnswer.html +153 -0
- data/doc/rdoc/classes/Wee/Decoration.html +42 -42
- data/doc/rdoc/classes/Wee/Delegate.html +27 -27
- data/doc/rdoc/classes/Wee/ErrorResponse.html +12 -12
- data/doc/rdoc/classes/Wee/FormDecoration.html +148 -0
- data/doc/rdoc/classes/Wee/GenericResponse.html +6 -6
- data/doc/rdoc/classes/Wee/HtmlCanvas.html +296 -215
- data/doc/rdoc/classes/Wee/HtmlWriter.html +83 -81
- data/doc/rdoc/classes/Wee/LiteralMethodCallback.html +21 -16
- data/doc/rdoc/classes/Wee/MessageBox.html +180 -0
- data/doc/rdoc/classes/Wee/PageDecoration.html +30 -30
- data/doc/rdoc/classes/Wee/Presenter.html +237 -69
- data/doc/rdoc/classes/Wee/RedirectResponse.html +6 -6
- data/doc/rdoc/classes/Wee/RefreshResponse.html +6 -6
- data/doc/rdoc/classes/Wee/Request.html +18 -18
- data/doc/rdoc/classes/Wee/RequestHandler.html +43 -39
- data/doc/rdoc/classes/Wee/Response.html +24 -24
- data/doc/rdoc/classes/Wee/Session.html +746 -72
- data/doc/rdoc/classes/Wee/SimpleIdGenerator.html +18 -18
- data/doc/rdoc/classes/Wee/Snapshot.html +19 -19
- data/doc/rdoc/classes/Wee/Utils.html +138 -2
- data/doc/rdoc/classes/Wee/Utils/LRUCache.html +7 -7
- data/doc/rdoc/classes/Wee/ValueHolder.html +18 -18
- data/doc/rdoc/classes/Wee/WEBrickAdaptor.html +43 -68
- data/doc/rdoc/classes/Wee/WrapperDecoration.html +150 -0
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/README.html +29 -15
- data/doc/rdoc/files/lib/wee/adaptors/webrick_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/application_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/components/form_decoration_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/components/messagebox_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/components/page_decoration_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/components/wrapper_decoration_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/components_rb.html +4 -1
- data/doc/rdoc/files/lib/wee/continuation/core/component_rb.html +101 -0
- data/doc/rdoc/files/lib/wee/continuation/session_rb.html +110 -0
- data/doc/rdoc/files/lib/wee/continuation_rb.html +116 -0
- data/doc/rdoc/files/lib/wee/core/callback_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/core/component_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/core/presenter_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/core_rb.html +3 -3
- data/doc/rdoc/files/lib/wee/databases/og_rb.html +108 -0
- data/doc/rdoc/files/lib/wee/renderer/html/brushes_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/renderer/html/canvas_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/renderer/html/writer_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/requesthandler_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/session_rb.html +1 -2
- data/doc/rdoc/files/lib/wee/utils/autoreload_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/utils/cache_rb.html +1 -1
- data/doc/rdoc/files/lib/wee/utils/helper_rb.html +1 -8
- data/doc/rdoc/files/lib/wee/utils_rb.html +110 -0
- data/doc/rdoc/files/lib/wee_rb.html +1 -1
- data/doc/rdoc/fr_class_index.html +11 -1
- data/doc/rdoc/fr_file_index.html +8 -0
- data/doc/rdoc/fr_method_index.html +269 -228
- data/examples/calculator.rb +69 -0
- data/examples/calendar.rb +5 -17
- data/examples/example.rb +2 -2
- data/examples/hw.rb +17 -0
- data/examples/live-update.rb +45 -0
- data/examples/og-test.rb +51 -0
- data/lib/wee.rb +1 -1
- data/lib/wee/adaptors/webrick.rb +2 -0
- data/lib/wee/application.rb +16 -0
- data/lib/wee/components.rb +3 -0
- data/lib/wee/components/form_decoration.rb +7 -0
- data/{test → lib/wee}/components/messagebox.rb +1 -1
- data/lib/wee/components/page_decoration.rb +5 -5
- data/lib/wee/components/wrapper_decoration.rb +7 -0
- data/lib/wee/continuation.rb +5 -0
- data/lib/wee/continuation/core/component.rb +55 -0
- data/lib/wee/continuation/session.rb +217 -0
- data/lib/wee/core/callback.rb +11 -6
- data/lib/wee/core/component.rb +45 -33
- data/lib/wee/core/presenter.rb +68 -0
- data/lib/wee/databases/og.rb +114 -0
- data/lib/wee/renderer/html/brushes.rb +179 -98
- data/lib/wee/renderer/html/canvas.rb +37 -13
- data/lib/wee/renderer/html/writer.rb +34 -32
- data/lib/wee/requesthandler.rb +6 -3
- data/lib/wee/session.rb +73 -54
- data/lib/wee/utils.rb +5 -0
- data/lib/wee/utils/autoreload.rb +1 -1
- data/lib/wee/utils/cache.rb +0 -2
- data/lib/wee/utils/helper.rb +40 -8
- data/test/components/calltest-cont.rb +16 -0
- data/test/components/calltest.rb +15 -10
- data/test/stress.rb +31 -28
- data/test/stress_and_measure.rb +53 -0
- data/test/stressed_application.rb +15 -0
- data/test/test_html_writer.rb +9 -4
- metadata +236 -195
- data/benchmark/bench.sh +0 -24
data/lib/wee/core/callback.rb
CHANGED
|
@@ -16,7 +16,7 @@ class Wee::CallbackRegistry
|
|
|
16
16
|
|
|
17
17
|
# Register +callback+ for +object+ under +type+ and return a unique callback id.
|
|
18
18
|
|
|
19
|
-
def register_for(object, type
|
|
19
|
+
def register_for(object, type, callback)
|
|
20
20
|
c = (@callbacks[type] ||= Hash.new)
|
|
21
21
|
o = (@obj_to_id_map[type] ||= Hash.new)
|
|
22
22
|
cid = @idgen.next.to_s
|
|
@@ -30,7 +30,7 @@ class Wee::CallbackRegistry
|
|
|
30
30
|
# :section: Friend methods for Wee::CallbackStream
|
|
31
31
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
32
32
|
|
|
33
|
-
def get_ids_for(object, type
|
|
33
|
+
def get_ids_for(object, type)
|
|
34
34
|
if o = @obj_to_id_map[type]
|
|
35
35
|
o[object] || []
|
|
36
36
|
else
|
|
@@ -38,7 +38,7 @@ class Wee::CallbackRegistry
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def get_callback_for(id, type
|
|
41
|
+
def get_callback_for(id, type)
|
|
42
42
|
if c = @callbacks[type]
|
|
43
43
|
c[id]
|
|
44
44
|
else
|
|
@@ -46,7 +46,7 @@ class Wee::CallbackRegistry
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def all_of_type(type
|
|
49
|
+
def all_of_type(type)
|
|
50
50
|
if c = @callbacks[type]
|
|
51
51
|
c
|
|
52
52
|
else
|
|
@@ -98,11 +98,16 @@ end
|
|
|
98
98
|
|
|
99
99
|
# A serializable callback.
|
|
100
100
|
class Wee::LiteralMethodCallback
|
|
101
|
-
def initialize(obj, method_id=:call)
|
|
101
|
+
def initialize(obj, method_id=:call, *additional_args)
|
|
102
102
|
@obj, @method_id = obj, method_id
|
|
103
|
+
@additional_args = additional_args unless additional_args.empty?
|
|
103
104
|
end
|
|
104
105
|
|
|
105
106
|
def call(*args)
|
|
106
|
-
@
|
|
107
|
+
if @additional_args
|
|
108
|
+
@obj.send(@method_id, *(args+@additional_args))
|
|
109
|
+
else
|
|
110
|
+
@obj.send(@method_id, *args)
|
|
111
|
+
end
|
|
107
112
|
end
|
|
108
113
|
end
|
data/lib/wee/core/component.rb
CHANGED
|
@@ -114,6 +114,7 @@ class Wee::Component < Wee::Presenter
|
|
|
114
114
|
|
|
115
115
|
def add_child(child)
|
|
116
116
|
self.children << child
|
|
117
|
+
child
|
|
117
118
|
end
|
|
118
119
|
|
|
119
120
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
@@ -282,46 +283,57 @@ class Wee::Component < Wee::Presenter
|
|
|
282
283
|
# [+component+]
|
|
283
284
|
# The component to be called.
|
|
284
285
|
#
|
|
286
|
+
# [+return_callback+]
|
|
287
|
+
# Is invoked when the called component answers.
|
|
288
|
+
# Either a symbol or any object that responds to #call. If it's a symbol,
|
|
289
|
+
# then the corresponding method of the current component will be called.
|
|
290
|
+
#
|
|
291
|
+
# [+additional_args+]
|
|
292
|
+
# Additional arguments that are passed (after the arguments given in
|
|
293
|
+
# #answer) to the +return_callback+
|
|
294
|
+
#
|
|
285
295
|
# <b>How it works</b>
|
|
286
296
|
#
|
|
287
|
-
|
|
288
|
-
# wrapped with an AnswerDecoration and the
|
|
289
|
-
# +
|
|
290
|
-
#
|
|
291
|
-
#
|
|
292
|
-
#
|
|
293
|
-
#
|
|
294
|
-
# called component invokes #answer, this will throw a <i>:wee_answer</i>
|
|
295
|
-
# exception which is catched in the AnswerDecoration. The AnswerDecoration
|
|
296
|
-
# then jumps back to the continuation we created at the beginning, and
|
|
297
|
-
# finally method #call returns.
|
|
297
|
+
|
|
298
|
+
# The component to be called is wrapped with an AnswerDecoration and the
|
|
299
|
+
# +return_callback+ parameter is assigned to it's +on_answer+ attribute (not
|
|
300
|
+
# directly as there are cleanup actions to be taken before the
|
|
301
|
+
# +return_callback+ can be invoked, hence we wrap it in the OnAnswer class).
|
|
302
|
+
# Then a Delegate decoration is added to the calling component (self), which
|
|
303
|
+
# delegates to the component to be called (+component+).
|
|
298
304
|
#
|
|
299
|
-
#
|
|
300
|
-
#
|
|
301
|
-
# callback
|
|
302
|
-
#
|
|
303
|
-
#
|
|
305
|
+
# Then we unwind the calling stack back to the Session by throwing
|
|
306
|
+
# <i>:wee_back_to_session</i>. This means, that there is only ever one action
|
|
307
|
+
# callback invoked per request. This is not neccessary, we could simply omit
|
|
308
|
+
# this, but then we'd break compatibility with the implementation using
|
|
309
|
+
# continuations.
|
|
310
|
+
#
|
|
311
|
+
# When at a later point in time the called component invokes #answer, this
|
|
312
|
+
# will throw a <i>:wee_answer</i> exception which is catched in the
|
|
313
|
+
# AnswerDecoration. The AnswerDecoration then invokes the +on_answer+
|
|
314
|
+
# callback which cleans up the decorations we added during #call, and finally
|
|
315
|
+
# passes control to the +return_callback+.
|
|
304
316
|
|
|
305
|
-
def call(component, return_callback
|
|
317
|
+
def call(component, return_callback=nil, *additional_args)
|
|
306
318
|
add_decoration(delegate = Wee::Delegate.new(component))
|
|
307
319
|
component.add_decoration(answer = Wee::AnswerDecoration.new)
|
|
320
|
+
answer.on_answer = OnAnswer.new(self, component, delegate, answer,
|
|
321
|
+
return_callback, additional_args)
|
|
322
|
+
throw :wee_back_to_session
|
|
323
|
+
end
|
|
308
324
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
remove_decoration(
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
component.remove_decoration(answer)
|
|
322
|
-
return_callback.call(*args)
|
|
323
|
-
}
|
|
324
|
-
throw :wee_back_to_session
|
|
325
|
+
class OnAnswer < Struct.new(:calling_component, :called_component, :delegate,
|
|
326
|
+
:answer, :return_callback, :additional_args)
|
|
327
|
+
|
|
328
|
+
def call(*args)
|
|
329
|
+
calling_component.remove_decoration(delegate)
|
|
330
|
+
called_component.remove_decoration(answer)
|
|
331
|
+
return if return_callback.nil?
|
|
332
|
+
if return_callback.respond_to?(:call)
|
|
333
|
+
return_callback.call(*(args + additional_args))
|
|
334
|
+
else
|
|
335
|
+
calling_component.send(return_callback, *(args + additional_args))
|
|
336
|
+
end
|
|
325
337
|
end
|
|
326
338
|
end
|
|
327
339
|
|
data/lib/wee/core/presenter.rb
CHANGED
|
@@ -129,4 +129,72 @@ class Wee::Presenter
|
|
|
129
129
|
Wee::Session.current
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
133
|
+
# :section: Properties
|
|
134
|
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
135
|
+
|
|
136
|
+
attr_accessor :properties
|
|
137
|
+
|
|
138
|
+
# Returns an "owned" property.
|
|
139
|
+
|
|
140
|
+
def get_property(prop)
|
|
141
|
+
if @properties
|
|
142
|
+
@properties[prop]
|
|
143
|
+
else
|
|
144
|
+
nil
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Tries to lookup a property from different places. +nil+ as property value
|
|
149
|
+
# is not allowed!
|
|
150
|
+
#
|
|
151
|
+
# Search order:
|
|
152
|
+
#
|
|
153
|
+
# 1. self.get_property(prop)
|
|
154
|
+
#
|
|
155
|
+
# 2. session.get_property(prop, self.class)
|
|
156
|
+
#
|
|
157
|
+
# 3. application.get_property(prop, self.class)
|
|
158
|
+
#
|
|
159
|
+
# 4. session.get_property(prop, nil)
|
|
160
|
+
#
|
|
161
|
+
# 5. application.get_property(prop, nil)
|
|
162
|
+
#
|
|
163
|
+
# 6. @@properties[prop]
|
|
164
|
+
#
|
|
165
|
+
|
|
166
|
+
def lookup_property(prop)
|
|
167
|
+
val = get_property(prop)
|
|
168
|
+
return val if val != nil
|
|
169
|
+
|
|
170
|
+
sess = session()
|
|
171
|
+
app = sess.application
|
|
172
|
+
klass = self.class
|
|
173
|
+
|
|
174
|
+
val = sess.get_property(prop, klass)
|
|
175
|
+
return val if val != nil
|
|
176
|
+
|
|
177
|
+
val = app.get_property(prop, klass)
|
|
178
|
+
return val if val != nil
|
|
179
|
+
|
|
180
|
+
val = sess.get_property(prop, nil)
|
|
181
|
+
return val if val != nil
|
|
182
|
+
|
|
183
|
+
val = app.get_property(prop, nil)
|
|
184
|
+
return val if val != nil
|
|
185
|
+
|
|
186
|
+
if defined?(@@properties)
|
|
187
|
+
val = @@properties[prop]
|
|
188
|
+
return val if val != nil
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
return nil
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# This is currently only used for describing which properties are required by
|
|
195
|
+
# the underlying component.
|
|
196
|
+
|
|
197
|
+
def self.uses_property(*args)
|
|
198
|
+
end
|
|
199
|
+
|
|
132
200
|
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require 'og'
|
|
2
|
+
|
|
3
|
+
class OgApplication < Wee::Application
|
|
4
|
+
attr_accessor :db
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class OgSession < Wee::Session
|
|
8
|
+
def awake
|
|
9
|
+
application.db.get_connection
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def sleep
|
|
13
|
+
application.db.put_connection
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class OgScaffolder < Wee::Component
|
|
18
|
+
def initialize(domain_class)
|
|
19
|
+
super()
|
|
20
|
+
@domain_class = domain_class
|
|
21
|
+
@attributes = domain_class.__props.map {|a| a.name}.reject {|a| a == 'oid'}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def delete(obj)
|
|
25
|
+
call Wee::MessageBox.new('Really delete?'), :confirm_delete, obj
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def confirm_delete(confirmed, obj)
|
|
29
|
+
if confirmed
|
|
30
|
+
@objs.delete(obj)
|
|
31
|
+
obj.delete!
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def edit(obj)
|
|
36
|
+
@edit = obj
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def save(obj)
|
|
40
|
+
obj.save!
|
|
41
|
+
@edit = nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def cancel
|
|
45
|
+
@objs.delete(@edit) if @edit and @edit.oid.nil?
|
|
46
|
+
@edit = nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def refresh
|
|
50
|
+
@objs = @domain_class.all || []
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def create
|
|
54
|
+
@objs << (@edit = @domain_class.new)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def render
|
|
58
|
+
refresh if @objs.nil?
|
|
59
|
+
|
|
60
|
+
r.h1 "#{ @domain_class } List"
|
|
61
|
+
r.anchor.callback { refresh }.with("Refresh")
|
|
62
|
+
|
|
63
|
+
r.form do
|
|
64
|
+
r.table.border(1).with {
|
|
65
|
+
|
|
66
|
+
r.table_row.with {
|
|
67
|
+
@attributes.each {|a|
|
|
68
|
+
r.table_header.with {
|
|
69
|
+
r.bold(a.capitalize)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
r.table_header.with(" ")
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@objs.each {|o|
|
|
76
|
+
r.table_row.with do
|
|
77
|
+
if @edit == o
|
|
78
|
+
|
|
79
|
+
@attributes.each { |attr|
|
|
80
|
+
r.table_data.with { r.text_input.callback {|v| o.send(attr+"=",v) }.value(o.send(attr)) }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
r.table_data.with {
|
|
84
|
+
r.submit_button.callback { save(o) }.value("Save")
|
|
85
|
+
r.space
|
|
86
|
+
r.submit_button.callback { cancel() }.value("Cancel")
|
|
87
|
+
r.space
|
|
88
|
+
r.anchor.callback { delete(o) }.with("Delete")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
else
|
|
92
|
+
|
|
93
|
+
@attributes.each { |attr|
|
|
94
|
+
r.table_data(o.send(attr))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
r.table_data.with {
|
|
98
|
+
r.anchor.callback { edit(o) }.with("Edit")
|
|
99
|
+
r.space
|
|
100
|
+
r.anchor.callback { delete(o) }.with("Delete")
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
r.anchor.callback { create() }.with("Add new #{ @domain_class }")
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
@@ -47,47 +47,151 @@ class Brush::GenericEncodedTextBrush < Brush
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
module Brush::ToCallback
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def to_callback(symbol, args, block)
|
|
54
|
+
raise ArgumentError if symbol and block
|
|
55
|
+
if symbol
|
|
56
|
+
Wee::LiteralMethodCallback.new(@canvas.current_component, symbol, *args)
|
|
57
|
+
else
|
|
58
|
+
raise ArgumentError if not args.empty?
|
|
59
|
+
block
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
50
64
|
class Brush::GenericTagBrush < Brush
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
|
|
66
|
+
def self.bool_attr(*attrs)
|
|
67
|
+
attrs.each { |a|
|
|
68
|
+
class_eval "
|
|
69
|
+
def #{ a }(bool=true)
|
|
70
|
+
if bool
|
|
71
|
+
@attributes['#{ a }'] = nil
|
|
72
|
+
else
|
|
73
|
+
@attributes.delete('#{ a }')
|
|
74
|
+
end
|
|
75
|
+
self
|
|
76
|
+
end
|
|
77
|
+
"
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.html_attr(*attrs)
|
|
82
|
+
attrs.each { |a|
|
|
83
|
+
class_eval "
|
|
84
|
+
def #{ a }(value)
|
|
85
|
+
html_attr('#{ a }', value)
|
|
86
|
+
end
|
|
87
|
+
"
|
|
88
|
+
}
|
|
55
89
|
end
|
|
56
90
|
|
|
57
|
-
|
|
58
|
-
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def html_attr(attr, value)
|
|
94
|
+
if value.nil?
|
|
95
|
+
@attributes.delete(attr)
|
|
96
|
+
else
|
|
97
|
+
@attributes[attr] = value.to_s
|
|
98
|
+
end
|
|
59
99
|
self
|
|
60
100
|
end
|
|
61
101
|
|
|
102
|
+
public
|
|
103
|
+
|
|
104
|
+
def method_missing(id, attr)
|
|
105
|
+
html_attr(id.to_s, attr)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def initialize(tag, is_single_tag=false)
|
|
109
|
+
super()
|
|
110
|
+
@tag, @is_single_tag = tag, is_single_tag
|
|
111
|
+
@attributes = Hash.new
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
html_attr :type, :id
|
|
115
|
+
|
|
62
116
|
def css_class(c)
|
|
63
|
-
|
|
64
|
-
self
|
|
117
|
+
html_attr("class", c)
|
|
65
118
|
end
|
|
66
119
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
120
|
+
include Brush::ToCallback
|
|
121
|
+
|
|
122
|
+
def onclick_callback(symbol=nil, *args, &block)
|
|
123
|
+
raise ArgumentError if symbol and block
|
|
124
|
+
url = @canvas.url_for_callback(to_callback(symbol, args, block))
|
|
125
|
+
onclick("javascript: document.location.href='#{ url }';")
|
|
70
126
|
end
|
|
71
127
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
128
|
+
# This method construct the css-class attribute by looking up the property
|
|
129
|
+
# from the current component.
|
|
130
|
+
|
|
131
|
+
def css_class_for(c)
|
|
132
|
+
prop = 'css.' + c
|
|
133
|
+
val = @canvas.current_component.lookup_property(prop)
|
|
134
|
+
raise "no property found for: <#{ prop }>" if val.nil?
|
|
135
|
+
css_class(val)
|
|
75
136
|
end
|
|
76
137
|
|
|
77
138
|
def with(text=nil, &block)
|
|
78
139
|
doc = @canvas.document
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
doc.
|
|
82
|
-
|
|
140
|
+
if @is_single_tag
|
|
141
|
+
raise ArgumentError if text or block
|
|
142
|
+
doc.single_tag(@tag, @attributes)
|
|
143
|
+
@closed = true
|
|
83
144
|
else
|
|
84
|
-
|
|
145
|
+
doc.start_tag(@tag, @attributes)
|
|
146
|
+
if text
|
|
147
|
+
doc.text(text)
|
|
148
|
+
super(text, &block)
|
|
149
|
+
else
|
|
150
|
+
super(&block)
|
|
151
|
+
end
|
|
152
|
+
doc.end_tag(@tag)
|
|
85
153
|
end
|
|
86
|
-
doc.end_tag(@tag)
|
|
87
154
|
nil
|
|
88
155
|
end
|
|
89
156
|
end
|
|
90
157
|
|
|
158
|
+
class Brush::GenericSingleTagBrush < Brush::GenericTagBrush
|
|
159
|
+
def initialize(tag)
|
|
160
|
+
super(tag, true)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
class Brush::ImageTag < Brush::GenericSingleTagBrush
|
|
165
|
+
html_attr :src
|
|
166
|
+
|
|
167
|
+
# This method construct the src attribute by looking up the property from the
|
|
168
|
+
# current component.
|
|
169
|
+
|
|
170
|
+
def src_for(s)
|
|
171
|
+
prop = "img." + s
|
|
172
|
+
val = @canvas.current_component.lookup_property(prop)
|
|
173
|
+
raise "no property found for: <#{ prop }>" if val.nil?
|
|
174
|
+
src(val)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def initialize
|
|
178
|
+
super("img")
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def with
|
|
182
|
+
super
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
class Brush::JavascriptTag < Brush::GenericTagBrush
|
|
187
|
+
html_attr :src, :type
|
|
188
|
+
|
|
189
|
+
def initialize
|
|
190
|
+
super("script")
|
|
191
|
+
type("text/javascript")
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
91
195
|
class Brush::TableTag < Brush::GenericTagBrush
|
|
92
196
|
def initialize
|
|
93
197
|
super('table')
|
|
@@ -100,19 +204,34 @@ class Brush::TableRowTag < Brush::GenericTagBrush
|
|
|
100
204
|
end
|
|
101
205
|
|
|
102
206
|
def align_top
|
|
103
|
-
|
|
104
|
-
self
|
|
207
|
+
html_attr('align', 'top')
|
|
105
208
|
end
|
|
106
209
|
|
|
107
|
-
def columns(*cols)
|
|
210
|
+
def columns(*cols, &block)
|
|
108
211
|
with {
|
|
109
|
-
cols.each {|col|
|
|
212
|
+
cols.each {|col|
|
|
213
|
+
@canvas.table_data.with {
|
|
214
|
+
if block
|
|
215
|
+
block.call(col)
|
|
216
|
+
else
|
|
217
|
+
@canvas.text(col)
|
|
218
|
+
end
|
|
219
|
+
}
|
|
220
|
+
}
|
|
110
221
|
}
|
|
111
222
|
end
|
|
112
223
|
|
|
113
|
-
def headings(*headers)
|
|
224
|
+
def headings(*headers, &block)
|
|
114
225
|
with {
|
|
115
|
-
headers.each {|
|
|
226
|
+
headers.each {|header|
|
|
227
|
+
@canvas.table_header.with {
|
|
228
|
+
if block
|
|
229
|
+
block.call(header)
|
|
230
|
+
else
|
|
231
|
+
@canvas.text(header)
|
|
232
|
+
end
|
|
233
|
+
}
|
|
234
|
+
}
|
|
116
235
|
}
|
|
117
236
|
end
|
|
118
237
|
|
|
@@ -130,52 +249,52 @@ class Brush::TableRowTag < Brush::GenericTagBrush
|
|
|
130
249
|
end
|
|
131
250
|
|
|
132
251
|
|
|
133
|
-
class Brush::InputTag < Brush::
|
|
252
|
+
class Brush::InputTag < Brush::GenericSingleTagBrush
|
|
134
253
|
def initialize
|
|
135
254
|
super('input')
|
|
136
255
|
end
|
|
137
256
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def #{ meth }(arg)
|
|
141
|
-
@attributes['#{ meth }'] = arg
|
|
142
|
-
self
|
|
143
|
-
end
|
|
144
|
-
]
|
|
145
|
-
end
|
|
257
|
+
html_attr :type, :name, :value, :size, :maxlength, :src
|
|
258
|
+
bool_attr :checked, :disabled, :readonly
|
|
146
259
|
|
|
147
260
|
def with
|
|
148
261
|
super
|
|
149
262
|
end
|
|
150
263
|
end
|
|
151
264
|
|
|
265
|
+
|
|
152
266
|
module Brush::InputCallbackMixin
|
|
153
267
|
public
|
|
154
268
|
|
|
155
|
-
def callback(symbol=nil, &block)
|
|
269
|
+
def callback(symbol=nil, *args, &block)
|
|
156
270
|
raise ArgumentError if symbol and block
|
|
157
|
-
|
|
158
|
-
name(@canvas.register_callback(:input, &block))
|
|
271
|
+
name(@canvas.register_callback(:input, to_callback(symbol, args, block)))
|
|
159
272
|
end
|
|
273
|
+
|
|
274
|
+
include Brush::ToCallback
|
|
160
275
|
end
|
|
161
276
|
|
|
162
277
|
module Brush::ActionCallbackMixin
|
|
163
278
|
public
|
|
164
279
|
|
|
165
|
-
def callback(symbol=nil, &block)
|
|
280
|
+
def callback(symbol=nil, *args, &block)
|
|
166
281
|
raise ArgumentError if symbol and block
|
|
167
|
-
|
|
168
|
-
name(@canvas.register_callback(:action, &block))
|
|
282
|
+
name(@canvas.register_callback(:action, to_callback(symbol, args, block)))
|
|
169
283
|
end
|
|
284
|
+
|
|
285
|
+
include Brush::ToCallback
|
|
170
286
|
end
|
|
171
287
|
|
|
172
288
|
# The callback id is listed in the URL (not as a form-data field)
|
|
173
289
|
module Brush::ActionURLCallbackMixin
|
|
174
290
|
public
|
|
175
291
|
|
|
176
|
-
def callback(symbol=nil, &block)
|
|
177
|
-
|
|
292
|
+
def callback(symbol=nil, *args, &block)
|
|
293
|
+
raise ArgumentError if symbol and block
|
|
294
|
+
__set_url(@canvas.url_for_callback(to_callback(symbol, args, block)))
|
|
178
295
|
end
|
|
296
|
+
|
|
297
|
+
include Brush::ToCallback
|
|
179
298
|
end
|
|
180
299
|
|
|
181
300
|
class Brush::TextAreaTag < Brush::GenericTagBrush
|
|
@@ -185,24 +304,8 @@ class Brush::TextAreaTag < Brush::GenericTagBrush
|
|
|
185
304
|
super('textarea')
|
|
186
305
|
end
|
|
187
306
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
def #{ meth }(arg)
|
|
191
|
-
@attributes['#{ meth }'] = arg
|
|
192
|
-
self
|
|
193
|
-
end
|
|
194
|
-
]
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def disabled
|
|
198
|
-
@attributes['disabled'] = nil
|
|
199
|
-
self
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def readonly
|
|
203
|
-
@attributes['readonly'] = nil
|
|
204
|
-
self
|
|
205
|
-
end
|
|
307
|
+
html_attr :name, :rows, :cols, :tabindex, :accesskey, :onfocus, :onblur, :onselect, :onchange
|
|
308
|
+
bool_attr :disabled, :readonly
|
|
206
309
|
|
|
207
310
|
def with(*args, &block)
|
|
208
311
|
super
|
|
@@ -214,14 +317,7 @@ class Brush::SelectOptionTag < Brush::GenericTagBrush
|
|
|
214
317
|
super('option')
|
|
215
318
|
end
|
|
216
319
|
|
|
217
|
-
|
|
218
|
-
if bool
|
|
219
|
-
@attributes['selected'] = nil
|
|
220
|
-
else
|
|
221
|
-
@attributes.delete('selected')
|
|
222
|
-
end
|
|
223
|
-
self
|
|
224
|
-
end
|
|
320
|
+
bool_attr :selected
|
|
225
321
|
end
|
|
226
322
|
|
|
227
323
|
class Brush::SelectListTag < Brush::GenericTagBrush
|
|
@@ -241,17 +337,13 @@ class Brush::SelectListTag < Brush::GenericTagBrush
|
|
|
241
337
|
]
|
|
242
338
|
end
|
|
243
339
|
|
|
244
|
-
|
|
245
|
-
@multiple = true
|
|
246
|
-
@attributes['multiple'] = nil
|
|
247
|
-
self
|
|
248
|
-
end
|
|
340
|
+
bool_attr :multiple
|
|
249
341
|
|
|
250
342
|
alias __old_callback callback
|
|
251
343
|
private :__old_callback
|
|
252
344
|
def callback(symbol=nil, &block)
|
|
253
345
|
raise ArgumentError if symbol and block
|
|
254
|
-
block = @canvas.current_component
|
|
346
|
+
block = Wee::LiteralMethodCallback.new(@canvas.current_component, symbol) unless block
|
|
255
347
|
|
|
256
348
|
@callback = block
|
|
257
349
|
self
|
|
@@ -268,7 +360,9 @@ class Brush::SelectListTag < Brush::GenericTagBrush
|
|
|
268
360
|
raise "invalid index in select list" if idx < 0 or idx > @items.size
|
|
269
361
|
@items[idx]
|
|
270
362
|
}
|
|
271
|
-
|
|
363
|
+
if choosen.size > 1 and not @attributes.has_key?('multiple')
|
|
364
|
+
raise "choosen more than one element from a non-multiple select list"
|
|
365
|
+
end
|
|
272
366
|
@callback.call(choosen)
|
|
273
367
|
}
|
|
274
368
|
end
|
|
@@ -277,7 +371,6 @@ class Brush::SelectListTag < Brush::GenericTagBrush
|
|
|
277
371
|
@items.each_index do |i|
|
|
278
372
|
@canvas.option.value(i).selected(@selected.include?(@items[i])).with(@labels[i])
|
|
279
373
|
end
|
|
280
|
-
@canvas.text("")
|
|
281
374
|
end
|
|
282
375
|
end
|
|
283
376
|
end
|
|
@@ -291,7 +384,7 @@ class Brush::TextInputTag < Brush::InputTag
|
|
|
291
384
|
end
|
|
292
385
|
end
|
|
293
386
|
|
|
294
|
-
class
|
|
387
|
+
class Brush::FileUploadTag < Brush::InputTag
|
|
295
388
|
include Brush::InputCallbackMixin
|
|
296
389
|
|
|
297
390
|
def initialize
|
|
@@ -318,7 +411,7 @@ end
|
|
|
318
411
|
# #value method. Note that it's neccessary to parse the passed form-fields and
|
|
319
412
|
# generate a "name" fields in the request, to make this image-button work.
|
|
320
413
|
|
|
321
|
-
class
|
|
414
|
+
class Brush::ImageButtonTag < Brush::InputTag
|
|
322
415
|
include Brush::ActionCallbackMixin
|
|
323
416
|
|
|
324
417
|
def initialize
|
|
@@ -338,8 +431,7 @@ class Brush::TableDataTag < Brush::GenericTagBrush
|
|
|
338
431
|
end
|
|
339
432
|
|
|
340
433
|
def align_top
|
|
341
|
-
|
|
342
|
-
self
|
|
434
|
+
html_attr('align', 'top')
|
|
343
435
|
end
|
|
344
436
|
end
|
|
345
437
|
|
|
@@ -358,15 +450,7 @@ class Brush::FormTag < Brush::GenericTagBrush
|
|
|
358
450
|
@attributes['method'] = 'POST'
|
|
359
451
|
end
|
|
360
452
|
|
|
361
|
-
|
|
362
|
-
@attributes['action'] = href
|
|
363
|
-
self
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
def enctype(typ)
|
|
367
|
-
@attributes['enctype'] = typ
|
|
368
|
-
self
|
|
369
|
-
end
|
|
453
|
+
html_attr :action, :enctype
|
|
370
454
|
|
|
371
455
|
alias __set_url action
|
|
372
456
|
|
|
@@ -387,19 +471,16 @@ class Brush::AnchorTag < Brush::GenericTagBrush
|
|
|
387
471
|
super('a')
|
|
388
472
|
end
|
|
389
473
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
end
|
|
394
|
-
alias href url
|
|
395
|
-
|
|
474
|
+
html_attr :href, :title
|
|
475
|
+
alias url href
|
|
476
|
+
alias tooltip title
|
|
396
477
|
alias __set_url url
|
|
397
478
|
end
|
|
398
479
|
|
|
399
480
|
|
|
400
481
|
class Brush::Page < Brush
|
|
401
|
-
def title(
|
|
402
|
-
@title =
|
|
482
|
+
def title(t)
|
|
483
|
+
@title = t
|
|
403
484
|
self
|
|
404
485
|
end
|
|
405
486
|
|