aurita-gui 0.3.4 → 0.3.5

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
@@ -5,7 +5,6 @@
5
5
  - Fixme: Setting values only works after all elements have been added
6
6
  (values won't be set for elements added after form.values=)
7
7
 
8
- - Implement element.sibling[:dom_id] --> element
9
8
  - Implement XPath1.0 method (parent, sibling, descendant, following ...)
10
9
 
11
10
  - Implement field visibility using
@@ -20,6 +19,11 @@
20
19
 
21
20
  = DONE =============================================
22
21
 
22
+ - Element should implement / delegate to Array,
23
+ so it can be used like any container.
24
+
25
+ - Implement element.sibling[:dom_id] --> element
26
+
23
27
  - Provide markaby-like syntax, Example:
24
28
 
25
29
  HTML.div 'content here' :class => :highlight
@@ -27,7 +31,7 @@
27
31
  and
28
32
 
29
33
  HTML.build {
30
- div 'content' {
34
+ div.header {
31
35
  h1 'header'
32
36
  }
33
37
  }
@@ -14,7 +14,7 @@ as stand-alone library in any context (such as rails).
14
14
  As there seems to be a lack of ruby form generators, i decided to release this
15
15
  part of Aurita in a single gem with no dependencies.
16
16
  EOF
17
- s.version = '0.3.4'
17
+ s.version = '0.3.5'
18
18
  s.author = 'Tobias Fuchs'
19
19
  s.email = 'fuchs@atomnode.net'
20
20
  s.date = Time.now
@@ -25,6 +25,7 @@ part of Aurita in a single gem with no dependencies.
25
25
  'lib/aurita-gui/*',
26
26
  'lib/aurita-gui/form/*',
27
27
  'bin/*',
28
+ 'samples/*',
28
29
  'spec/*'].to_a
29
30
 
30
31
  s.has_rdoc = true
@@ -1,4 +1,6 @@
1
1
 
2
+ require('delegate')
3
+
2
4
  module Aurita
3
5
  module GUI
4
6
 
@@ -14,11 +16,46 @@ module GUI
14
16
  # via parameter :content or using a
15
17
  # block or by #content and #content=.
16
18
  #
19
+ # == Usage as container
20
+ #
21
+ # Element implements all features expected from a
22
+ # container class.
23
+ # It delegates access to @content to class Array,
24
+ # so an element can be used as Array instance, too:
25
+ #
26
+ # e = Element.new { Element.new { 'first' } + Element.new { 'second' } }
27
+ # puts e.join(' -- ')
28
+ # -->
29
+ # 'first -- second'
30
+ #
31
+ # You can also push elements into an element:
32
+ #
33
+ # e1 = HTML.div { 'Foo' }
34
+ # e2 = HTML.div { 'Bar' }
35
+ #
36
+ # assert_equal(e[0], 'Foo')
37
+ # assert_equal(e[1], e2)
38
+ #
39
+ # It also keeps track of parent classes:
40
+ #
41
+ # assert_equal(e1[1].parent, e1)
42
+ #
43
+ # Random access operators are redefined, so you
44
+ # can either access elements by array index, as usual,
45
+ # as well as by their DOM id:
46
+ #
47
+ # e = Element.new { Element.new(:tag => :p, :id => :foo) { 'nested element' } }
48
+ # puts e[:foo].to_s
49
+ # -->
50
+ # '<p id="foo">nested element</p>'
51
+ #
52
+ # == Builder
53
+ #
17
54
  # Most methods invoked on an Element instance are
18
55
  # redirected to return or set a tag attribute.
19
56
  # Example:
20
57
  #
21
- # link = Element(:tag => :a) { 'klick me' }
58
+ # link = Element.new(:tag => :a) { 'click me' }
22
59
  # link.href = '/link/to/somewhere'
23
60
  #
24
61
  # Same as
@@ -108,11 +145,11 @@ module GUI
108
145
  # e.onclick == 'alert("message");'
109
146
  # e.to_s == '<div onclick="alert(\"message\");"></div>'
110
147
  #
111
- class Element
148
+ class Element < DelegateClass(Array)
112
149
 
113
150
  @@element_count = 0
114
151
 
115
- attr_accessor :attrib, :content, :parent, :force_closing_tag, :tag
152
+ attr_accessor :attrib, :parent, :force_closing_tag, :tag
116
153
 
117
154
  def initialize(*args, &block)
118
155
 
@@ -144,52 +181,73 @@ module GUI
144
181
  end
145
182
  @content = [ @content ] unless (@content.kind_of? Array or @content.to_s.length == 0)
146
183
  @content ||= []
184
+
185
+ @content.each { |c|
186
+ if c.is_a?(Element) then
187
+ c.parent = self
188
+ end
189
+ }
147
190
  params.delete(:content)
148
191
  params.delete(:tag)
149
- # params[:id] = self.class.to_s.split('::')[-1].downcase + '_' << @@element_count.to_s if params[:id].nil?
150
- # params[:onclick] << ';' unless params[:onclick].nil? or params[:onclick].include?(';')
151
192
 
152
193
  @attrib = params
153
- # @attrib[:id] = @attrib[:id].to_s
154
-
194
+
195
+ super(@content)
196
+
155
197
  end
156
198
 
157
199
  def has_content?
158
- (@content.length > 0)
200
+ (length > 0)
159
201
  end
160
202
 
161
- # Return DOM id of this element.
162
- def dom_id
163
- @attrib[:id] if @attrib
164
- end
165
- # Set DOM id of this element.
166
- def dom_id=(value)
167
- @attrib[:id] = value if @attrib
168
- end
169
203
  # Alias definition for #dom_id=(value)
170
204
  # Define explicitly so built-in method #id
171
205
  # is not invoked instead
172
206
  def id=(value)
173
- @attrib[:id] = value
207
+ @attrib[:id] = value if @attrib
174
208
  end
209
+ alias dom_id= id=
175
210
  # Alias definition for #dom_id()
176
211
  def id
177
- @attrib[:id]
212
+ @attrib[:id] if @attrib
178
213
  end
214
+ alias dom_id id
179
215
 
180
- # Render this element to a string and append another
181
- # element.
216
+ # Return [ self, other ] so concatenation of
217
+ # Element instances works as expected;
218
+ #
219
+ # HTML.build {
220
+ # div { 'first' } + div { 'second' }
221
+ # }
222
+ # --> <Element [ <Element 'first'>, <Element 'second'> ] >
223
+ #
182
224
  def +(other)
183
- # return string << other.string if other.kind_of? Element
184
225
  return [ self, other ]
185
226
  end
186
- alias << +
187
227
 
228
+ # Append object to array of nested elements.
229
+ # Object to append (other) does not have to
230
+ # be an Element instance.
231
+ # If so, however, other#parent will be set
232
+ # to this instance.
233
+ def <<(other)
234
+ other.parent = self if other.is_a?(Element)
235
+ __getobj__().push(other)
236
+ end
237
+
238
+ # Returns [ self ], so concatenation with
239
+ # Arrays and other Element instances works
240
+ # as expected (see #<<(other).
188
241
  def to_ary
189
242
  [ self ]
190
243
  end
191
244
  alias to_a to_ary
192
245
 
246
+ # Returns nested content as array.
247
+ def get_content
248
+ __getobj__()
249
+ end
250
+
193
251
  # Redirect methods to setting or retreiving tag
194
252
  # attributes.
195
253
  # There are several possible routings for method_missing:
@@ -220,16 +278,20 @@ module GUI
220
278
  if block_given? then
221
279
  @attrib[:class] = meth
222
280
  @attrib.update(value) if value.is_a? Hash
223
- @content = yield
281
+ c = yield
282
+ c = [ c ] unless c.is_a?(Array)
283
+ __setobj__(c)
224
284
  return self
225
285
  elsif !value.nil? && !meth.to_s.include?('=') then
226
286
  @attrib[:class] = meth
227
287
  case value
228
288
  when Hash then
229
289
  @attrib.update(value)
230
- @content = value[:content]
290
+ c = value[:content]
291
+ c = [ c ] if (c && !c.is_a?(Array))
292
+ __setobj__(c) if c
231
293
  when String then
232
- @content = value
294
+ __setobj__([value])
233
295
  end
234
296
  return self
235
297
  else
@@ -240,9 +302,11 @@ module GUI
240
302
 
241
303
  # Set enclosed content of this element.
242
304
  # Will be automatically wrapped in an array.
243
- def content=(obj)
244
- @content = [ obj ]
305
+ def set_content(obj)
306
+ return __setobj__([ obj ]) unless (obj.is_a?(Array))
307
+ __setobj__(obj)
245
308
  end
309
+ alias content= set_content
246
310
 
247
311
  # Define explicitly so built-in method #type
248
312
  # is not invoked instead
@@ -252,7 +316,7 @@ module GUI
252
316
 
253
317
  # Do not redirect random access operators.
254
318
  def [](index)
255
- return @content[index] if (index.is_a? Numeric)
319
+ return super(index) if (index.is_a?(Fixnum))
256
320
  return find_by_dom_id(index)
257
321
  end
258
322
 
@@ -260,7 +324,7 @@ module GUI
260
324
  # its dom_id
261
325
  def find_by_dom_id(dom_id)
262
326
  dom_id = dom_id.to_sym
263
- @content.each { |c|
327
+ each { |c|
264
328
  if c.is_a? Element then
265
329
  return c if (c.dom_id == dom_id)
266
330
  sub = c.find_by_dom_id(dom_id)
@@ -272,16 +336,10 @@ module GUI
272
336
 
273
337
  # Do not redirect random access operators.
274
338
  def []=(index,element)
275
- @content[index] = element if (index.is_a? Numeric)
339
+ super(index,element) if (index.is_a? Numeric)
276
340
  e = find_by_dom_id(index)
277
341
  e.swap(element)
278
342
  end
279
- def length
280
- @content.length
281
- end
282
- def empty?
283
- @content.length == 0
284
- end
285
343
 
286
344
  # Copy constructor. Replace self with
287
345
  # other element.
@@ -290,7 +348,7 @@ module GUI
290
348
  @tag = other.tag
291
349
  @attrib = other.attrib
292
350
  @attrib[:id] = save_own_id
293
- @content = other.content
351
+ __setobj__(other.get_content)
294
352
  end
295
353
  alias copy swap
296
354
 
@@ -302,43 +360,37 @@ module GUI
302
360
 
303
361
  # Render this element to a string.
304
362
  def string
305
- return content.to_s if @tag == :pseudo
363
+ return get_content.to_s if @tag == :pseudo
306
364
 
307
365
  attrib_string = ''
308
366
  @attrib.each_pair { |name,value|
309
367
  if value.instance_of?(Array) then
310
368
  value = value.join(' ')
311
- elsif
312
- value.instance_of?(TrueClass) then
369
+ elsif value.instance_of?(TrueClass) then
313
370
  value = name
314
371
  end
315
372
  if !value.nil? then
316
- value = value.to_s
317
- attrib_string << ' ' << name.to_s + '="' << value.gsub('"','\"') + '"'
373
+ value = value.to_s.gsub('"','\"')
374
+ attrib_string << " #{name}=\"#{value}\""
318
375
  end
319
376
  }
320
377
 
321
- out = ''
322
378
  if (!(@force_closing_tag.instance_of?(FalseClass)) &&
323
379
  [ :div, :label, :button, :textarea ].include?(@tag)) then
324
380
  @force_closing_tag = true
325
381
  end
326
- if @force_closing_tag || content.to_s != '' then
327
- out << "<#{@tag}"
328
- out << attrib_string if attrib_string.length > 0
329
- out << ">#{content}"
330
- out << "</#{@tag}>"
382
+ if @force_closing_tag || has_content? then
383
+ return "<#{@tag}#{attrib_string}>#{__getobj__}</#{@tag}>"
331
384
  else
332
- out = "<#{@tag.to_s}#{attrib_string} />"
385
+ return "<#{@tag.to_s}#{attrib_string} />"
333
386
  end
334
- return out
335
387
  end
336
388
  alias to_s string
389
+ alias to_str string
337
390
 
338
- def each(&block)
339
- @content.each(&block)
340
- end
341
-
391
+ # Return CSS classes as array. Note that
392
+ # Element#class is not redefined to return
393
+ # attribute :class, for obvious reasons.
342
394
  def css_classes
343
395
  css_classes = @attrib[:class]
344
396
  if css_classes.kind_of? Array
@@ -348,21 +400,76 @@ module GUI
348
400
  else # e.g. Symbol
349
401
  css_classes = [ css_classes ]
350
402
  end
351
- css_classes.collect { |c| c.to_sym if c }
403
+ css_classes.map! { |c| c.to_sym if c }
352
404
  return css_classes
353
405
  end
354
406
  alias css_class css_classes
355
407
 
408
+ # Add CSS class to this Element instance.
409
+ # e = Element.new(:class => :first)
410
+ # e.add_class(:second
411
+ # e.to_s
412
+ # -->
413
+ # <div class="first second"></div>
356
414
  def add_class(css_class_name)
357
415
  @attrib[:class] = (css_classes << css_class_name.to_sym)
358
416
  end
417
+ alias add_css_class add_class
359
418
 
419
+ # Remove CSS class from this Element instance.
420
+ # Add CSS class to this Element instance.
421
+ # e = Element.new(:class => [ :first, :second ])
422
+ # e.to_s
423
+ # -->
424
+ # <div class="first second"></div>
425
+ #
426
+ # e.remove_class(:second)
427
+ # e.to_s
428
+ # -->
429
+ # <div class="first"></div>
360
430
  def remove_class(css_class_name)
361
431
  classes = css_classes
362
432
  classes.delete(css_class_name.to_sym)
363
433
  @attrib[:class] = classes
364
434
  end
365
-
435
+ alias remove_css_class remove_class
436
+
437
+ # Iterates over all Elements in this
438
+ # instances object tree (depth first).
439
+ #
440
+ # x = HTML.build {
441
+ # div.main {
442
+ # h2.header { 'Title' } +
443
+ # div.lead { 'Intro here' } +
444
+ # div.body {
445
+ # p.section { 'First' } +
446
+ # p.section { 'Second' }
447
+ # }
448
+ # }
449
+ # }
450
+ #
451
+ # x.recurse { |element|
452
+ # p element.css_class
453
+ # }
454
+ #
455
+ # -->
456
+ #
457
+ # :main
458
+ # :header
459
+ # :lead
460
+ # :body
461
+ # :section
462
+ # :section
463
+ #
464
+ def recurse(&block)
465
+ each { |c|
466
+ if c.is_a?(Element) then
467
+ yield(c)
468
+ c.recurse(&block)
469
+ end
470
+ }
471
+ end
472
+
366
473
  end # class
367
474
 
368
475
  end # module
@@ -3,6 +3,7 @@ require('aurita-gui/form/form_field')
3
3
 
4
4
  module Aurita
5
5
  module GUI
6
+ # TODO: Use ArrayFields for option field/value storage
6
7
 
7
8
  # Abstract base class for all form elements containing
8
9
  # options, like Select_Field, Radio_Field, Checkbox_Field
@@ -4,6 +4,9 @@ require('aurita-gui/element')
4
4
  module Aurita
5
5
  module GUI
6
6
 
7
+ # = Aurita::GUI
8
+ # Tobias Fuchs, 2009
9
+ #
7
10
  # == About
8
11
  #
9
12
  # Aurita::GUI is a library for convenient, simple
File without changes
@@ -0,0 +1,17 @@
1
+
2
+ require 'rubygems'
3
+ require 'aurita-gui'
4
+
5
+ include Aurita::GUI
6
+
7
+ e1 = HTML.div.outer { 'Foo' }
8
+ e2 = HTML.div.inner { 'Bar' }
9
+
10
+ e1 << e2
11
+
12
+ puts e1.to_s
13
+ p e1[0] == 'Foo'
14
+ p e1[1] == e2
15
+
16
+ p e1[1].parent == e1
17
+ p e2.parent == e1
@@ -0,0 +1,22 @@
1
+
2
+ require 'rubygems'
3
+ require 'aurita-gui'
4
+
5
+ include Aurita::GUI
6
+
7
+
8
+ class Renderfoo
9
+
10
+ def outerfun(i)
11
+ i * i
12
+ end
13
+
14
+ def render
15
+ puts HTML.build {
16
+ outerfun(23)
17
+ }.to_s
18
+ end
19
+
20
+ end
21
+
22
+ Renderfoo.new.render
@@ -0,0 +1,21 @@
1
+
2
+ require 'rubygems'
3
+ require 'aurita-gui'
4
+
5
+ include Aurita::GUI
6
+
7
+ x = HTML.build {
8
+ div.main {
9
+ h2.header { 'Title' } +
10
+ div.lead { 'Intro here' } +
11
+ div.body {
12
+ p.section { 'First' } +
13
+ p.section { 'Second' } +
14
+ p.section { 'Third' }
15
+ }
16
+ }
17
+ }
18
+
19
+ x.recurse { |element|
20
+ p element.css_class
21
+ }
File without changes
@@ -41,8 +41,9 @@ describe Aurita::GUI::Element, "basic rendering" do
41
41
  e1 = Element.new(:id => :first)
42
42
  e2 = Element.new(:id => :second)
43
43
 
44
- (e1 << e2).should == [ e1, e2 ]
45
44
  (e1 + e2).should == [ e1, e2 ]
45
+ e1 << e2
46
+ e1[0].should == e2
46
47
  end
47
48
 
48
49
  it "should be able to render to string" do
@@ -51,14 +52,14 @@ describe Aurita::GUI::Element, "basic rendering" do
51
52
  end
52
53
 
53
54
  it "should have enclosed content that is an array" do
54
- @e1.content.length.should == 0
55
+ @e1.get_content.length.should == 0
55
56
  @e1.has_content?().should == false
56
- @e1.content.should == []
57
+ @e1.get_content.should == []
57
58
  end
58
59
 
59
60
  it "should close the tag depending on content" do
60
61
  @e1.content = 'the content'
61
- @e1.content.should == [ 'the content' ]
62
+ @e1.get_content.should == [ 'the content' ]
62
63
  @e1.to_s.should == '<tagname>the content</tagname>'
63
64
  end
64
65
 
@@ -97,7 +98,7 @@ describe Aurita::GUI::Element, "basic rendering" do
97
98
 
98
99
  it "should accept parameter :content" do
99
100
  e = Element.new(:tag => :bar, :content => 'content here', :name => :wombat)
100
- e.content.should == ['content here']
101
+ e.get_content.should == ['content here']
101
102
  e.name.should == :wombat
102
103
  e.to_s.should == '<bar name="wombat">content here</bar>'
103
104
  end
@@ -105,7 +106,7 @@ describe Aurita::GUI::Element, "basic rendering" do
105
106
  it "should accept content as block, maintaining object identity" do
106
107
  test_obj_identity = 'lorem_ipsum'
107
108
  e = Element.new(:tag => :jada) { test_obj_identity }
108
- e.content.should == [ test_obj_identity ]
109
+ e.get_content.should == [ test_obj_identity ]
109
110
  e.tag.should == :jada
110
111
  end
111
112
 
@@ -117,18 +118,18 @@ describe Aurita::GUI::Element, "basic rendering" do
117
118
  end
118
119
 
119
120
  it "should accept other element instances as content" do
120
- @outer.content.should == [ @inner ]
121
+ @outer.get_content.should == [ @inner ]
121
122
  @outer.to_s.should == '<p class="outer"><h2>i am an inner header</h2></p>'
122
123
  end
123
124
 
124
125
  it "should maintain an object hierarchy" do
125
- @outer.content.first.new_attrib = 23
126
- @outer.content.first.new_attrib.should == 23
126
+ @outer.get_content.first.new_attrib = 23
127
+ @outer.get_content.first.new_attrib.should == 23
127
128
  end
128
129
 
129
130
  it "should be possible to alter an enclosed element after adding it as content" do
130
131
  @inner.decorated_attrib = 'decorated'
131
- @inner.content << ' with decoration'
132
+ @inner.get_content << ' with decoration'
132
133
 
133
134
  @outer.to_s.should == '<p class="outer"><h2 decorated_attrib="decorated">i am an inner header with decoration</h2></p>'
134
135
 
@@ -157,10 +158,10 @@ describe Aurita::GUI::Element, "basic rendering" do
157
158
  dwa = 'two'
158
159
  tri = 'three'
159
160
  e.content = ras
160
- e.content.should == [ ras ]
161
- e.content << dwa
162
- e.content << tri
163
- e.content.should == [ ras, dwa, tri ]
161
+ e.get_content.should == [ ras ]
162
+ e << dwa
163
+ e << tri
164
+ e.get_content.should == [ ras, dwa, tri ]
164
165
  end
165
166
 
166
167
  end
@@ -38,15 +38,15 @@ describe Aurita::GUI::HTML, "basic rendering" do
38
38
  @e[0].css_class.first.should == :outer
39
39
  @e[0][0].id.should == :header
40
40
  @e[0][1].id.should == :content
41
- @e[0][1].content.should == [ 'Content' ]
41
+ @e[0][1].get_content.should == [ 'Content' ]
42
42
  @e[0][1].content = 'Altered'
43
- @e[0][1].content.should == [ 'Altered' ]
43
+ @e[0][1].get_content.should == [ 'Altered' ]
44
44
  @e.to_s.should == '<div class="outer"><h2 id="header">Header</h2><p id="content">Altered</p></div>'
45
45
  end
46
46
 
47
47
  it "should be possible to retreive elements just by DOM id" do
48
48
  e = @e[:header]
49
- e.content.first.should == 'Header'
49
+ e.get_content.first.should == 'Header'
50
50
  end
51
51
 
52
52
  it "should escape double-quotes in tag parameters" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aurita-gui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
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-26 00:00:00 +01:00
12
+ date: 2009-01-27 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -22,15 +22,14 @@ extensions: []
22
22
  extra_rdoc_files: []
23
23
 
24
24
  files:
25
- - cheatsheet.rb
26
25
  - spec
27
26
  - History.txt
28
27
  - lib
28
+ - samples
29
29
  - aurita-gui.gemspec
30
30
  - bin
31
31
  - TODO
32
32
  - test
33
- - valuetest.rb
34
33
  - LICENSE
35
34
  - lib/aurita-gui
36
35
  - lib/aurita-gui.rb
@@ -59,6 +58,11 @@ files:
59
58
  - lib/aurita-gui/form/template_helper.rb
60
59
  - lib/aurita-gui/form/input_field.rb
61
60
  - lib/aurita-gui/form/date_field.rb
61
+ - samples/putstest.rb
62
+ - samples/recurse.rb
63
+ - samples/cheatsheet.rb
64
+ - samples/valuetest.rb
65
+ - samples/pushtest.rb
62
66
  - spec/marshal.rb
63
67
  - spec/javascript.rb
64
68
  - spec/form.rb