require 'facet/string/capitalized' require 'facet/string/camelize' require 'facet/class/method_name' require 'facet/dir/self/recurse' require 'facet/annotation' require 'glue/configuration' require 'glue/template' module Nitro # A programmatically generated element. Elements are a form # of macros to allow for cleaner templates. They are evaluated # at compile time, so there is no performance hit when you use # them (at the expense of slightly reduced functionality). # # Nitro provides an additional method of defining elements. # Instead of creating a lot of small classes, you can put # .xhtml templates in the Element template_root. These templates # are automatically converted into Element classes. # # For extra safety, you are advised to place your classes in the # Nitro::Element namespace. If your classes do not extend # Nitro::Element, the Nitro::ElementMixin is automatically # injected in the class. # # An element can have and access a hierarchy of sub-elements. # use #{content :sub_element_name} to access the render output # of the subelement. Additionaly you can access the whole # subelement object: _children[:sub_element_name] # # === Design # # An underscore is used for the standard attibutes to # avoid name clashes. #-- # TODO: # * separate 'view' template files. #++ module ElementMixin # The parent of this element. attr_accessor :_parent # The children of this element. attr_accessor :_children alias_method :children, :_children # The text of this element. attr_accessor :_text # The view of this element. attr_accessor :_view # The id of this element. attr_accessor :id def initialize(*args) @_children = {} @_text = '' @id = self.class.demodulize.underscore end # Prepend this code to the element content. def open end # If an optional name parameter is passed renders # the content of the named child element. # # eg. #{content :child_element_id} def content(cname = nil) if cname if c = @_children[cname.to_s] c.content else Logger.error "Undefined sub-element '#{cname}' for element '#{self.class}'" end else @_text end end # Append this code to the element content. def close end # Override this. def render "#{open}#{content}#{close}" end def render_children str = '' for c in @_children.values str << c.render end return str end def add_child(child) child._parent = self @_children[child.id] = child end alias_method :children, :_children end # A programmatically generated element. # # === Usage # # = in the code # # class Page < Nitro::Element # def render # %{ #