aurita-gui 0.2.0 → 0.3.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/TODO +24 -0
- data/aurita-gui.gemspec +2 -2
- data/cheatsheet.rb +28 -0
- data/fieldtest.rb +64 -0
- data/lib/aurita-gui/element.rb +9 -7
- data/lib/aurita-gui/form.rb +167 -29
- data/lib/aurita-gui/form/form_field.rb +174 -10
- data/lib/aurita-gui/form/input_field.rb +1 -0
- data/lib/aurita-gui/form/textarea_field.rb +6 -4
- data/lib/aurita-gui/html.rb +199 -21
- data/valuetest.rb +50 -0
- metadata +5 -3
data/TODO
CHANGED
@@ -2,3 +2,27 @@
|
|
2
2
|
- Implement <fieldset>
|
3
3
|
- Implement <optgroup>
|
4
4
|
|
5
|
+
- Implement field visibility using
|
6
|
+
field.visible = true/false, wrapped in
|
7
|
+
def form.fields=(fields)
|
8
|
+
@element_map.each_pair { |fieldname, element|
|
9
|
+
unless fields.include?(fieldname)
|
10
|
+
@element_map[fieldname].visible = false
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
= DONE =============================================
|
16
|
+
|
17
|
+
- Decorate required fields.
|
18
|
+
Required fields are always rendered.
|
19
|
+
|
20
|
+
field = Text_Field.new(:required => true)
|
21
|
+
field.required = true | false
|
22
|
+
|
23
|
+
- Hide fields (render as hidden input field)
|
24
|
+
|
25
|
+
field = Text_Field.new(:hidden => true)
|
26
|
+
field.hidden = true
|
27
|
+
field.hide
|
28
|
+
field.show
|
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.
|
17
|
+
s.version = '0.3.0'
|
18
18
|
s.author = 'Tobias Fuchs'
|
19
19
|
s.email = 'fuchs@atomnode.net'
|
20
20
|
s.date = Time.now
|
@@ -29,7 +29,7 @@ part of Aurita in a single gem with no dependencies.
|
|
29
29
|
|
30
30
|
s.has_rdoc = true
|
31
31
|
s.rdoc_options << '--title' << 'Aurita::GUI' <<
|
32
|
-
'--main' << '
|
32
|
+
'--main' << 'Aurita::GUI::HTML' <<
|
33
33
|
'--line-numbers'
|
34
34
|
|
35
35
|
s.homepage = 'http://aurita.wortundform.de/'
|
data/cheatsheet.rb
CHANGED
@@ -12,6 +12,7 @@ include Aurita::GUI
|
|
12
12
|
# This is the most convenient way to build
|
13
13
|
# HTML using aurita-gui.
|
14
14
|
# (Thanks to oGMo for demanding more magic)
|
15
|
+
|
15
16
|
t1 = HTML.build {
|
16
17
|
div(:class => :css_class,
|
17
18
|
:onmouseover => "do_something_with(this);") {
|
@@ -25,6 +26,33 @@ t1 = HTML.build {
|
|
25
26
|
puts t1.to_s
|
26
27
|
puts '-----------------------------------------'
|
27
28
|
|
29
|
+
# Note that all method calls are redirected to
|
30
|
+
# class HTML, so this won't work as expected:
|
31
|
+
|
32
|
+
HTML.build {
|
33
|
+
div {
|
34
|
+
h2 { compute_string() }
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
# --> <compute_string />
|
39
|
+
# This is due to a class_eval restriction every
|
40
|
+
# builder struggles with at the moment.
|
41
|
+
# (There is mixico, but it is not portable).
|
42
|
+
#
|
43
|
+
# To come by this inconvenience, use, for
|
44
|
+
# example:
|
45
|
+
|
46
|
+
HTML.build {
|
47
|
+
div {
|
48
|
+
HTML.h2 { compute_string() }
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
# --> <div>computed string here</div>
|
53
|
+
# This works, as explicit calls to class methods
|
54
|
+
# of HTML are not rendered using class_eval.
|
55
|
+
|
28
56
|
# The previous example effectively does the
|
29
57
|
# following:
|
30
58
|
t2 = HTML.div(:class => :css_class,
|
data/fieldtest.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
require('rubygems')
|
3
|
+
require('aurita-gui')
|
4
|
+
require('test/unit/assertions')
|
5
|
+
|
6
|
+
include Test::Unit::Assertions
|
7
|
+
|
8
|
+
include Aurita::GUI
|
9
|
+
|
10
|
+
form = Form.new(:name => :the_form,
|
11
|
+
:id => :the_form_id,
|
12
|
+
:action => :where_to_send)
|
13
|
+
# You can either set all attributes in the
|
14
|
+
# constructor call ...
|
15
|
+
text = Input_Field.new(:name => :description,
|
16
|
+
:class => :the_css_class,
|
17
|
+
:label => 'Enter description',
|
18
|
+
:onfocus => "alert('input focussed');",
|
19
|
+
:value => 'some text')
|
20
|
+
# Or set them afterwards:
|
21
|
+
text.onblur = "alert('i lost focus :(');"
|
22
|
+
|
23
|
+
puts "\nDefault ---------------------------------\n"
|
24
|
+
puts text.to_s
|
25
|
+
puts "\nDisabled --------------------------------\n"
|
26
|
+
text.disable!
|
27
|
+
puts text.to_s
|
28
|
+
puts "\nEnabled ---------------------------------\n"
|
29
|
+
text.enable!
|
30
|
+
puts text.to_s
|
31
|
+
puts "\nReadonly --------------------------------\n"
|
32
|
+
text.readonly!
|
33
|
+
puts text.to_s
|
34
|
+
puts "\nEditable --------------------------------\n"
|
35
|
+
text.editable!
|
36
|
+
puts text.to_s
|
37
|
+
|
38
|
+
puts "\nTo hidden -------------------------------\n"
|
39
|
+
puts text.to_hidden_field.to_s
|
40
|
+
|
41
|
+
# Add it to the form:
|
42
|
+
form.add(text)
|
43
|
+
puts "\nThe Form --------------------------------\n"
|
44
|
+
|
45
|
+
# Access it again, via name:
|
46
|
+
assert_equal(form[:description], text)
|
47
|
+
# Or by using its index:
|
48
|
+
assert_equal(form[0], text)
|
49
|
+
|
50
|
+
# This is useful!
|
51
|
+
form[:description].value = 'change value'
|
52
|
+
|
53
|
+
checkbox = Checkbox_Field.new(:name => :enable_me,
|
54
|
+
:value => :foo,
|
55
|
+
:label => 'Check me',
|
56
|
+
:options => [ :foo, :bar ] )
|
57
|
+
form.add(checkbox)
|
58
|
+
form[:description].required = true
|
59
|
+
checkbox.required = true
|
60
|
+
form.fields = [ :description, :enable_me ]
|
61
|
+
form.delete_field(:enable_me)
|
62
|
+
puts form.to_s
|
63
|
+
|
64
|
+
|
data/lib/aurita-gui/element.rb
CHANGED
@@ -50,9 +50,11 @@ module GUI
|
|
50
50
|
|
51
51
|
def initialize(params={}, &block)
|
52
52
|
@@element_count += 1
|
53
|
-
@id
|
54
|
-
@parent
|
53
|
+
@id = @@element_count
|
54
|
+
@parent = params[:parent]
|
55
|
+
@force_close = params[:force_closing_tag]
|
55
56
|
params.delete(:parent)
|
57
|
+
params.delete(:force_closing_tag)
|
56
58
|
|
57
59
|
params[:tag] = :div if params[:tag].nil?
|
58
60
|
|
@@ -158,12 +160,12 @@ module GUI
|
|
158
160
|
end
|
159
161
|
}
|
160
162
|
|
161
|
-
if content.to_s != '' then
|
162
|
-
'<' << @tag.to_s << ' ' << attrib_string << '>' << "\n" <<
|
163
|
-
content.to_s +
|
164
|
-
'</' << @tag.to_s << '>'
|
163
|
+
if @force_close || content.to_s != '' then
|
164
|
+
'<' << @tag.to_s << ' ' << attrib_string << '>' << "\n " <<
|
165
|
+
content.to_s.gsub("\n","\n ") + "\n" <<
|
166
|
+
'</' << @tag.to_s << '>'
|
165
167
|
else
|
166
|
-
'<' << @tag.to_s << ' ' << attrib_string << '/>'
|
168
|
+
'<' << @tag.to_s << ' ' << attrib_string << '/>'
|
167
169
|
end
|
168
170
|
|
169
171
|
end
|
data/lib/aurita-gui/form.rb
CHANGED
@@ -27,7 +27,7 @@ module GUI
|
|
27
27
|
|
28
28
|
def initialize(field)
|
29
29
|
label_params = { :for => field.dom_id }
|
30
|
-
label_params[:id] = field.dom_id.to_s + '_label'
|
30
|
+
label_params[:id] = field.dom_id.to_s + '_label'
|
31
31
|
label = field.label
|
32
32
|
@content = [ HTML.label(label_params) { label }, field ]
|
33
33
|
params = { :tag => :li,
|
@@ -39,31 +39,146 @@ module GUI
|
|
39
39
|
|
40
40
|
end
|
41
41
|
|
42
|
+
# Usage examples:
|
43
|
+
#
|
44
|
+
# form = Form.new(:method => :put # default: :post
|
45
|
+
# :action => '/where/to/send/form/'
|
46
|
+
# :onsubmit => "alert('submitting');") {
|
47
|
+
# [
|
48
|
+
# Input_Field.new(:name => :description, :label => 'Description'),
|
49
|
+
# Select_Field.new(:name => :category, :label => 'Select category')
|
50
|
+
# ]
|
51
|
+
# }
|
52
|
+
# textarea = GUI::Textarea.new(:name => :comment, :label => 'Comment')
|
53
|
+
# form.add(textarea)
|
54
|
+
#
|
55
|
+
# In case you want to override the form action (default: /aurita/dispatch),
|
56
|
+
# use :action_url:
|
57
|
+
#
|
58
|
+
# Form.new(:action_url => '/where/to/send/form')
|
59
|
+
# or
|
60
|
+
# Form.action_url = '/where/to/send/form'
|
61
|
+
#
|
62
|
+
#
|
63
|
+
# == Render modes
|
64
|
+
#
|
65
|
+
# There are several ways to influence the rendering of a
|
66
|
+
# field.
|
67
|
+
# Available modes are:
|
68
|
+
#
|
69
|
+
# * editable: Default mode, opposite of readonly mode.
|
70
|
+
# * disabled: Set the disabled="disabled" attribute. Element will
|
71
|
+
# be rendered as input field, but can't be modified
|
72
|
+
# by the user.
|
73
|
+
# * readonly: Unlike in disabled mode, element will not be rendered
|
74
|
+
# as input field, but as a <div> containing the field's value.
|
75
|
+
# * required: Always render this field. If it is not included in the
|
76
|
+
# form's field configuration, render it as hidden field.
|
77
|
+
# * hidden: Render as hidden field.
|
78
|
+
#
|
79
|
+
# === Examples
|
80
|
+
#
|
81
|
+
# form = Form.new(:name => :the_form,
|
82
|
+
# :id => :the_form_id,
|
83
|
+
# :action => :where_to_send)
|
84
|
+
#
|
85
|
+
# You can either set all attributes in the
|
86
|
+
# constructor call ...
|
87
|
+
#
|
88
|
+
# text = Input_Field.new(:name => :description,
|
89
|
+
# :class => :the_css_class,
|
90
|
+
# :label => 'Enter description',
|
91
|
+
# :onfocus => "alert('input focussed');",
|
92
|
+
# :value => 'some text')
|
93
|
+
#
|
94
|
+
# Or set them afterwards:
|
95
|
+
#
|
96
|
+
# text.onblur = "alert('i lost focus :(');"
|
97
|
+
#
|
98
|
+
# Default mode:
|
99
|
+
#
|
100
|
+
# puts text.to_s
|
101
|
+
#
|
102
|
+
# Disabled mode:
|
103
|
+
#
|
104
|
+
# text.disable!
|
105
|
+
# puts text.to_s
|
106
|
+
#
|
107
|
+
# Re-enable:
|
108
|
+
#
|
109
|
+
# text.enable!
|
110
|
+
# puts text.to_s
|
111
|
+
#
|
112
|
+
# Readonly:
|
113
|
+
#
|
114
|
+
# text.readonly!
|
115
|
+
# puts text.to_s
|
116
|
+
#
|
117
|
+
# Back to editable:
|
118
|
+
#
|
119
|
+
# text.editable!
|
120
|
+
# puts text.to_s
|
121
|
+
#
|
122
|
+
# Render to hidden field:
|
123
|
+
#
|
124
|
+
# puts text.to_hidden_field.to_s
|
125
|
+
#
|
126
|
+
# Set to hidden (will only influence handling when
|
127
|
+
# rendered by a form):
|
128
|
+
#
|
129
|
+
# text.hidden = true
|
130
|
+
#
|
131
|
+
# Add it to the form:
|
132
|
+
#
|
133
|
+
# form.add(text)
|
134
|
+
#
|
135
|
+
# === Modifying form elements
|
136
|
+
#
|
137
|
+
# Access it again, by name:
|
138
|
+
#
|
139
|
+
# assert_equal(form[:description], text)
|
140
|
+
#
|
141
|
+
# Or by using its index:
|
142
|
+
#
|
143
|
+
# assert_equal(form[0], text)
|
144
|
+
#
|
145
|
+
# This is useful!
|
146
|
+
#
|
147
|
+
# form[:description].value = 'change value'
|
148
|
+
#
|
149
|
+
# checkbox = Checkbox_Field.new(:name => :enable_me,
|
150
|
+
# :value => :foo,
|
151
|
+
# :label => 'Check me',
|
152
|
+
# :options => [ :foo, :bar ] )
|
153
|
+
# form.add(checkbox)
|
154
|
+
#
|
155
|
+
# Modifying a field element *after* adding it to the
|
156
|
+
# form also works, as the form instance only references
|
157
|
+
# its form elements:
|
158
|
+
#
|
159
|
+
# checkbox.required = true
|
160
|
+
#
|
161
|
+
# The all form instance this checkbox has been added to
|
162
|
+
# now recognize it as a required field.
|
163
|
+
#
|
164
|
+
# form.fields = [ :description, :enable_me ]
|
165
|
+
# form.delete_field(:enable_me)
|
166
|
+
#
|
167
|
+
# And this is something i personally really like:
|
168
|
+
#
|
169
|
+
# form[:description].required = true
|
170
|
+
#
|
171
|
+
# Now, checkbox is not included in the form's field
|
172
|
+
# configuration, but as it is a required field, it
|
173
|
+
# will be rendered as hidden field.
|
174
|
+
#
|
175
|
+
# puts form.to_s
|
176
|
+
#
|
177
|
+
#
|
42
178
|
class Form < Element
|
43
179
|
|
44
180
|
attr_accessor :method, :target, :action, :fields, :elements, :element_map
|
45
181
|
|
46
|
-
# Usage examples:
|
47
|
-
#
|
48
|
-
# form = Form.new(:method => :put # default: :post
|
49
|
-
# :action => '/where/to/send/form/'
|
50
|
-
# :onsubmit => "alert('submitting');") {
|
51
|
-
# [
|
52
|
-
# Input_Field.new(:name => :description, :label => 'Description'),
|
53
|
-
# Select_Field.new(:name => :category, :label => 'Select category')
|
54
|
-
# ]
|
55
|
-
# }
|
56
|
-
# textarea = GUI::Textarea.new(:name => :comment, :label => 'Comment')
|
57
|
-
# form.add(textarea)
|
58
|
-
#
|
59
|
-
# In case you want to override the form action (default: /aurita/dispatch),
|
60
|
-
# use :action_url:
|
61
|
-
#
|
62
|
-
# Form.new(:action_url => '/where/to/send/form')
|
63
|
-
# or
|
64
|
-
# Form.action_url = '/where/to/send/form'
|
65
|
-
#
|
66
|
-
#
|
67
182
|
def initialize(params, &block)
|
68
183
|
@action = params[:action]
|
69
184
|
@method = params[:method]
|
@@ -160,6 +275,10 @@ module GUI
|
|
160
275
|
#
|
161
276
|
def values=(value_hash={})
|
162
277
|
@values = value_hash
|
278
|
+
@values.each_pair { |field_name, value|
|
279
|
+
element = @element_map[field_name.to_s]
|
280
|
+
element.value = value if element
|
281
|
+
}
|
163
282
|
end
|
164
283
|
alias set_values values=
|
165
284
|
|
@@ -179,9 +298,25 @@ module GUI
|
|
179
298
|
@element_map[field.name.to_s] = field
|
180
299
|
}
|
181
300
|
end
|
301
|
+
@fields.uniq!
|
182
302
|
return @fields
|
183
303
|
end
|
184
304
|
|
305
|
+
# Remove field with name=field_name from
|
306
|
+
# list of elements to be rendered in the form.
|
307
|
+
# The element will not be deleted from the form,
|
308
|
+
# so it can be enabled again using
|
309
|
+
#
|
310
|
+
# form.fields << :field_name
|
311
|
+
#
|
312
|
+
def delete_field(field_name)
|
313
|
+
if field_name.kind_of? Numeric then
|
314
|
+
@fields.delete_at(field_name)
|
315
|
+
else
|
316
|
+
@fields.delete(field_name.to_s)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
185
320
|
# Return underlying HTML element instance (HTML.ul),
|
186
321
|
# without wrapping HTML.form element.
|
187
322
|
def content
|
@@ -193,9 +328,7 @@ module GUI
|
|
193
328
|
fields().each { |field|
|
194
329
|
element = @element_map[field.to_s]
|
195
330
|
if element then
|
196
|
-
|
197
|
-
value ||= @values[element.name.to_s.intern]
|
198
|
-
element.value = value if value
|
331
|
+
element = element.to_hidden_field() if element.hidden?
|
199
332
|
if element.kind_of? Aurita::GUI::Hidden_Field then
|
200
333
|
@content << element
|
201
334
|
else
|
@@ -203,16 +336,21 @@ module GUI
|
|
203
336
|
end
|
204
337
|
end
|
205
338
|
}
|
206
|
-
|
207
|
-
|
339
|
+
# Render required field as hidden field if not
|
340
|
+
# included in form field config:
|
341
|
+
@elements.each { |element|
|
342
|
+
if !fields.include?(element.name.to_s) && element.required? then
|
343
|
+
@content << element.to_hidden_field()
|
344
|
+
end
|
345
|
+
}
|
346
|
+
@content = HTML.ul(:class => :form_fields) { @content }
|
208
347
|
return @content
|
209
348
|
end
|
210
349
|
|
211
350
|
# Render this form to an HTML.form instance.
|
212
351
|
# Wraps result of #content.
|
213
352
|
def element
|
214
|
-
|
215
|
-
HTML.form(@attrib) { cont }
|
353
|
+
HTML.form(@attrib) { content() }
|
216
354
|
end
|
217
355
|
|
218
356
|
# Render this form to a string
|
@@ -25,19 +25,60 @@ module GUI
|
|
25
25
|
# i.onclick = "alert('i have been clicked');"
|
26
26
|
# i.class = 'css_class'
|
27
27
|
#
|
28
|
+
# To indicate a required form field, set the :required flag:
|
29
|
+
#
|
30
|
+
# i = Input_Field.new(:required => true, :name => :description)
|
31
|
+
#
|
32
|
+
# Or
|
33
|
+
#
|
34
|
+
# i.required = true
|
35
|
+
#
|
36
|
+
# A required field will always be rendered, even
|
37
|
+
# if it is not included in the form field settings.
|
38
|
+
# In this case, it is rendered as hidden field.
|
39
|
+
#
|
40
|
+
# To force rendering a form element as hidden field,
|
41
|
+
# set the :hidden flag:
|
42
|
+
#
|
43
|
+
# i = Input_Field.new(:hidden => true, :name => :hide_me)
|
44
|
+
#
|
45
|
+
# Or
|
46
|
+
#
|
47
|
+
# i.hidden = true
|
48
|
+
#
|
49
|
+
# There is also a readonly render mode for form fields
|
50
|
+
# In readonly mode, a field element will be rendered as
|
51
|
+
# div element, containing the field value.
|
52
|
+
# This is useful for delete forms.
|
53
|
+
#
|
54
|
+
# i = Input_Field.new(:readonly => true, :name => :description)
|
55
|
+
#
|
56
|
+
# Or
|
57
|
+
#
|
58
|
+
# i.readonly = true # or i.readonly!
|
59
|
+
#
|
60
|
+
# And back to editable render mode:
|
61
|
+
#
|
62
|
+
# i.redonly = false
|
63
|
+
#
|
64
|
+
# Or
|
65
|
+
#
|
66
|
+
# i.editable!
|
28
67
|
#
|
29
68
|
class Form_Field < Element
|
30
69
|
|
31
|
-
attr_accessor :type, :form, :label, :value
|
70
|
+
attr_accessor :type, :form, :label, :value, :required, :hidden
|
32
71
|
|
33
72
|
def initialize(params)
|
34
73
|
# @value = params[:value]
|
35
74
|
raise Form_Error.new('Must provide parameter :name for ' << self.class.to_s) unless params[:name]
|
36
|
-
@form
|
37
|
-
@form
|
38
|
-
@label
|
75
|
+
@form = params[:parent]
|
76
|
+
@form ||= params[:form]
|
77
|
+
@label = params[:label]
|
39
78
|
# Get value from params unless set by derived constructor:
|
40
|
-
@value
|
79
|
+
@value = params[:value] unless @value
|
80
|
+
@required = params[:required]
|
81
|
+
@hidden = params[:hidden]
|
41
82
|
# Do not delete parameter value, as it is a
|
42
83
|
# standard for <input> elements.
|
43
84
|
# Field types not supporting the value attribute
|
@@ -47,47 +88,170 @@ module GUI
|
|
47
88
|
params.delete(:form)
|
48
89
|
params.delete(:parent)
|
49
90
|
params.delete(:label)
|
91
|
+
params.delete(:required)
|
92
|
+
params.delete(:hidden)
|
50
93
|
params[:parent] = @form
|
51
94
|
super(params)
|
52
95
|
end
|
53
96
|
|
97
|
+
=begin
|
54
98
|
def form=(form_instance)
|
55
99
|
@form = form_instance
|
56
100
|
@params[:parent] = @form
|
57
101
|
end
|
102
|
+
=end
|
58
103
|
|
104
|
+
# Virtual method.
|
59
105
|
def element
|
60
106
|
raise Form_Error.new('Cannot render abstract class Form_Field')
|
61
107
|
end
|
108
|
+
|
109
|
+
# Render this form field element to a
|
110
|
+
# readonly element.
|
111
|
+
# Will not affect this element instance.
|
62
112
|
def readonly_element
|
113
|
+
# Todo: Add CSS classes 'readonly' and self.class
|
63
114
|
HTML.div(@attrib) { @value }
|
64
115
|
end
|
65
116
|
|
117
|
+
# Render this form field element to a
|
118
|
+
# Hidden_Field instance. Will not affect
|
119
|
+
# this element instance.
|
120
|
+
def to_hidden_field
|
121
|
+
Hidden_Field.new(:type => :hidden,
|
122
|
+
:name => @attrib[:name],
|
123
|
+
:id => dom_id.to_s,
|
124
|
+
:value => @value)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Render this form field element to string.
|
66
128
|
def to_s
|
67
129
|
return element().string unless @readonly
|
68
130
|
return readonly_element().string
|
69
131
|
end
|
70
132
|
alias string to_s
|
71
133
|
|
134
|
+
# Set field element to editable mode.
|
135
|
+
# See Aurita::GUI::Form for more information
|
136
|
+
# on rendering modes.
|
72
137
|
def editable!
|
73
|
-
@
|
138
|
+
@readonly = false
|
139
|
+
remove_class(:readonly)
|
74
140
|
end
|
141
|
+
|
142
|
+
# Set field element to readonly mode.
|
143
|
+
# See Aurita::GUI::Form for more information
|
144
|
+
# on rendering modes.
|
75
145
|
def readonly!
|
76
|
-
@attrib[:class] = @attrib[:class].to_s << ' readonly'
|
77
146
|
@readonly = true
|
147
|
+
add_class(:readonly)
|
78
148
|
end
|
149
|
+
# Whether this field element is in readonly mode.
|
79
150
|
def readonly?
|
80
151
|
@readonly
|
81
152
|
end
|
153
|
+
# Set :readonly flag (true | false).
|
154
|
+
def readonly=(is_readonly)
|
155
|
+
@readonly = is_readonly
|
156
|
+
if is_readonly then
|
157
|
+
add_class(:readonly)
|
158
|
+
else
|
159
|
+
remove_class(:readonly)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Set field element to disabled mode.
|
164
|
+
# See Aurita::GUI::Form for more information
|
165
|
+
# on rendering modes.
|
82
166
|
def disable!
|
83
167
|
@attrib[:disabled] = true
|
168
|
+
add_class(:disabled)
|
84
169
|
end
|
170
|
+
# Set field element to enabled mode (default).
|
171
|
+
# See Aurita::GUI::Form for more information
|
172
|
+
# on rendering modes.
|
85
173
|
def enable!
|
86
174
|
@attrib.delete(:disabled)
|
175
|
+
remove_class(:disabled)
|
176
|
+
end
|
177
|
+
def disabled=(is_disabled)
|
178
|
+
@disabled = is_disabled
|
179
|
+
if is_disabled then
|
180
|
+
add_class(:disabled)
|
181
|
+
else
|
182
|
+
remove_class(:disabled)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Set :required flag (true | false).
|
187
|
+
def required=(is_required)
|
188
|
+
@required = is_required
|
189
|
+
if is_required then
|
190
|
+
add_class(:required)
|
191
|
+
else
|
192
|
+
remove_class(:required)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Set field element to required mode.
|
197
|
+
# See Aurita::GUI::Form for more information
|
198
|
+
# on rendering modes.
|
199
|
+
def required!
|
200
|
+
@required = true
|
201
|
+
add_class(:required)
|
202
|
+
end
|
203
|
+
# Set field element to optional mode (default).
|
204
|
+
def optional!
|
205
|
+
@required = false
|
206
|
+
remove_class(:required)
|
207
|
+
end
|
208
|
+
# Whether this field element is a required field.
|
209
|
+
def required?
|
210
|
+
(@required == true)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Set hidden flag for this element.
|
214
|
+
# See Aurita::GUI::Form for more information
|
215
|
+
# on rendering modes.
|
216
|
+
def hide!
|
217
|
+
@hidden = true
|
218
|
+
end
|
219
|
+
# Remove :hidden flag from this element.
|
220
|
+
def show!
|
221
|
+
@hidden = false
|
222
|
+
end
|
223
|
+
# Whether this field element is hidden.
|
224
|
+
def hidden?
|
225
|
+
(@hidden == true)
|
226
|
+
end
|
227
|
+
|
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
|
87
251
|
end
|
88
252
|
|
89
|
-
end
|
253
|
+
end # class
|
90
254
|
|
91
255
|
|
92
|
-
end
|
93
|
-
end
|
256
|
+
end # module
|
257
|
+
end # module
|
@@ -8,13 +8,15 @@ module GUI
|
|
8
8
|
def initialize(params, &block)
|
9
9
|
params[:tag] = :textarea
|
10
10
|
# Move value parameter to @content:
|
11
|
-
@
|
11
|
+
@value = params[:value]
|
12
|
+
super(params)
|
12
13
|
params.delete(:value)
|
13
|
-
|
14
|
-
@value = @content
|
14
|
+
@value = yield.to_s if block_given?
|
15
15
|
end
|
16
16
|
def element
|
17
|
-
|
17
|
+
# Always close <textarea> tags!
|
18
|
+
@attrib[:force_closing_tag] = true
|
19
|
+
HTML.textarea(@attrib) { @value.to_s }
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
data/lib/aurita-gui/html.rb
CHANGED
@@ -4,34 +4,212 @@ require('aurita-gui/element')
|
|
4
4
|
module Aurita
|
5
5
|
module GUI
|
6
6
|
|
7
|
-
#
|
8
|
-
# Aurita::GUI::Element. Almost every class method
|
9
|
-
# is redirected to generate a correspoding
|
10
|
-
# Element instance.
|
7
|
+
# == About
|
11
8
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# For tags without enclosed content (i.e. without
|
15
|
-
# closing tag):
|
9
|
+
# Aurita::GUI is a library for convenient, simple
|
10
|
+
# HTML generation for web applications.
|
16
11
|
#
|
17
|
-
#
|
18
|
-
#
|
12
|
+
# It is a stand-alone library isolated from the
|
13
|
+
# Aurita Web Application Framework, where Aurita::GUI
|
14
|
+
# is used to support design of OO-accessible GUI
|
15
|
+
# elements.
|
19
16
|
#
|
20
|
-
#
|
21
|
-
#
|
17
|
+
# Other than other builder implementations (there
|
18
|
+
# are many), Aurita::GUI is not just a collection
|
19
|
+
# of template helpers. It is data persistent and
|
20
|
+
# maintains object hierarchies.
|
21
|
+
# That is: The HTML hierarchy you build is not just
|
22
|
+
# rendered to a string - you can access and modify a
|
23
|
+
# generated HTML hierarchy before rendering it.
|
22
24
|
#
|
23
|
-
#
|
25
|
+
# This is especially useful (and necessary) when
|
26
|
+
# generating forms.
|
24
27
|
#
|
25
|
-
#
|
28
|
+
# Aurita::GUI is designed to be especially useful
|
29
|
+
# for automated form generation (Lore ORM uses it
|
30
|
+
# to generate forms for models).
|
26
31
|
#
|
27
|
-
#
|
32
|
+
# Of course there is also Aurita::GUI::Template_Helper
|
33
|
+
# for templates, but this is just one possible
|
34
|
+
# implementation that wraps common tasks in methods.
|
35
|
+
# You can easily write your own template helpers
|
36
|
+
# and use them e.g. in Rails, Merb or Ramaze projects.
|
28
37
|
#
|
29
|
-
# HTML.a(:href => 'http://domain.com') { 'click me' }
|
30
|
-
# # --> '<a href="http://domain.com">click me</a>'
|
31
38
|
#
|
32
|
-
|
33
|
-
|
34
|
-
|
39
|
+
# Aurita::GUI::HTML is a convenient factory for
|
40
|
+
# Aurita::GUI::Element, the base class to almost
|
41
|
+
# every instance this library generates.
|
42
|
+
# HTML's class methods are redirected to generate a
|
43
|
+
# correspoding Element instance.
|
44
|
+
#
|
45
|
+
# It implements an object-oriented, minimalistic
|
46
|
+
# generator for HTML code.
|
47
|
+
# For tags without enclosed content (i.e. without
|
48
|
+
# closing tag):
|
49
|
+
#
|
50
|
+
# HTML.br
|
51
|
+
# # --> '<br />'
|
52
|
+
#
|
53
|
+
# HTML.hr(:class => 'divide')
|
54
|
+
# # --> '<hr class="divide" />'
|
55
|
+
#
|
56
|
+
# This is effectively a wrapper for
|
57
|
+
#
|
58
|
+
# Element.new(:tag => :hr, :class => 'divide')
|
59
|
+
#
|
60
|
+
# Enclosed content is passed in a block:
|
61
|
+
#
|
62
|
+
# HTML.a(:href => 'http://domain.com') { 'click me' }
|
63
|
+
# # --> '<a href="http://domain.com">click me</a>'
|
64
|
+
#
|
65
|
+
# Or as a constructor parameter:
|
66
|
+
#
|
67
|
+
# HTML.a(:href => 'http://domain.com', :content => 'click me')
|
68
|
+
#
|
69
|
+
# == Further Examples
|
70
|
+
#
|
71
|
+
# There are some few usage principles that are
|
72
|
+
# consistent for every class of Aurita::GUI.
|
73
|
+
# One of them: If a parameter can be passed as constructor
|
74
|
+
# argument, there are also getter and setter methods
|
75
|
+
# for this parameter:
|
76
|
+
#
|
77
|
+
# d = HTML.div { 'the content' }
|
78
|
+
# d.content = 'i changed the content'
|
79
|
+
# d.onclick = "alert('you clicked me');"
|
80
|
+
#
|
81
|
+
#
|
82
|
+
# === The basics
|
83
|
+
#
|
84
|
+
# This is the most convenient way to build
|
85
|
+
# HTML using aurita-gui.
|
86
|
+
# (Thanks to oGMo for demanding more magic)
|
87
|
+
#
|
88
|
+
# t1 = HTML.build {
|
89
|
+
# div(:class => :css_class,
|
90
|
+
# :onmouseover => "do_something_with(this);") {
|
91
|
+
# ul(:id => :the_list) {
|
92
|
+
# li(:class => :first) { 'foo' } +
|
93
|
+
# li(:class => :second) { 'bar' } +
|
94
|
+
# li(:class => :third) { 'batz' }
|
95
|
+
# }
|
96
|
+
# }
|
97
|
+
# }
|
98
|
+
# puts t1.to_s
|
99
|
+
#
|
100
|
+
# Note that all method calls are redirected to
|
101
|
+
# class HTML, so this won't work as expected:
|
102
|
+
#
|
103
|
+
# HTML.build {
|
104
|
+
# div {
|
105
|
+
# h2 { compute_string() }
|
106
|
+
# }
|
107
|
+
# }.to_s
|
108
|
+
#
|
109
|
+
# --> <div><h2><compute_string /></h2></div>
|
110
|
+
#
|
111
|
+
# This is due to a class_eval restriction every
|
112
|
+
# builder struggles with at the moment.
|
113
|
+
# (There is mixico, but it is not portable).
|
114
|
+
#
|
115
|
+
# To come by this inconvenience, use, for
|
116
|
+
# example:
|
117
|
+
#
|
118
|
+
# HTML.build {
|
119
|
+
# div {
|
120
|
+
# HTML.h2 { compute_string() }
|
121
|
+
# }
|
122
|
+
# }.to_s
|
123
|
+
#
|
124
|
+
# --> <div><h2>computed string here</h2></div>
|
125
|
+
#
|
126
|
+
# This works, as explicit calls to class methods
|
127
|
+
# of HTML are not rendered using class_eval.
|
128
|
+
#
|
129
|
+
# The previous example effectively does the
|
130
|
+
# following:
|
131
|
+
#
|
132
|
+
# t2 = HTML.div(:class => :css_class,
|
133
|
+
# :onmouseover => "do_something_with(this);") {
|
134
|
+
# HTML.ul(:id => :the_list) {
|
135
|
+
# HTML.li(:class => :first) { 'foo' } +
|
136
|
+
# HTML.li(:class => :second) { 'bar' } +
|
137
|
+
# HTML.li(:class => :third) { 'batz' }
|
138
|
+
# }
|
139
|
+
# }
|
140
|
+
# assert_equal(t1.to_s, t2.to_s)
|
141
|
+
#
|
142
|
+
# Element is not a full Enumerable implementation (yet),
|
143
|
+
# but it offers random access operators ...
|
144
|
+
#
|
145
|
+
# assert_equal(t1[0].tag, :ul) # First element of div is <ul>
|
146
|
+
#
|
147
|
+
# t1[0][1] = HTML.li(:class => :changed) { 'wombat' }
|
148
|
+
#
|
149
|
+
# ... as well as #each ...
|
150
|
+
#
|
151
|
+
# t1[0].each { |element|
|
152
|
+
# element.id = 'each_change'
|
153
|
+
# }
|
154
|
+
#
|
155
|
+
# ... empty? and length. More to come in future releases.
|
156
|
+
#
|
157
|
+
# assert_equal(t1[0].length, 3) # List has 3 entries
|
158
|
+
# assert_equal(t1[0].empty?, false) # List has 3 entries
|
159
|
+
#
|
160
|
+
#
|
161
|
+
# === Form builder
|
162
|
+
#
|
163
|
+
# form = Form.new(:name => :the_form,
|
164
|
+
# :id => :the_form_id,
|
165
|
+
# :action => :where_to_send)
|
166
|
+
#
|
167
|
+
# You can either set all attributes in the
|
168
|
+
# constructor call ...
|
169
|
+
#
|
170
|
+
# text = Input_Field.new(:name => :description,
|
171
|
+
# :class => :the_css_class,
|
172
|
+
# :onfocus => "alert('input focussed');",
|
173
|
+
# :value => 'some text')
|
174
|
+
# Or set them afterwards:
|
175
|
+
#
|
176
|
+
# text.onblur = "alert('i lost focus :(');"
|
177
|
+
#
|
178
|
+
# Enable / disable:
|
179
|
+
#
|
180
|
+
# text.disable!
|
181
|
+
# text.enable!
|
182
|
+
#
|
183
|
+
# Set an element to readonly mode (display value only):
|
184
|
+
# text.readonly!
|
185
|
+
#
|
186
|
+
# And back to editable mode:
|
187
|
+
#
|
188
|
+
# text.editable!
|
189
|
+
#
|
190
|
+
# Add it to the form:
|
191
|
+
# form.add(text)
|
192
|
+
#
|
193
|
+
# Access it again, via name:
|
194
|
+
#
|
195
|
+
# assert_equal(form[:description], text)
|
196
|
+
#
|
197
|
+
# Or by using its index:
|
198
|
+
#
|
199
|
+
# assert_equal(form[0], text)
|
200
|
+
#
|
201
|
+
# This is useful!
|
202
|
+
#
|
203
|
+
# form[:description].value = 'change value'
|
204
|
+
#
|
205
|
+
# checkbox = Checkbox_Field.new(:name => :enable_me,
|
206
|
+
# :value => :foo,
|
207
|
+
# :label => 'Check me',
|
208
|
+
# :options => [ :foo, :bar ] )
|
209
|
+
# form.add(checkbox)
|
210
|
+
#
|
211
|
+
# puts form.to_s
|
212
|
+
#
|
35
213
|
class HTML
|
36
214
|
|
37
215
|
# Statically defined as <br /> must not have any attributes.
|
@@ -43,7 +221,6 @@ module GUI
|
|
43
221
|
raise ::Exception.new('Missing attributes for HTML.' << meth_name.inspect) unless attrib_hash
|
44
222
|
attrib_hash[:tag] = meth_name
|
45
223
|
cont = yield if block_given?
|
46
|
-
# cont = self.class_eval(&block)
|
47
224
|
attrib_hash[:content] = cont
|
48
225
|
Element.new(attrib_hash)
|
49
226
|
end
|
@@ -70,6 +247,7 @@ module GUI
|
|
70
247
|
end
|
71
248
|
|
72
249
|
=begin
|
250
|
+
XHTML_TAGS = [ :html, :div, :p, :input, :select, :option, :ul, :ol, :li ]
|
73
251
|
for t in XHTML_TAGS do
|
74
252
|
meth = <<EOC
|
75
253
|
def self.#{t.to_s}(attribs=nil, &block)
|
data/valuetest.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
require('rubygems')
|
3
|
+
require('aurita-gui')
|
4
|
+
require('test/unit/assertions')
|
5
|
+
|
6
|
+
include Test::Unit::Assertions
|
7
|
+
|
8
|
+
include Aurita::GUI
|
9
|
+
|
10
|
+
form = Form.new(:name => :the_form,
|
11
|
+
:id => :the_form_id,
|
12
|
+
:action => :where_to_send)
|
13
|
+
# You can either set all attributes in the
|
14
|
+
# constructor call ...
|
15
|
+
text = Input_Field.new(:name => :description,
|
16
|
+
:class => :the_css_class)
|
17
|
+
|
18
|
+
# Enable / disable:
|
19
|
+
form.add(text)
|
20
|
+
|
21
|
+
checkbox = Checkbox_Field.new(:name => :enable_me,
|
22
|
+
:label => 'Check me',
|
23
|
+
:options => [ :foo, :bar ] )
|
24
|
+
form.add(checkbox)
|
25
|
+
|
26
|
+
textarea = Textarea_Field.new(:name => :message,
|
27
|
+
:label => 'Tell me something',
|
28
|
+
:value => 'Dear Sir ...')
|
29
|
+
form.add(textarea)
|
30
|
+
# You also can change values after adding them to the form:
|
31
|
+
textarea.value.gsub!('Sir','Madam')
|
32
|
+
|
33
|
+
# Finally. form.values=(hash) replaces form values:
|
34
|
+
form.values = { :enable_me => :foo, :description => 'The description' }
|
35
|
+
|
36
|
+
puts form.to_s
|
37
|
+
|
38
|
+
assert_equal(form[0].value, 'The description')
|
39
|
+
assert_equal(form[1].value, :foo)
|
40
|
+
|
41
|
+
h = HTML.build {
|
42
|
+
p(:class => :oaragraph) {
|
43
|
+
div(:id => :content) {
|
44
|
+
'Here is text'
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
p h[0].content = 'Bla'
|
50
|
+
puts h.to_s
|
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.
|
4
|
+
version: 0.3.0
|
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-13 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -22,6 +22,7 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
+
- fieldtest.rb
|
25
26
|
- cheatsheet.rb
|
26
27
|
- History.txt
|
27
28
|
- lib
|
@@ -29,6 +30,7 @@ files:
|
|
29
30
|
- bin
|
30
31
|
- TODO
|
31
32
|
- test
|
33
|
+
- valuetest.rb
|
32
34
|
- LICENSE
|
33
35
|
- lib/aurita-gui
|
34
36
|
- lib/aurita-gui.rb
|
@@ -64,7 +66,7 @@ rdoc_options:
|
|
64
66
|
- --title
|
65
67
|
- Aurita::GUI
|
66
68
|
- --main
|
67
|
-
-
|
69
|
+
- Aurita::GUI::HTML
|
68
70
|
- --line-numbers
|
69
71
|
require_paths:
|
70
72
|
- lib
|