#!/usr/bin/env ruby #-- # Copyright &169;2001-2008 Integrallis Software, LLC. # All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ require 'trellis/trellis' require 'paginator' module Trellis module CoreComponents # Component that triggers an action on the server with a subsequent full # page refresh # class ActionLink < Trellis::Component render do |tag| source = tag.attr['tid'] context = tag.attr['context'] path = (tag.globals.page.path.nil? || tag.globals.page.path.empty?) ? nil : tag.globals.page.path class_name = tag.globals.page.class.name target_page = tag.attr['page'] || path || class_name if context value = tag.locals.instance_eval(context) || tag.globals.instance_eval(context) end if source if context id = "#{source}_#{value}" href = DefaultRouter.to_uri(:page => target_page, :event => 'select', :source => source, :value => value) else id = "#{source}" href = DefaultRouter.to_uri(:page => target_page, :event => 'select', :source => source) end else if context id = "action_link_#{value}" href = DefaultRouter.to_uri(:page => target_page, :event => 'select', :value => value) else id = "action_link" href = DefaultRouter.to_uri(:page => target_page, :event => 'select') end end builder = Builder::XmlMarkup.new text = builder.a('${contents}', "href" => href, "id" => id) text.replace_ant_style_property('contents', tag.expand) end end # # # class Loop < Trellis::Component render do |tag| value_name = tag.attr['value'] value = "#{value_name}=" # make value available by name to the page source = tag.attr['source'] start, finish = source.split('..') content = '' (start..finish).each do |n| tag.locals.send(value.to_sym, n) content << tag.expand end content end end # # # class Each < Trellis::Component render do |tag| value_name = tag.attr['value'] value = "#{value_name}=" # make value available by name to the page source = tag.attr['source'] begin iterator = tag.locals.instance_eval(source) || tag.globals.instance_eval(source) rescue NoMethodError iterator = [] end content = '' iterator.each do |n| tag.locals.send(value.to_sym, n) content << tag.expand end if iterator content end end # # # class Value < Trellis::Component render do |tag| name = tag.attr['name'] unless name.include?('.') value = tag.locals.send(name.to_sym) || tag.globals.send(name.to_sym) else value = tag.locals.instance_eval(name) || tag.globals.instance_eval(name) end value end end class Eval < Trellis::Component render do |tag| expression = tag.attr['expression'] tag.locals.instance_eval(expression) || tag.globals.instance_eval(expression) if expression end end # # page link should take parameters for pages that have a custom route # class PageLink < Trellis::Component render do |tag| url_root = tag.globals.page.class.url_root page_name = tag.attr['tpage'] id = tag.attr['tid'] || page_name href = DefaultRouter.to_uri(:url_root => url_root, :page => page_name) contents = tag.expand builder = Builder::XmlMarkup.new builder.a(contents, "href" => href, "id" => "page_link_#{id}") end end # # # class Img < Trellis::Component render do |tag| attrs = tag.attr.exclude_keys('src', 'alt') # resolve the ${} variables attrs['src'] = Utils.expand_properties_in_tag(tag.attr['src'], tag) attrs['alt'] = Utils.expand_properties_in_tag(tag.attr['alt'], tag) builder = Builder::XmlMarkup.new builder.img(attrs) end end # # # class Remove < Trellis::Component render do |tag| # do nothing end end # # # class If < Trellis::Component render do |tag| # resolve the ${} variables test = Utils.expand_properties_in_tag(tag.attr['test'], tag) value = tag.locals.instance_eval(test) || tag.globals.instance_eval(test) result = !value ? false : value tag.expand if result end end # # # class Unless < Trellis::Component render do |tag| # resolve the ${} variables test = Utils.expand_properties_in_tag(tag.attr['test'], tag) value = tag.locals.instance_eval(test) || tag.globals.instance_eval(test) result = !value ? false : value tag.expand unless result end end # # # class Button < Trellis::Component render do |tag| attrs = tag.attr.exclude_keys('tid', 'name', 'type') attrs['name'] = "#{tag.attr['tid']}" contents = tag.expand builder = Builder::XmlMarkup.new builder.button(contents, attrs) end end # # # class Form < Trellis::Component render do |tag| url_root = tag.globals.page.class.url_root form_name = tag.attr['tid'] on_behalf = tag.attr['on_behalf'] method = tag.attr['method'] || 'GET' tag.locals.form_name = form_name value = tag.attr['value'] if value eval_value = tag.locals.instance_eval(value) || tag.globals.instance_eval(value) end path = (tag.globals.page.path.nil? || tag.globals.page.path.empty?) ? nil : tag.globals.page.path class_name = tag.globals.page.class.name target_page = path || class_name href = Trellis::DefaultRouter.to_uri(:url_root => url_root, :page => target_page, :event => "submit", :source => "#{(on_behalf ? on_behalf : form_name)}", :value => eval_value) attrs = tag.attr.exclude_keys('tid', 'on_behalf', 'method') attrs["name"] = form_name attrs["action"] = href attrs["method"] = method builder = Builder::XmlMarkup.new builder.form(attrs) do |form| form << tag.expand end end end # # # class Submit < Trellis::Component tag_name "submit" contained_in "form" render do |tag| attrs = tag.attr.exclude_keys('tid', 'name', 'type') attrs['name'] = "#{tag.locals.form_name}_#{tag.attr['tid']}" attrs['type'] = 'submit' builder = Builder::XmlMarkup.new builder.input(attrs) end end # # # class CheckBox < Trellis::Component tag_name "check_box" contained_in "form" render do |tag| attrs = tag.attr.exclude_keys('tid', 'name', 'type') attrs['name'] = "#{tag.locals.form_name}_#{tag.attr['tid']}" attrs['type'] = 'checkbox' builder = Builder::XmlMarkup.new builder.input(attrs) end end # # # class TextField < Trellis::Component tag_name "text_field" contained_in "form" render do |tag| attrs = tag.attr.exclude_keys('tid', 'name', 'type', 'value') attrs['name'] = "#{tag.locals.form_name}_#{tag.attr['tid']}" value = tag.attr['value'] literal = tag.attr['literal'] =~ /^(y|yes|true)$/ if value if !literal resolved_value = '' unless value.include?('.') resolved_value = tag.locals.send(value.to_sym) || tag.globals.send(value.to_sym) else target_name, method = value.split('.') target = tag.locals.send(target_name.to_sym) || tag.globals.send(target_name.to_sym) resolved_value = target.send(method.to_sym) if target end attrs['value'] = resolved_value if resolved_value else attrs['value'] = value end end attrs['type'] = 'text' builder = Builder::XmlMarkup.new builder.input(attrs) end end # # # class TextArea < Trellis::Component tag_name "text_area" contained_in "form" render do |tag| attrs = tag.attr.exclude_keys('tid', 'name', 'keep_contents') attrs['name'] = "#{tag.locals.form_name}_#{tag.attr['tid']}" keep_contents = tag.attr['keep_contents'] if keep_contents contents = keep_contents =~ /^(y|yes|true)$/ ? tag.expand : '' else contents = '' end builder = Builder::XmlMarkup.new builder.textarea(contents, attrs) end end # # # class Password < Trellis::Component tag_name "password" contained_in "form" render do |tag| attrs = tag.attr.exclude_keys('tid', 'name', 'type') attrs['name'] = "#{tag.locals.form_name}_#{tag.attr['tid']}" attrs['type'] = 'password' builder = Builder::XmlMarkup.new builder.input(attrs) end end # # # class Hidden < Trellis::Component tag_name "hidden" contained_in "form" render do |tag| attrs = tag.attr.exclude_keys('tid', 'name', 'type', 'value') attrs['name'] = "#{tag.locals.form_name}_#{tag.attr['tid']}" value = tag.attr['value'] literal = tag.attr['literal'] =~ /^(y|yes|true)$/ if value if !literal resolved_value = '' unless value.include?('.') resolved_value = tag.globals.send(value.to_sym) else target_name, method = value.split('.') target = tag.globals.send(target_name.to_sym) resolved_value = target.send(method.to_sym) end attrs['value'] = resolved_value else attrs['value'] = value end end attrs['type'] = 'hidden' builder = Builder::XmlMarkup.new builder.input(attrs) end end # # # class Select < Trellis::Component tag_name "select" contained_in "form" render do |tag| attrs = tag.attr.exclude_keys('tid', 'select_if', 'selected_value', 'source') attrs['name'] = "#{tag.locals.form_name}_#{tag.attr['tid']}" expression = tag.attr['source'] # something we can iterate over selected = Utils.evaluate_tag_attribute('select_if', tag) selected_value = Utils.evaluate_tag_attribute('selected_value', tag) value_accessor = Utils.expand_properties_in_tag(tag.attr['value'], tag) builder = Builder::XmlMarkup.new builder.select(attrs) do if expression.include? '..' start, finish = expression.split('..') (start..finish).each do |item| value = value_accessor ? item.instance_eval(value_accessor) : item unless item == selected builder.option item, :value => value else builder.option item, selected => (selected_value.nil? ? 'yes' : selected_value), :value => value end end else source = Utils.evaluate_tag_attribute('source', tag) if source.respond_to? :each source.each do |item| value = value_accessor ? item.instance_eval(value_accessor) : item unless item == selected builder.option item, :value => value else builder.option item, :selected => (selected_value.nil? ? 'yes' : selected_value), :value => value end end elsif source.respond_to? :each_pair source.each_pair do |name,value| unless value == selected builder.option name, :value => value else builder.option name, :selected => (selected_value.nil? ? value : selected_value), :value => value end end end end end end end # Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object # assigned to the template (identified by +object+). The text of label will default to the attribute name unless you specify # it explicitly. Additional options on the label tag can be passed as a hash with +options+. These options will be tagged # onto the HTML as an HTML element attribute as in the example shown. # # ==== Examples # label(:post, :title) # #=> # # label(:post, :title, "A short title") # #=> # # label(:post, :title, "A short title", :class => "title_label") # #=> class Label < Trellis::Component render do |tag| target = "#{tag.locals.form_name}_#{tag.attr['for']}" contents = tag.expand builder = Builder::XmlMarkup.new builder.label(contents, :for => target) end end # Creates a file upload field. If you are using file uploads then you will also need # to set the multipart option for the form tag: # # <%= form_tag { :action => "post" }, { :multipart => true } %> # <%= file_field_tag "file" %> # <%= submit_tag %> # <%= end_form_tag %> # # The specified URL will then be passed a File object containing the selected file, or if the field # was left blank, a StringIO object. # # ==== Options # * Creates standard HTML attributes for the tag. # * :disabled - If set to true, the user will not be able to use this input. # # ==== Examples # file_field_tag 'attachment' # # => # # file_field_tag 'avatar', :class => 'profile-input' # # => # # file_field_tag 'picture', :disabled => true # # => # # file_field_tag 'resume', :value => '~/resume.doc' # # => # # file_field_tag 'user_pic', :accept => 'image/png,image/gif,image/jpeg' # # => # # file_field_tag 'file', :accept => 'text/html', :class => 'upload', :value => 'index.html' # # => class File < Trellis::Component render do |tag| end end # TODO: Need radio button group and a standalone radio button class Div < Trellis::Component render do |tag| attrs = tag.attr.exclude_keys('id', 'title') attrs['id'] = Utils.expand_properties_in_tag(tag.attr['id'], tag) if tag.attr['id'] attrs['title'] = Utils.expand_properties_in_tag(tag.attr['title'], tag) if tag.attr['title'] builder = Builder::XmlMarkup.new builder.div(attrs) { |div| div << tag.expand } end end end end