aurita-gui 0.3.1 → 0.3.2
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/TODO +3 -0
- data/aurita-gui.gemspec +1 -1
- data/lib/aurita-gui/element.rb +39 -3
- data/lib/aurita-gui/form.rb +135 -21
- data/lib/aurita-gui/form/form_field.rb +70 -38
- data/spec/form.rb +28 -0
- data/spec/html.rb +6 -0
- metadata +3 -2
data/TODO
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
- Implement <fieldset>
|
3
3
|
- Implement <optgroup>
|
4
4
|
|
5
|
+
- Fixme: Setting values only works after all elements have been added
|
6
|
+
(values won't be set for elements added after form.values=)
|
7
|
+
|
5
8
|
- Implement element.sibling[:dom_id] --> element
|
6
9
|
- Implement XPath1.0 method (parent, sibling, descendant, following ...)
|
7
10
|
|
data/aurita-gui.gemspec
CHANGED
@@ -14,7 +14,7 @@ as stand-alone library in any context (such as rails).
|
|
14
14
|
As there seems to be a lack of ruby form generators, i decided to release this
|
15
15
|
part of Aurita in a single gem with no dependencies.
|
16
16
|
EOF
|
17
|
-
s.version = '0.3.
|
17
|
+
s.version = '0.3.2'
|
18
18
|
s.author = 'Tobias Fuchs'
|
19
19
|
s.email = 'fuchs@atomnode.net'
|
20
20
|
s.date = Time.now
|
data/lib/aurita-gui/element.rb
CHANGED
@@ -42,6 +42,19 @@ module GUI
|
|
42
42
|
# by any derived class like Aurita::GUI::Form or
|
43
43
|
# Aurita::GUI::Table.
|
44
44
|
#
|
45
|
+
# == Notes
|
46
|
+
#
|
47
|
+
# Double-quotes in tag parameters will be escaped
|
48
|
+
# when rendering to string.
|
49
|
+
#
|
50
|
+
# e = Element.new(:onclick => 'alert("message");')
|
51
|
+
#
|
52
|
+
# The value of parameter :onclick does not change,
|
53
|
+
# but will be escaped when rendering:
|
54
|
+
#
|
55
|
+
# e.onclick == 'alert("message");'
|
56
|
+
# e.to_s == '<div onclick="alert(\"message\");"></div>'
|
57
|
+
#
|
45
58
|
class Element
|
46
59
|
|
47
60
|
@@element_count = 0
|
@@ -85,11 +98,11 @@ module GUI
|
|
85
98
|
|
86
99
|
# Return DOM id of this element.
|
87
100
|
def dom_id
|
88
|
-
@attrib[:id]
|
101
|
+
@attrib[:id] if @attrib
|
89
102
|
end
|
90
103
|
# Set DOM id of this element.
|
91
104
|
def dom_id=(value)
|
92
|
-
@attrib[:id] = value
|
105
|
+
@attrib[:id] = value if @attrib
|
93
106
|
end
|
94
107
|
|
95
108
|
# Render this element to a string and append another
|
@@ -168,7 +181,7 @@ module GUI
|
|
168
181
|
end
|
169
182
|
if !value.nil? then
|
170
183
|
value = value.to_s
|
171
|
-
attrib_string << ' ' << name.to_s + '="' << value + '"'
|
184
|
+
attrib_string << ' ' << name.to_s + '="' << value.gsub('"','\"') + '"'
|
172
185
|
end
|
173
186
|
}
|
174
187
|
|
@@ -188,6 +201,29 @@ module GUI
|
|
188
201
|
def each(&block)
|
189
202
|
@content.each(&block)
|
190
203
|
end
|
204
|
+
|
205
|
+
def css_classes
|
206
|
+
css_classes = @attrib[:class]
|
207
|
+
if css_classes.kind_of? Array
|
208
|
+
css_classes.flatten!
|
209
|
+
elsif css_classes.kind_of? String
|
210
|
+
css_classes = css_classes.split(' ')
|
211
|
+
else # e.g. Symbol
|
212
|
+
css_classes = [ css_classes ]
|
213
|
+
end
|
214
|
+
css_classes.collect { |c| c.to_sym if c }
|
215
|
+
return css_classes
|
216
|
+
end
|
217
|
+
|
218
|
+
def add_class(css_class_name)
|
219
|
+
@attrib[:class] = (css_classes << css_class_name.to_sym)
|
220
|
+
end
|
221
|
+
|
222
|
+
def remove_class(css_class_name)
|
223
|
+
classes = css_classes
|
224
|
+
classes.delete(css_class_name.to_sym)
|
225
|
+
@attrib[:class] = classes
|
226
|
+
end
|
191
227
|
|
192
228
|
end # class
|
193
229
|
|
data/lib/aurita-gui/form.rb
CHANGED
@@ -22,23 +22,114 @@ module Aurita
|
|
22
22
|
module GUI
|
23
23
|
|
24
24
|
|
25
|
+
# Default decorator for form fields.
|
26
|
+
# Decorates single entry of form to <li> element, setting CSS
|
27
|
+
# classes and DOM ids.
|
28
|
+
# To use your own field decorator, derive it from Aurita::GUI::Element
|
29
|
+
# (maybe indirectly via one of its derivates) and define its
|
30
|
+
# constructor to expect a single Form_Field instance.
|
31
|
+
# The field decorator has to wrap the actual form field.
|
32
|
+
#
|
33
|
+
# See the source code of Aurita::GUI::Form_Field_Wrapper for a
|
34
|
+
# simple implementation.
|
35
|
+
#
|
36
|
+
# Tell a form to use a specific field decorator by
|
37
|
+
#
|
38
|
+
# the_form.field_decorator = My_Field_Decorator
|
39
|
+
#
|
40
|
+
# To use your own implementation as defaut, overload Form.initialize
|
41
|
+
# like
|
42
|
+
#
|
43
|
+
# class My_Form < Aurita::GUI::Form
|
44
|
+
# def initialize(params={}, &block)
|
45
|
+
# super(params, &block)
|
46
|
+
# @field_decorator = My_Field_Decorator
|
47
|
+
# emd
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# Or write a factory (*hint hint*) like:
|
51
|
+
#
|
52
|
+
# class Form_Factory
|
53
|
+
# def self.form(params={}, &block)
|
54
|
+
# form = Aurita::GUI::Form.new(params, &block)
|
55
|
+
# form.field_decorator = My_Field_Decorator
|
56
|
+
# return form
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# See also: Form_Content_Wrapper (pretty much the same).
|
61
|
+
#
|
25
62
|
class Form_Field_Wrapper < Aurita::GUI::Element
|
26
63
|
attr_accessor :field
|
27
64
|
|
28
65
|
def initialize(field)
|
29
|
-
label_params =
|
30
|
-
|
31
|
-
|
32
|
-
|
66
|
+
label_params = false
|
67
|
+
if field.label then
|
68
|
+
label_params = { :for => field.dom_id, :force_closing_tag => true }
|
69
|
+
label_params[:id] = field.dom_id.to_s + '_label' if field.dom_id
|
70
|
+
label = field.label
|
71
|
+
@content = [ HTML.label(label_params) { label }, field ]
|
72
|
+
else
|
73
|
+
@content = field
|
74
|
+
end
|
75
|
+
css_classes = field.class.to_s.split('::')[-1].downcase + '_wrap form_field'
|
76
|
+
css_classes << ' required' if field.required?
|
77
|
+
css_classes << ' invalid' if field.invalid?
|
33
78
|
params = { :tag => :li,
|
34
79
|
:content => @content,
|
35
80
|
:id => field.dom_id + '_wrap',
|
36
|
-
:class =>
|
81
|
+
:class => css_classes }
|
37
82
|
super(params)
|
38
83
|
end
|
39
84
|
|
40
85
|
end
|
41
86
|
|
87
|
+
# Default decorator for form contents (list of form fields).
|
88
|
+
# Decorates all entries of form to <ul> element, setting CSS
|
89
|
+
# class 'form_field'.
|
90
|
+
# To use your own field decorator, derive it from Aurita::GUI::Element
|
91
|
+
# (maybe indirectly via one of its derivates) and define its
|
92
|
+
# constructor to expect a list of Form_Field instances as
|
93
|
+
# content attribute (either in params or as block).
|
94
|
+
# The content decorator has to wrap the actual array of form fields.
|
95
|
+
#
|
96
|
+
# See the source code of Aurita::GUI::Form_Content_Wrapper for a
|
97
|
+
# simple implementation.
|
98
|
+
#
|
99
|
+
# Tell a form to use a specific content decorator by
|
100
|
+
#
|
101
|
+
# the_form.content_decorator = My_Content_Decorator
|
102
|
+
#
|
103
|
+
# To use your own implementation as defaut, overload Form.initialize
|
104
|
+
# like
|
105
|
+
#
|
106
|
+
# class My_Form < Aurita::GUI::Form
|
107
|
+
# def initialize(params={}, &block)
|
108
|
+
# super(params, &block)
|
109
|
+
# @content_decorator = My_Content_Decorator
|
110
|
+
# emd
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# Or write a factory (*hint hint*) like:
|
114
|
+
#
|
115
|
+
# class Form_Factory
|
116
|
+
# def self.form(params={}, &block)
|
117
|
+
# form = Aurita::GUI::Form.new(params, &block)
|
118
|
+
# form.content_decorator = My_Content_Decorator
|
119
|
+
# return form
|
120
|
+
# end
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
# See also: Form_Field_Wrapper (pretty much the same).
|
124
|
+
#
|
125
|
+
class Form_Content_Wrapper < Aurita::GUI::Element
|
126
|
+
def initialize(params={}, &block)
|
127
|
+
params[:tag] = :ul
|
128
|
+
params[:class] = :form_fields
|
129
|
+
super(params, &block)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
42
133
|
# Usage examples:
|
43
134
|
#
|
44
135
|
# form = Form.new(:method => :put # default: :post
|
@@ -174,23 +265,43 @@ module GUI
|
|
174
265
|
#
|
175
266
|
# puts form.to_s
|
176
267
|
#
|
268
|
+
# === Further customization
|
269
|
+
#
|
270
|
+
# The default form decorators (Form_Field_Wrapper and
|
271
|
+
# Form_Content_Wrapper) do their best to guess DOM ids
|
272
|
+
# and CSS classes. In case you want to implement your
|
273
|
+
# own decorators - e.g. in case you don't want any
|
274
|
+
# 'guessed' CSS classes at all - you can overwrite them
|
275
|
+
# via
|
276
|
+
#
|
277
|
+
# the_form.field_decorator = My_Field_Decorator
|
278
|
+
#
|
279
|
+
# and
|
280
|
+
#
|
281
|
+
# the_form.content_decorator = My_Content_Decorator
|
282
|
+
#
|
283
|
+
# See documentation to Form_Field_Wrapper and
|
284
|
+
# Form_Content_Wrapper for instructions on how to
|
285
|
+
# implement custom form decorators.
|
177
286
|
#
|
178
287
|
class Form < Element
|
179
288
|
|
180
|
-
attr_accessor :method, :target, :action, :fields, :elements, :element_map, :values
|
289
|
+
attr_accessor :method, :target, :action, :fields, :elements, :element_map, :values, :field_decorator, :content_decorator
|
181
290
|
|
182
|
-
def initialize(params, &block)
|
183
|
-
@action
|
184
|
-
@method
|
185
|
-
@fields
|
186
|
-
@values
|
187
|
-
@method
|
188
|
-
@fields
|
189
|
-
@elements
|
190
|
-
@element_map
|
191
|
-
@values
|
192
|
-
@title
|
291
|
+
def initialize(params={}, &block)
|
292
|
+
@action = params[:action]
|
293
|
+
@method = params[:method]
|
294
|
+
@fields = params[:fields]
|
295
|
+
@values = params[:values]
|
296
|
+
@method ||= :post
|
297
|
+
@fields ||= []
|
298
|
+
@elements = []
|
299
|
+
@element_map = {}
|
300
|
+
@values ||= {}
|
301
|
+
@title = false
|
193
302
|
@custom_fields = false
|
303
|
+
@field_decorator = Aurita::GUI::Form_Field_Wrapper
|
304
|
+
@content_decorator = Aurita::GUI::Form_Content_Wrapper
|
194
305
|
if block_given? then
|
195
306
|
yield.each { |e| add(e) }
|
196
307
|
end
|
@@ -251,10 +362,12 @@ module GUI
|
|
251
362
|
# TODO: Should overwrite previous field element
|
252
363
|
# with same field name.
|
253
364
|
def add(form_field_element)
|
365
|
+
field_name = form_field_element.name.to_s
|
366
|
+
form_field_element.value = @values[field_name] unless form_field_element.value.to_s != ''
|
254
367
|
if !form_field_element.dom_id then
|
255
|
-
form_field_element.dom_id =
|
368
|
+
form_field_element.dom_id = field_name.gsub('.','_')
|
256
369
|
end
|
257
|
-
@element_map[
|
370
|
+
@element_map[field_name] = form_field_element
|
258
371
|
@elements << form_field_element
|
259
372
|
@content = false # Invalidate
|
260
373
|
end
|
@@ -342,7 +455,7 @@ module GUI
|
|
342
455
|
if element.kind_of? Aurita::GUI::Hidden_Field then
|
343
456
|
@content << element
|
344
457
|
else
|
345
|
-
@content <<
|
458
|
+
@content << @field_decorator.new(element)
|
346
459
|
end
|
347
460
|
end
|
348
461
|
}
|
@@ -353,7 +466,8 @@ module GUI
|
|
353
466
|
@content << element.to_hidden_field()
|
354
467
|
end
|
355
468
|
}
|
356
|
-
|
469
|
+
fields_id = dom_id().to_s+'_fields' if dom_id()
|
470
|
+
@content = @content_decorator.new(:id => fields_id) { @content }
|
357
471
|
return @content
|
358
472
|
end
|
359
473
|
|
@@ -6,12 +6,34 @@ require('aurita-gui/form/form_error')
|
|
6
6
|
module Aurita
|
7
7
|
module GUI
|
8
8
|
|
9
|
-
# Class Form_Field is an abstract base class for
|
10
|
-
#
|
9
|
+
# Class Form_Field is an abstract base class for built-in
|
10
|
+
# form fields (Input_Field, Hidden_Field,
|
11
11
|
# Radio_Field, Checkbox_Field, Select_Field,
|
12
12
|
# Textarea_Field) or any custom form field type.
|
13
|
-
# It is a wrapper for GUI::Element, extending it
|
14
|
-
#
|
13
|
+
# It is a wrapper for GUI::Element, extending it by
|
14
|
+
# parameters @name, @label and @value.
|
15
|
+
#
|
16
|
+
# Form_Field can be used directly as a decorator for any
|
17
|
+
# instance of Element.
|
18
|
+
# This is useful in case you want to add GUI component
|
19
|
+
# to a form that is not derived from Form_Field itself.
|
20
|
+
# To do so, pass an Element instance to the constructor's
|
21
|
+
# block.
|
22
|
+
# Note that in any case, a Form_Field instance requires
|
23
|
+
# the :name attribute, even if this doesn't make
|
24
|
+
# sense at first glance when not adding a 'real' form
|
25
|
+
# field. This is necessary as it could not be accessed
|
26
|
+
# after adding it to the form otherwise.
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
#
|
30
|
+
# button = Button.new(:onclick => 'submit();') { 'OK' }
|
31
|
+
# button_field = Form_Field.new(:name => :submit_button) { button }
|
32
|
+
# form.add(button_field)
|
33
|
+
#
|
34
|
+
#
|
35
|
+
# In common cases, you won't use Form_Field directly,
|
36
|
+
# but one of it's derivates.
|
15
37
|
#
|
16
38
|
# Usage:
|
17
39
|
#
|
@@ -65,20 +87,28 @@ module GUI
|
|
65
87
|
#
|
66
88
|
# i.editable!
|
67
89
|
#
|
90
|
+
# You can also store an expected data type in an Form_Field.
|
91
|
+
# This is just for convenience for e.g. form generators.
|
92
|
+
# So far, Form_Field@data_type won't be interpreted by
|
93
|
+
# any part of Aurita::GUI.
|
94
|
+
#
|
68
95
|
class Form_Field < Element
|
69
96
|
|
70
|
-
attr_accessor :type, :form, :label, :value, :required, :hidden
|
97
|
+
attr_accessor :type, :form, :label, :value, :required, :hidden, :data_type, :invalid, :hint
|
71
98
|
|
72
|
-
def initialize(params)
|
99
|
+
def initialize(params, &block)
|
73
100
|
# @value = params[:value]
|
74
101
|
raise Form_Error.new('Must provide parameter :name for ' << self.class.to_s) unless params[:name]
|
75
|
-
@form
|
76
|
-
@form
|
77
|
-
@label
|
102
|
+
@form = params[:parent]
|
103
|
+
@form ||= params[:form]
|
104
|
+
@label = params[:label]
|
78
105
|
# Get value from params unless set by derived constructor:
|
79
|
-
@value
|
80
|
-
@required
|
81
|
-
@hidden
|
106
|
+
@value = params[:value] unless @value
|
107
|
+
@required = params[:required]
|
108
|
+
@hidden = params[:hidden]
|
109
|
+
@data_type = params[:data_type]
|
110
|
+
@invalid = params[:invalid]
|
111
|
+
@hint = params[:hint]
|
82
112
|
# Do not delete parameter value, as it is a
|
83
113
|
# standard for <input> elements.
|
84
114
|
# Field types not supporting the value attribute
|
@@ -90,7 +120,14 @@ module GUI
|
|
90
120
|
params.delete(:label)
|
91
121
|
params.delete(:required)
|
92
122
|
params.delete(:hidden)
|
123
|
+
params.delete(:data_type)
|
124
|
+
params.delete(:invalid)
|
125
|
+
params.delete(:hint)
|
93
126
|
params[:parent] = @form
|
127
|
+
if block_given? then
|
128
|
+
@element = yield
|
129
|
+
params[:content] = @element
|
130
|
+
end
|
94
131
|
super(params)
|
95
132
|
end
|
96
133
|
|
@@ -103,7 +140,8 @@ module GUI
|
|
103
140
|
|
104
141
|
# Virtual method.
|
105
142
|
def element
|
106
|
-
raise Form_Error.new('Cannot render abstract class Form_Field')
|
143
|
+
raise Form_Error.new('Cannot render abstract class Form_Field') unless @element
|
144
|
+
@element
|
107
145
|
end
|
108
146
|
|
109
147
|
# Render this form field element to a
|
@@ -160,6 +198,25 @@ module GUI
|
|
160
198
|
end
|
161
199
|
end
|
162
200
|
|
201
|
+
# Mark field element as invalid (e.g. missing value).
|
202
|
+
def invalid!
|
203
|
+
@invalid = true
|
204
|
+
add_class(:invalid)
|
205
|
+
end
|
206
|
+
# Whether this field element is marked as invalid.
|
207
|
+
def invalid?
|
208
|
+
@invalid == true
|
209
|
+
end
|
210
|
+
# Set :invalid flag (true | false).
|
211
|
+
def invalid=(is_invalid)
|
212
|
+
@invalid = is_invalid
|
213
|
+
if is_invalid then
|
214
|
+
add_class(:invalid)
|
215
|
+
else
|
216
|
+
remove_class(:invalid)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
163
220
|
# Set field element to disabled mode.
|
164
221
|
# See Aurita::GUI::Form for more information
|
165
222
|
# on rendering modes.
|
@@ -225,31 +282,6 @@ module GUI
|
|
225
282
|
(@hidden == true)
|
226
283
|
end
|
227
284
|
|
228
|
-
protected
|
229
|
-
|
230
|
-
def css_classes
|
231
|
-
css_classes = @attrib[:class]
|
232
|
-
if css_classes.kind_of? Array
|
233
|
-
css_classes.flatten!
|
234
|
-
elsif css_classes.kind_of? String
|
235
|
-
css_classes = css_classes.split(' ')
|
236
|
-
else # e.g. Symbol
|
237
|
-
css_classes = [ css_classes ]
|
238
|
-
end
|
239
|
-
css_classes.collect { |c| c.to_sym if c }
|
240
|
-
return css_classes
|
241
|
-
end
|
242
|
-
|
243
|
-
def add_class(css_class_name)
|
244
|
-
@attrib[:class] = (css_classes << css_class_name.to_sym)
|
245
|
-
end
|
246
|
-
|
247
|
-
def remove_class(css_class_name)
|
248
|
-
classes = css_classes
|
249
|
-
classes.delete(css_class_name.to_sym)
|
250
|
-
@attrib[:class] = classes
|
251
|
-
end
|
252
|
-
|
253
285
|
end # class
|
254
286
|
|
255
287
|
|
data/spec/form.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
require('rubygems')
|
3
|
+
require('aurita-gui/form')
|
4
|
+
|
5
|
+
include Aurita::GUI
|
6
|
+
|
7
|
+
describe Aurita::GUI::Form, "basic rendering" do
|
8
|
+
before do
|
9
|
+
@form = Form.new()
|
10
|
+
@text_field = Input_Field.new(:name => :textfield)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should probvide method #add to add form fields" do
|
14
|
+
@form.add(@text_field)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should allow access to form fields by index" do
|
18
|
+
text_field = Input_Field.new(:name => :compare_me)
|
19
|
+
@form.add(text_field)
|
20
|
+
@form.elements[0].should == text_field
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should wrap form fields as list elements (<li>...</li>)" do
|
24
|
+
@form.add(@text_field)
|
25
|
+
@form.to_s.should == '<form><ul class="form_fields"><li class="input_field_wrap form_field" id="textfield_wrap"><input type="text" name="textfield" id="textfield" /></li></ul></form>'
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/spec/html.rb
CHANGED
@@ -36,4 +36,10 @@ describe Aurita::GUI::HTML, "basic rendering" do
|
|
36
36
|
@e.to_s.should == '<div class="outer"><h2 id="header">Header</h2><p id="content">Altered</p></div>'
|
37
37
|
end
|
38
38
|
|
39
|
+
it "should escape double-quotes in tag parameters" do
|
40
|
+
e = Element.new(:onclick => 'alert("message");')
|
41
|
+
e.onclick.should == 'alert("message");'
|
42
|
+
e.to_s.should == '<div onclick="alert(\"message\");"></div>'
|
43
|
+
end
|
44
|
+
|
39
45
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aurita-gui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Fuchs
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-20 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- lib/aurita-gui/form/input_field.rb
|
59
59
|
- lib/aurita-gui/form/date_field.rb
|
60
60
|
- spec/;
|
61
|
+
- spec/form.rb
|
61
62
|
- spec/html.rb
|
62
63
|
- spec/element.rb
|
63
64
|
has_rdoc: true
|