aurita-gui 0.2.0 → 0.3.0

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