Class: Aurita::GUI::Element
- Inherits:
-
Array
- Object
- Array
- Aurita::GUI::Element
- Extended by:
- Marshal_Helper_Class_Methods
- Includes:
- Marshal_Helper
- Defined in:
- lib/aurita-gui/element.rb,
lib/aurita-gui/marshal.rb
Overview
GUI::Element is the base class for any rendering implementation. It consists of the following members:
* @tag: The HTML tag to render.
* @attrib: A hash storing tag attributes, like
{ :href => '/link/to/somewhere' }
* @content: Content this element is wrapping.
Content can be set in the constructor
via parameter :content or using a
block or by #content and #content=.
Usage as container
Element implements all features expected from a container class. It delegates access to @content to class Array, so an element can be used as Array instance, too:
e = Element.new { Element.new { 'first' } + Element.new { 'second' } }
puts e.join(' -- ')
-->
'first -- second'
You can also push elements into an element:
e1 = HTML.div { 'Foo' }
e2 = HTML.div { 'Bar' }
assert_equal(e[0], 'Foo')
assert_equal(e[1], e2)
It also keeps track of parent classes:
assert_equal(e1[1].parent, e1)
Random access operators are redefined, so you can either access elements by array index, as usual, as well as by their DOM id:
e = Element.new { Element.new(:tag => :p, :id => :foo) { 'nested element' } }
puts e[:foo].to_s
-->
'<p id="foo">nested element</p>'
Builder
Most methods invoked on an Element instance are redirected to return or set a tag attribute. Example:
link = Element.new(:tag => :a) { 'click me' }
link.href = '/link/to/somewhere'
Same as
link = Element(:tag => :a,
:content => 'click me',
:href => '/link/to/somewhere')
An Element instance can wrap one or more other elements:
image_link = Element.new(:tag => :a, :href => '/link/') {
Element.new(:tag => :img, :src => '/an_image.png')
}
In case an element has no content, it will render a self-closing tag, like <img … />.
In most cases you won’t use class Element directly, but by using a factory like Aurita::GUI::HTML or by any derived class like Aurita::GUI::Form or Aurita::GUI::Table.
Markaby style
A syntax similar to markaby is also provided:
HTML.build {
div.outer {
p.inner 'click me'
} +
div. 'text at the bottom'
}.to_s
–>
<div class="outer">
<p class="inner">paragraph</p>
</div>
<div class="footer">text at the bottom</div>
Javascript convenience
When including the Javascript helper (aurita-gui/javascript), class HTML is extended by method .js, which provides building Javascript snippets in ruby:
e = HTML.build {
div.outer(:onclick => js.Wombat.alert('message')) {
p.inner 'click me'
}
}
e.to_s
–>
<div class="outer" onclick="Wombat.alert(\'message\'); ">
<p class="inner">click me</p>
</div>
But watch out for operator precedence! This won’t work, as .js() catches the block first:
HTML.build {
div :header, :onclick => js.funcall { 'i will not be passed to div' }
}
–>
<div class="header" onclick="funcall();"></div>
So be explicit, use parentheses:
HTML.build {
div(:header, :onclick => js.funcall) { 'aaah, much better' }
}
–>
<div class="header" onclick="funcall();">aaah, much better</div>
Notes
Double-quotes in tag parameters will be escaped when rendering to string.
e = Element.new(:onclick => 'alert("message");')
The value of parameter :onclick does not change, but will be escaped when rendering:
e.onclick == 'alert("message");'
e.to_s == '<div onclick="alert(\"message\");"></div>'
Direct Known Subclasses
Buffered_Element, Button, Fieldset, Form, Form_Content_Wrapper, Form_Field, Form_Field_Wrapper, Table, Table_Cell, Table_Row
Constant Summary collapse
- @@element_count =
0
Instance Attribute Summary collapse
-
#attrib ⇒ Object
Returns the value of attribute attrib.
-
#force_closing_tag ⇒ Object
Returns the value of attribute force_closing_tag.
-
#parent ⇒ Object
Returns the value of attribute parent.
-
#tag ⇒ Object
Returns the value of attribute tag.
Instance Method Summary collapse
-
#+(other) ⇒ Object
Return [ self, other ] so concatenation of Element instances works as expected; .
-
#<<(other) ⇒ Object
Append object to array of nested elements.
-
#[](index) ⇒ Object
Do not redirect random access operators.
-
#[]=(index, element) ⇒ Object
Do not redirect random access operators.
-
#add_class(css_class_name) ⇒ Object
(also: #add_css_class)
Add CSS class to this Element instance.
-
#clear_floating ⇒ Object
Static helper definition for clearing CSS floats.
-
#css_classes ⇒ Object
(also: #css_class)
Return CSS classes as array.
-
#find_by_dom_id(dom_id) ⇒ Object
Retreive an element from object tree by its dom_id.
-
#get_content ⇒ Object
Returns nested content as array.
- #has_content? ⇒ Boolean
-
#id ⇒ Object
(also: #dom_id)
Alias definition for #dom_id().
-
#id=(value) ⇒ Object
(also: #dom_id=)
Alias definition for #dom_id=(value) Define explicitly so built-in method #id is not invoked instead.
-
#initialize(*args, &block) ⇒ Element
constructor
A new instance of Element.
-
#method_missing(meth, value = nil, &block) ⇒ Object
Redirect methods to setting or retreiving tag attributes.
-
#recurse(&block) ⇒ Object
Iterates over all Elements in this instances object tree (depth first).
-
#remove_class(css_class_name) ⇒ Object
(also: #remove_css_class)
Remove CSS class from this Element instance.
-
#set_content(obj) ⇒ Object
(also: #content=)
Set enclosed content of this element.
-
#string ⇒ Object
(also: #to_s, #to_str)
Render this element to a string.
-
#swap(other) ⇒ Object
(also: #copy)
Copy constructor.
-
#to_ary ⇒ Object
(also: #to_a)
Returns [ self ], so concatenation with Arrays and other Element instances works as expected (see #<<(other)..
-
#type=(type) ⇒ Object
Define explicitly so built-in method #type is not invoked instead.
Methods included from Marshal_Helper_Class_Methods
Methods included from Marshal_Helper
Constructor Details
#initialize(*args, &block) ⇒ Element
Returns a new instance of Element.
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/aurita-gui/element.rb', line 154 def initialize(*args, &block) params = {} case args[0] when Hash params = args[0] else params = args[1] params ||= {} params[:content] = args[0] end @@element_count += 1 @id = @@element_count @parent = params[:parent] @force_closing_tag = params[:force_closing_tag] params[:tag] = :div if params[:tag].nil? @tag = params[:tag] params.delete(:parent) params.delete(:force_closing_tag) if block_given? then @content = yield else @content = params[:content] end @content = [ @content ] unless (@content.kind_of? Array or @content.to_s.length == 0) @content ||= [] @content.each { |c| if c.is_a?(Element) then c.parent = self end } params.delete(:content) params.delete(:tag) @attrib = params super(@content) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, value = nil, &block) ⇒ Object
Redirect methods to setting or retreiving tag attributes. There are several possible routings for method_missing:
-
Setting an attribute (no block, method ends in ‘=’) Example:
my_div = HTML.div 'content'
my_div.onlick = "alert('foo');"
puts my_div.to_s
–>
<div onclick="alert('foo');">content</div>
-
Retreiving an attribute (no block, method does not end in ‘=’). Example:
puts my_div.onlick
–>
'alert(\'foo\');'
-
Setting the css class (block or value passed, method does not end in ‘=’). Example:
my_div.highlighted { 'content' }
or
my_div.highlighted 'content'
–>
<div class="highlighted">content</div>
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/aurita-gui/element.rb', line 277 def method_missing(meth, value=nil, &block) if block_given? then @attrib[:class] = meth @attrib.update(value) if value.is_a? Hash c = yield c = [ c ] unless c.is_a?(Array) __setobj__(c) return self elsif !value.nil? && !meth.to_s.include?('=') then @attrib[:class] = meth case value when Hash then @attrib.update(value) c = value[:content] c = [ c ] if (c && !c.is_a?(Array)) __setobj__(c) if c when String then __setobj__([value]) end return self else return @attrib[meth] unless value or meth.to_s.include? '=' @attrib[meth.to_s.gsub('=','').intern] = value end end |
Instance Attribute Details
#attrib ⇒ Object
Returns the value of attribute attrib.
152 153 154 |
# File 'lib/aurita-gui/element.rb', line 152 def attrib @attrib end |
#force_closing_tag ⇒ Object
Returns the value of attribute force_closing_tag.
152 153 154 |
# File 'lib/aurita-gui/element.rb', line 152 def force_closing_tag @force_closing_tag end |
#parent ⇒ Object
Returns the value of attribute parent.
152 153 154 |
# File 'lib/aurita-gui/element.rb', line 152 def parent @parent end |
#tag ⇒ Object
Returns the value of attribute tag.
152 153 154 |
# File 'lib/aurita-gui/element.rb', line 152 def tag @tag end |
Instance Method Details
#+(other) ⇒ Object
Return [ self, other ] so concatenation of Element instances works as expected;
HTML.build {
div { 'first' } + div { 'second' }
}
--> <Element [ <Element 'first'>, <Element 'second'> ] >
224 225 226 |
# File 'lib/aurita-gui/element.rb', line 224 def +(other) return [ self, other ] end |
#<<(other) ⇒ Object
Append object to array of nested elements. Object to append (other) does not have to be an Element instance. If so, however, other#parent will be set to this instance.
233 234 235 236 |
# File 'lib/aurita-gui/element.rb', line 233 def <<(other) other.parent = self if other.is_a?(Element) __getobj__().push(other) end |
#[](index) ⇒ Object
Do not redirect random access operators.
318 319 320 321 |
# File 'lib/aurita-gui/element.rb', line 318 def [](index) return super(index) if (index.is_a?(Fixnum)) return find_by_dom_id(index) end |
#[]=(index, element) ⇒ Object
Do not redirect random access operators.
338 339 340 341 342 |
# File 'lib/aurita-gui/element.rb', line 338 def []=(index,element) super(index,element) if (index.is_a? Numeric) e = find_by_dom_id(index) e.swap(element) end |
#add_class(css_class_name) ⇒ Object Also known as: add_css_class
Add CSS class to this Element instance.
e = Element.new(:class => :first)
e.add_class(:second
e.to_s
–>
<div class="first second"></div>
414 415 416 |
# File 'lib/aurita-gui/element.rb', line 414 def add_class(css_class_name) @attrib[:class] = (css_classes << css_class_name.to_sym) end |
#clear_floating ⇒ Object
Static helper definition for clearing CSS floats.
357 358 359 |
# File 'lib/aurita-gui/element.rb', line 357 def clear_floating '<div style="clear: both;" />' end |
#css_classes ⇒ Object Also known as: css_class
Return CSS classes as array. Note that Element#class is not redefined to return attribute :class, for obvious reasons.
394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/aurita-gui/element.rb', line 394 def css_classes css_classes = @attrib[:class] if css_classes.kind_of? Array css_classes.flatten! elsif css_classes.kind_of? String css_classes = css_classes.split(' ') else # e.g. Symbol css_classes = [ css_classes ] end css_classes.map! { |c| c.to_sym if c } return css_classes end |
#find_by_dom_id(dom_id) ⇒ Object
Retreive an element from object tree by its dom_id
325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/aurita-gui/element.rb', line 325 def find_by_dom_id(dom_id) dom_id = dom_id.to_sym each { |c| if c.is_a? Element then return c if (c.dom_id == dom_id) sub = c.find_by_dom_id(dom_id) return sub if sub end } return nil end |
#get_content ⇒ Object
Returns nested content as array.
247 248 249 |
# File 'lib/aurita-gui/element.rb', line 247 def get_content __getobj__() end |
#has_content? ⇒ Boolean
199 200 201 |
# File 'lib/aurita-gui/element.rb', line 199 def has_content? (length > 0) end |
#id ⇒ Object Also known as: dom_id
Alias definition for #dom_id()
211 212 213 |
# File 'lib/aurita-gui/element.rb', line 211 def id @attrib[:id] if @attrib end |
#id=(value) ⇒ Object Also known as: dom_id=
Alias definition for #dom_id=(value) Define explicitly so built-in method #id is not invoked instead
206 207 208 |
# File 'lib/aurita-gui/element.rb', line 206 def id=(value) @attrib[:id] = value if @attrib end |
#recurse(&block) ⇒ Object
Iterates over all Elements in this instances object tree (depth first).
x = HTML.build {
div.main {
h2.header { 'Title' } +
div.lead { 'Intro here' } +
div.body {
p.section { 'First' } +
p.section { 'Second' }
}
}
}
x.recurse { |element|
p element.css_class
}
–>
:main
:header
:lead
:body
:section
:section
464 465 466 467 468 469 470 471 |
# File 'lib/aurita-gui/element.rb', line 464 def recurse(&block) each { |c| if c.is_a?(Element) then yield(c) c.recurse(&block) end } end |
#remove_class(css_class_name) ⇒ Object Also known as: remove_css_class
Remove CSS class from this Element instance. Add CSS class to this Element instance.
e = Element.new(:class => [ :first, :second ])
e.to_s
–>
<div class="first second"></div>
e.remove_class(:second)
e.to_s
–>
<div class="first"></div>
430 431 432 433 434 |
# File 'lib/aurita-gui/element.rb', line 430 def remove_class(css_class_name) classes = css_classes classes.delete(css_class_name.to_sym) @attrib[:class] = classes end |
#set_content(obj) ⇒ Object Also known as: content=
Set enclosed content of this element. Will be automatically wrapped in an array.
305 306 307 308 |
# File 'lib/aurita-gui/element.rb', line 305 def set_content(obj) return __setobj__([ obj ]) unless (obj.is_a?(Array)) __setobj__(obj) end |
#string ⇒ Object Also known as: to_s, to_str
Render this element to a string.
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'lib/aurita-gui/element.rb', line 362 def string return get_content.to_s if @tag == :pseudo attrib_string = '' @attrib.each_pair { |name,value| if value.instance_of?(Array) then value = value.join(' ') elsif value.instance_of?(TrueClass) then value = name end if !value.nil? then value = value.to_s.gsub('"','\"') attrib_string << " #{name}=\"#{value}\"" end } if (!(@force_closing_tag.instance_of?(FalseClass)) && [ :div, :label, :button, :textarea ].include?(@tag)) then @force_closing_tag = true end if @force_closing_tag || has_content? then return "<#{@tag}#{attrib_string}>#{__getobj__}</#{@tag}>" else return "<#{@tag.to_s}#{attrib_string} />" end end |
#swap(other) ⇒ Object Also known as: copy
Copy constructor. Replace self with other element.
346 347 348 349 350 351 352 |
# File 'lib/aurita-gui/element.rb', line 346 def swap(other) save_own_id = dom_id() @tag = other.tag @attrib = other.attrib @attrib[:id] = save_own_id __setobj__(other.get_content) end |
#to_ary ⇒ Object Also known as: to_a
Returns [ self ], so concatenation with Arrays and other Element instances works as expected (see #<<(other).
241 242 243 |
# File 'lib/aurita-gui/element.rb', line 241 def to_ary [ self ] end |
#type=(type) ⇒ Object
Define explicitly so built-in method #type is not invoked instead
313 314 315 |
# File 'lib/aurita-gui/element.rb', line 313 def type=(type) @attrib[:type] = type end |