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 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.2.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' << './cheatsheet.rb' <<
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
+
@@ -50,9 +50,11 @@ module GUI
50
50
 
51
51
  def initialize(params={}, &block)
52
52
  @@element_count += 1
53
- @id = @@element_count
54
- @parent = params[: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 << '>' << "\n"
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 << '/>' << "\n"
168
+ '<' << @tag.to_s << ' ' << attrib_string << '/>'
167
169
  end
168
170
 
169
171
  end
@@ -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
- value = @values[element.name.to_s]
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
- cont = @content
207
- @content = HTML.ul(:class => :form_fields) { cont }
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
- cont = content()
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 = params[:parent]
37
- @form ||= params[:form]
38
- @label = params[: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 = params[:value] unless @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
- @reaonly = false
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
@@ -31,6 +31,7 @@ module GUI
31
31
  super(params)
32
32
  end
33
33
  def element
34
+ @attrib[:value] = @value
34
35
  HTML.input(@attrib)
35
36
  end
36
37
  end
@@ -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
- @content = params[:value]
11
+ @value = params[:value]
12
+ super(params)
12
13
  params.delete(:value)
13
- super(params, &block)
14
- @value = @content
14
+ @value = yield.to_s if block_given?
15
15
  end
16
16
  def element
17
- HTML.textarea(@attrib) { @value }
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
 
@@ -4,34 +4,212 @@ require('aurita-gui/element')
4
4
  module Aurita
5
5
  module GUI
6
6
 
7
- # Aurita::GUI::HTML is a convenient factory for
8
- # Aurita::GUI::Element. Almost every class method
9
- # is redirected to generate a correspoding
10
- # Element instance.
7
+ # == About
11
8
  #
12
- # It implements an object-oriented, minimalistic
13
- # generator for HTML code.
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
- # HTML.br
18
- # # --> '<br />'
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
- # HTML.hr(:class => 'divide')
21
- # # --> '<hr class="divide" />'
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
- # This is effectively a wrapper for
25
+ # This is especially useful (and necessary) when
26
+ # generating forms.
24
27
  #
25
- # Element.new(:tag => :hr, :class => 'divide')
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
- # Enclosed content is passed in a block:
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
- XHTML_TAGS = [ :html, :div, :p, :input, :select, :option, :ul, :ol, :li ]
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.2.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 00:00:00 +01:00
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
- - ./cheatsheet.rb
69
+ - Aurita::GUI::HTML
68
70
  - --line-numbers
69
71
  require_paths:
70
72
  - lib