#
# Copyright (C) 2007 Mobio Networks, Inc.
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see .
#
require 'builder/xmlmarkup'
require 'rmobio/rxml/base_transformer'
require 'singleton'
module Rmobio
module Rxml
=begin rdoc
Provide a transformer to translate rxml document to xforms markup for Mobio client.
It subclasses BaseTransformer class and overwirtes the tag methods to produce the
proper xforms markup.
To get xforms transformer, pass the client type 'xf' to TransformerFactory get_transformer method:
require 'rmobio/rxml/transformer_factory'
@xml = TransformerFactory.get_transformer('xf')
or call the instance method to get the instance:
require 'rmobio/rxml/xforms_transformer'
@xml = XformsTransformer.instance
Here is an example rxml view that uses the transformer methods to output xforms document:
img = {:alt=>"Rails", :xstyle=>'height="5ex" width="100%"'}
@xml.doctimgype(xml) do |x|
@xml.body(x, 'mobio') do|body|
@xml.image(body, "img1", 'http://localhost:3000/images/rails.png',img)
@xml.softBr(body)
@xml.text(body, 'My test app')
end
end
The above code generates the following xforms for Mobio runner:
http://localhost:3000/images/rails.png
My test app
A rails icon and some text will be displayed on Mobio runner when you load the rxml page.
=end
class XformsTransformer < BaseTransformer
include Singleton
#Generate standdard xforms document header. The model output goes to
#instance variable @model_buffer and view output goes to instance variable
#@view_buffer. Any tag methods in the call block will be directed to either
#view or model buffer (depending on the tag method) and combined to produce
#the final document.
def doctype(xml)
xml << ''
@model_buffer = ''
@model_buffer << "\n"
# basic_styles
yield xml
@model_buffer << "\n\n"
xml << @model_buffer << @view_buffer
xml << ""
@view_buffer = ""
@model_buffer = ""
end
#Generate xthml head and body tag. The title argument is not used for xforms
#client. The style is optional. If style is specified,
#it will be added to the xforms style tag with src attribute:
#
#In rxml:
# @xml.body(x, 'mobio', 'default_style.xml')
#
#generates the following xforms markup:
#
#
#Please note, by default when client sees the src attribute, it is expecting
#the response content to be sent as 'application/xml' not 'application/mform' (for
#complete xforms document). For the styles to work, you will need to handle
#the url so it sends back the xml content with http content-type header set
#to 'application/xml'.
#
#An easier way to include external styles is to output the styles using
#builder xml (not transformer @xml) variable:
#
#==== Examples
# @xml.body(x, 'mobio') do |body|
# xml << render(:partial=> 'default_style.xml')
#The content in the style xml (note, it will be _default_style.xml) will
#then be embeded in the final document.
def body(doc, title="", style=nil)
# xforms style is external style
@view_buffer << '' if style
@view_buffer << "\n"
yield doc
@view_buffer << ''
@view_buffer << ""
end
#Produce a text string. The text displayed can be the _txt_ argument if there's
#no :id and :xpath options or it can be the data from model instance specified
#in :id and :xpath.
#
#==== Options
#
#* :xstyle -- specifies xforms style attributes like height, width, style,\
#etc. as string.
#* :id -- specifies the instance id of string. \
#If :id is specified but nso :xpath, the method creates an instance data in \
#@model_buffer with a tag name "text" that contains the _txt_ string.\
#If :id and :xpath are both specified, the method doesn't create any model instance,\
#instead, it assumes there's an instance with the id and xpath already defined\
#and the text widget displays the data in that xpath.
#* :xpath -- specifies the xpath of the text string in the instance model.\
#If :id is not specified, it assumes a relative path for the text node. \
#See the 3rd example. \
#* :value -- specifies the value attribute of text widget. \
#See the last example
#==== Examples
#* Text widget displays the string of _txt_ argument without creating an instance:
# @xml.text(body, 'My test', :xstyle=>'style="white"')
#
#generates the following xforms:
# My test
#The outupt is a one line text.
#* Text widget creates a model instance and displays the string from the new instance:
# @xml.text(body, 'My test',
# :id=>'txt1',
# :xstyle=>'style="white"')
#generates the following xforms:
#In model:
# My test
#In view:
#
#* Text widget displays string from a pre defined instance:
# @xml.text(body, 'My test', :id=>'txt1', :xpath=>'images/id')
#generates the following xforms:
#
#* Text widget displays string from a pre defined instance in a relative path:
# @xml.itemset(list, 'tb1', "instance('audios')/items/item") do |row|
# @xml.cell(row)do |cell|
# @xml.text(cell, "", :xpath=>'@name')
# end
# end
#generates the following xforms:
#
#
#
#
#
#* Text widget displays a string in value attribute:
# @xml.text(cell, "", :value=>"concat('tel:', instance('phones')/number)")
#generates the following xforms:
#
#
def text(doc, txt="", options={})
# If there's id but no xpath, we will create a default instance data for
# the textoutput.
if options[:id] and options[:xpath].nil?
@model_buffer << "\n" << '' << txt << "\n"
end
if options[:xstyle]
@view_buffer << "\n"
else
# If there's an xpath but no id, this is a relative pace, don't create any instance.
if options[:xpath]
@view_buffer << ' ref="' << options[:xpath] << '"/>'
elsif options[:value]
@view_buffer << " value=\"#{options[:value]}\"/>"
else
@view_buffer << ">" << txt << ""
end
end
end
def text_line(doc, txt="", options={})
text(doc, txt, options)
end
#Produce a textoutput widget (multi line text box).
#The text area is read only for xforms client.
#
#==== Options
#
#* :xstyle -- specifies xforms style attributes like height, width, style, \
#etc. as string.
#* :id -- specifies the instance id of string.
#If :id is specified but no :xpath, the method creates an instance data in
#@model_buffer with a tag name "text" that contains the _txt_ string.
#If :id and :xpath are both specified, the method doesn't create any model instance,
#instead, it assumes there's an instance with the id and xpath already defined
#and the textoutput widget displays the data in that xpath.
#* :xpath -- specifies the xpath of the text string in the instance model.
#
#==== Examples
# @xml.textoutput(body, 'My test', {:xstyle=>'style="white" height="2ex"'})
#
#generates the following xforms:
# My test
#The output is a 5 character high text box.
#
#==== Examples
#* Text widget displays the string of _txt_ argument without creating an instance:
# @xml.textoutput(body, 'My test box', :xstyle=>'height="3ex"')
#
#generates a 3 line text box:
# My test box
#* Text widget creates a model instance and displays the string from the new instance:
# @xml.textoutput(body, 'My test box',
# :id=>'txt1', :xstyle=>'height="3ex"')
#generates the following xforms:
#In model:
# My test
#In view:
#
#* Text widget displays string from a pre defined instance:
# @xml.textoutput(body, 'My test', :id=>'txt1', :xpath=>'images/id',
# :xstyle=>'height="5ex" width="50%"')
#generates the following xforms:
#
#
def textoutput(doc, txt="", options={})
# If there's id but no xpath, we will create a default instance data for
# the textoutput.
if options[:id] and options[:xpath].nil?
@model_buffer << "\n" << '' << txt << "\n"
end
@view_buffer << "\n"
else
@view_buffer << ">" << txt << ""
end
end # end textoutput
#
#Create user input field.
#1. id: The instance id that will be associated with this input field. An instance data \
#will be created automatically in the model if options[:xpath] is not specified. \
#The instance is created with only one tag: 'txt'.
#2. value: initial value that will be displayed when ui is loaded
#3. type: not used for xforms client
#==== Options
#* :xstyle -- specifies xforms style attributes as a string
#* :xpath -- specifies the xpath of the input data in the model
#==== Examples
#* Create a simple input box:
# @xml.input(body, "name", "john", "text")
#generates the following xforms:
#
#In Model section of the form:
#
# john
#
#In View section of the form:
#
#Notice the instance data is created automatically because the rxml tag
#didn't specify the :xpath argument. Mobio runner will display an input box with default
#value "john" in the box when the page is launched. User can edit the
#string in the box and the value will be assinged to the model instance('name')/txt.
#
#* The next example shows how to create an input tag with predefined instance data:
#Note, create the options hash before the beginning of the document)
# options = {
# :style=> 'style="white"',
# :xstyle=>'maxlength="10" style="white"',
# :xpath=>"images/id"}
# @xml.doctype(xml) do |x|
# @xml.body(x, 'mobio', 'default_style.xml') do|body|
# @xml.input(body, "img", "", "text", options)
# end
# end
#
#The above rxml generates only the view part in the xforms:
# ' << value << "\n"
end
@view_buffer << "\n"
else
@view_buffer << options[:xpath] << "\"/>"
end
end # end input
#Create multi lines input area. Similar to input tag except input tag only
#allow a single input line.
#1. id: The instance id that will be associated with this input field. An instance data \
#will be created automatically in the model if options[:xpath] is not specified. \
#The instance is created with only one tag: 'txt'.
#2. value: initial value that will be displayed when ui is loaded
#3. type: not used for xforms client
#==== Options
#* :xstyle -- specifies xforms style attributes as a string
#* :xpath -- specifies the xpath of the input data in the model
#==== Examples
#* Create a simple textarea:
# @xml.textarea(body, "name", "john", "text")
#generates the following xforms:
#
#In Model section of the form:
#
# john
#
#In View section of the form:
#
#Notice the instance data is created automatically because the rxml tag
#didn't specify the :xpath argument. Mobio runner will display an input box with default
#value "john" in the box when the page is launched. User can edit the
#string in the box and the value will be assinged to the model instance('name')/txt.
#
#* The next example shows how to create a textarea tag with predefined instance data:
#Note, create the options hash before the beginning of the document)
# options = {
# :style=> 'style="white"',
# :xstyle=>'height="3ex"',
# :xpath=>"images/id"}
# @xml.doctype(xml) do |x|
# @xml.body(x, 'mobio', 'default_style.xml') do|body|
# @xml.textarea(body, "img", "", "text", options)
# end
# end
#
#The above rxml generates only the view part in the xforms:
# ' << value << "\n"
end
@view_buffer << "\n"
else
@view_buffer << options[:xpath] << "\"/>"
end
end # end textarea
#Implement xforms in view buffer and tag in model buffer
#If argument 'create_instance' is set to true, it will create an instance
#based on the attributes (see options). Otherwise, it assumes an instance is
#already defined in the model. The submit_tag can not act along, it has to be
#associated with a tag with UI (like link tag, button or menu item where
#user can click on).
#
#1. id: the name of the model instance that contains the submission defintion
#2. create_instance: true or false, create submission model instance or not.
#If set to true, a new model instance will be created.
#==== Options
#To create submission model, the following attributes should be specified in options:
#* :action -- specifies the url for the action
#* :req_id -- specifies the instance id to hold the submission data
#* :replace_id -- if specified, the submission replace attribute is\
#set to "instance"; otherwise, the submission replace attribute is set to "all". \
#In case of "all", the client is expecting a complete xforms document in \
#response. If it's "instance", only the request_id instance data is updated \
#with the response data. Note the response header should be set to \
#"application/xml" instead of "application/xforms" for "instance" replace.\
#See Mobio client user manual for defails.\
#* :event -- specifies event type to trigger the action. \
#If not defined, "DOMActivate" will be used.
#==== Examples
#* First example demonstrates a submit tag (wrapped in link widget) that \
#creates a submit action and submission instance. When user clicks on the link, \
#the response will replace only the instance data in "results". The UI \
#doesn't change.
#
#Create two instances for the submission to hold the request and replace data:
# (Request data)
# @xml.instance_tag(body, "name") do |y|
# @xml.fname
# end
#
# (Instance to hold the response data)
# @xml.instance_tag(body, "results")
#
#Use link to provide a UI for user to activate the submission, specify true for
#create_instance argument so a new submission instance data can be created:
#
# @xml.link(body, "http://m.twitter.com", "m.twitter.com") do |link|
# @xml.submit_tag(link, "login", true,
# :action=>'login', :req_id=>'name', :replace_id=>'results')
# end
#generates the following xforms:
#
#In the model:
#
#
#In the view:
#
#
#* In this example, we will create a submit tag that creates just the submit button\
# and use an existing submission instance to invoke the action. The response \
# is a complete xforms document which replaces the whole UI:
#
# @xml.link(body, "http://m.twitter.com", "m.twitter.com") do |link|
# @xml.submit_tag(link, "login", false,
# :action=>'login', :req_id=>'name', :replace_id=>'results')
# end
#
#generates only a view:
#
#The submission instance with id "login" must exist for the button to work.
#
def submit_tag(doc, id, create_instance, options={}, &block)
# The model
if create_instance
@model_buffer << "\n'
end
# The view
@view_buffer << "\n"
if block
yield doc
end
@view_buffer << ""
end
#Not supported for xforms client. Just pass the block. Xforsm client should
#use instance_tag, submit_tag for form submission.
def form(doc, id, action, method)
yield doc
end
#There's no link widget in Mobio client so use a button widget to provide
#the same feature for html link. If url is provided and there's no call block,
# will be used to invoke the url. Otherwise, the call block
#will be executed and template can provide specifal action using the action tag.
#or view_tag.
#Default event type is ev:event="DOMActivate" for the button.
#1. url: the http get url when user press the button, only valid if there's\
#no call block
#2. txt: label displayed on the button
#==== Options
##* :xstyle -- specifies xforms style attributes like height, width, style, \
#etc. as string.
#
#==== Examples
#* Simple link:
# @xml.link(body, "http://m.twitter.com", "Twitter")
#generate the following xforms:
# Twitter
#
#
#* Customize action:
# @xml.link(body, "http://m.twitter.com", "Twitter") do |link|
# @xml.view_tag(link, '')
# end
#generates the following xforms:
# Twitter
#
#
#
def link(doc, url, txt="", options={}, &block)
@view_buffer << "\n' << txt << ''
# If no action provided, use to load the url
if block
yield doc
else
@view_buffer << ''
end
@view_buffer << ''
end
#Create button control. If there's no call block,
# will be used to invoke the url. Otherwise, the call block
#will be executed and template can provide specifal action using any of
#the action tags or view_tag.
#Default event type is ev:event="DOMActivate" for the button.
#1. url: the http get url when user press the button, only valid if there's\
#no call block
#2. label: label displayed on the button
#==== Options
##* :xstyle -- specifies xforms style attributes like height, width, style, \
#etc. as string.
#
#==== Examples
#* Simple link:
# @xml.button(body, "http://m.twitter.com", "Twitter")
#generate the following xforms:
# Twitter
#
#
#* Customize action:
# @xml.button(body, "http://m.twitter.com", "Twitter") do |link|
# @xml.view_tag(link, '')
# end
#generates the following xforms:
# Twitter
#
#
#
def button(doc, url, label, options={}, &block)
@view_buffer << "\n' << label << ''
# If no action provided, use to load the url
if block
yield doc
else
@view_buffer << ''
end
@view_buffer << ''
end
#Output arbitray stuff in the model buffer. A workaround for any special xforms
#tags that are not supported yet in the transformer.
def model_tag(doc, txt)
@model_buffer << txt
end
#Output arbitray stuff in the view buffer. A workaround for any special xforms
#tags that are not supported yet in the transformer.
def view_tag(doc, txt)
@view_buffer << txt
end
#Line break
def softBr(doc)
@view_buffer << ''
end
#Create image widget. There are two types of image control: icon and image.
#See Mobio client user manual for details.
#1. src: the url of the image
#2. options: all other attributes
#==== Options
#* :xstyle -- specifies xforms style attributes like height, width, style, \
#etc. as string.
#* :widget -- specifies the widget to use, "icon" or "image". Default\
#is .
#* :xpath -- specifies the xpath of the data instancen that contains \
#the image url.
#
#==== Examples (
#* Create a simple image control\
#Note, define the style options outside the doctype block):
# img = {:alt=>"Rails", :xstyle=>'height="5ex" width="100%"'}
# @xml.doctype(xml) do |x|
# @xml.body(x, 'default_style.xml') do|body|
# @xml.image(body, "img1", 'http://localhost:3000/images/rails.png',img)
# end
# end
#generates the following xforms:
# http://localhost:3000/images/rails.png
#The image will be scaled to 5 character high on the screen when the page is loaded.
#* This example creates an icon widget which takes the image url from an \
#instance variable:
# @xml.image(body, 'http://localhost:3000/images/rails.png',
# {:xstyle=>'height="3ex" width="20em"',
# :xpath=>"instance('img1')/images/url",
# :widget=>"icon"})
#generates the following xforms:
#
#The icon takes the url from an instance named "img1" with xpath /images/url.
#The instance data has to be defined for the image to be displayed.
def image(doc, src=nil, options={})
widget = "image"
widget = options[:widget] if options[:widget]
@view_buffer << "\n"
else
@view_buffer << '>' << src
end
@view_buffer << ""
end
#Create an instance in the model
#1. id: the name of the instance that will be created
#2. src: the src of the instance data. If src is specified, the call block
#will not be executed.
#==== Examples
#* Create a blank instance:
# @xml.instance_tag(body, "foo")
#generates the following xforms in the model:
#
#
#* Combine instance_tag with any xml tag to create a useful instance model:
# @xml.instance_tag(body, "name") do |y|
# @xml.fname
# @xml.lname("Doe")
# @xml.info("Basic", :zip=>"95014", :phone=>"415-1111111")
# end
#generates the instance data in the model:
#
#
#
# Doe
# Basic
#
#
#
#* Create an instance from a src url. The src url should return the instance \
#data with HTTP content-type set to 'application/xml'. The instance data is \
#RELOADED every time the page is requested no matter it's cached or not. \
#This is useful when you want the whole xforms UI cached but a small \
#set of instance data be refreshed every time user reloads the page.
#
# @xml.instance_tag(body, "", "get_data")
#
#The rxml generates the following xforms in the model:
#
#
#and the template for url "get_data" returns this: (note the content-type header)
# <% headers['Content-Type']='application/xml' %>
#
# Lunch?
# Meeting reminder
# Your account activities
#
#
#* Create an instance with multiple layers:
#
# @xml.instance_tag(body, "photos") do |x|
# @xml.items do |y|
# @xml.item("image1")
# @xml.item("image2")
# end
# end
#generates the following instance in xforms model:
#
#
#
# - image1
# - image2
#
#
#
def instance_tag(doc, id, src=nil, &block)
if src.nil?
@model_buffer << "\n\n\n"
if block
yield doc
end
@model_buffer << "\n"
else
@model_buffer << "\n"
end
end
def vstack(doc, xstyle='height="0"')
@view_buffer << ""
yield doc
@view_buffer << ""
end
def hstack(doc, xstyle='height="0"')
@view_buffer << ""
yield doc
@view_buffer << ""
end
#Create grid control, similar to table in html.
#==== Options
#* :style -- specifies html, xhtml style attributes as a string
#* :xstyle -- specifies xforms style attributes as a string
#==== Examples
# Create photos instance:
# @xml.instance_tag(body, "photos") do |x|
# @xml.items do |y|
# @xml.item("image1", :val=>'1')
# @xml.item("image2", :val=>'2')
# end
# end
#
# Create grid widget:
# @xml.table(body) do |tbl|
# @xml.row(tbl, "mylist", "instance('photos')/items/item", :xstyle=>'col="auto"') do |row|
# @xml.cell(row) do |td|
# @xml.text(td, "", :xpath=>'.')
# @xml.text(td, "", :xpath=>'@val')
# end
# end
# end
#Generates the following xforms:
#In the model:
#
#
# - image1
- image2
#
#
#
#In the view:
#
#
#
#
#
#
#
#
#The UI is a table with 2 columns and 2 rows of text data.
def table(doc, options={})
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create grid rowset control, similar to in html.
#1. id - the widget id
#2. nodeset - the xpath to the instance data
#==== Options
#* :style -- specifies html, xhtml style attributes as a string
#* :xstyle -- specifies xforms style attributes as a string
def row(doc, id=nil, nodeset=nil, options={})
@view_buffer << ""
yield doc
@view_buffer << ''
end
#Create grid rowlist control. similar to
in html.
#1. id - the widget id
#==== Options
#* :style -- specifies html, xhtml style attributes as a string
#* :xstyle -- specifies xforms style attributes as a string
def row_list(doc, id, options={})
@view_buffer << ""
yield doc
@view_buffer << ''
end
#Create control which takes a nodeset attribute and iterates
#items in the nodese
#1. id - the widget id
#2. nodset - the xpath to the instance data
#==== Options
#* :style -- specifies html, xhtml style attributes as a string
#* :xstyle -- specifies xforms style attributes as a string
def itemset(doc, id, nodeset, options={})
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create control with static data.
#1. id - the widget id
#==== Options
#* :style -- specifies html, xhtml style attributes as a string
#* :xstyle -- specifies xforms style attributes as a string
def itemlist(doc, id, options={})
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create control.
#==== Options
#* :style -- specifies html, xhtml style attributes as a string
#* :xstyle -- specifies xforms style attributes as a string
def cell(doc, options={})
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create control.
#==== Options
#* :style -- specifies html, xhtml style attributes as a string
#* :xstyle -- specifies xforms style attributes as a string
def list(doc, options={})
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create a Tab control
#1. xstyle: the xforms style string.
# The tag is always followed by several xcase tags to create a complete UI \
# for Tabs.
#
#==== Examples
#Create a tab control that contains 2 case in the tab body and header:
#
# @xml.tab(body) do |tab|
# @xml.xcase(tab, "first", "Current Match", 'style="tab"') do |xcase|
# @xml.text(body, "hello world!")
# end
# @xml.xcase(tab, "2nd", "future", 'style="tab"') do |xcase|
# @xml.text(body, "hello world!")
# end
# end
#generates the following xforms in the view:
#
#
# hello world!
#
#
# Second Page
#
#
#
def tab(doc, xstyle='width="100%" height="100%"')
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create swtich case control, similar to Tab control but without the tab UI.
#This tag and xcase tag can create muliple switch
#case for xforms client to provide multiple UIs in a form that can be toggled
#back and forth using the xf:toggle command. Refer to client user manual
#for the usage.
#
#==== Examples
# @xml.switch(body) do |tab|
# @xml.xcase(tab, "b") do |c1|
# @xml.text(c1, "hello world!")
# end
# @xml.xcase(tab, "a") do |xcase|
# @xml.text(body, "hello world!")
# end
# end
#generates the following:
#
#
# hello world!
#
#
# hello world!
#
#
def switch(doc)
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create a case control. This tag cannot act along. It has to be wrapped in
#either a "switch" tag or a "tab" tag.
#See the document and examples in tab and switch tag.
#1. id: the case reference id
#2. label: what is displayed in the tab header (only needed in tab case)
#3. xstyle: the xforms style string for the case (only needed in tab case).
def xcase(doc, id, label=nil, xstyle=nil)
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create a softkey menu.
#1. position: "1" for left softkey and "3" for right softkey
#2. label: what is displayed in the tab header (only needed in tab case)
#3. xstyle: the xforms style string for the case (only needed in tab case)
#
#==== Examples
#* Softkey with a load action. The left softkey is created with label "GO" \
#and will load page foo2.xml when the softkey is pressed.
# @xml.softkey(body, "1", "GO") do |soft1|
# @xml.load_tag(soft1, "foo2.xml")
# end
#generates the following:
#
# GO
#
#
#
#* Softkey that pops up an Options menu. When right softkey is pressed, a popup\
#menu "Options" will display 4 menu items. The first 3 menu items are assigned\
#a default accesskey. The last menu item defines its own access key "0" \
#which is reserved for exit action.
# @xml.softkey(body, "3", "Options", "menu1")
# @xml.menus(body, "menu1", "Options") do |menus|
# @xml.menu(menus, "move1") do |item|
# @xml.load_tag(item, "foo1.xml")
# end
# @xml.menu(menus, "move2") do |item|
# @xml.load_tag(item, 'foo2.xml')
# end
# @xml.menu(menus, "move3")
# @xml.menu(menus, "exit", "0") do |item|
# @xml.view_tag(item, '')
# end
# end
# end
#genereates the following:
#
# Options
#
#
#
#
def softkey(doc, position="1", label="", refid=nil, &block)
@view_buffer << "\n#{label}"
# If we have a refid, setup a popup for the child menus; otherwise, execute
# the proc to take action.
if refid.nil? and block
yield doc
else
@view_buffer << ""
end
@view_buffer << "\n"
end
#A holders for a popup menu.
#1. id: the widget's reference id. The id is used by softkey to trigger the popup\
#action.
#2. label: what is displayed on the title of the popup window. Default label \
#is "Options".
#3. xstyle: the xforms style string for the popup window. If xstyle is not \
#specified, default style string "width='40%'" is used.
#==== Examples
#Refer to softkey examples
def menus(doc, id, label="Options", xstyle=nil)
@view_buffer << "\n" if xstyle
else
@view_buffer << " width=\"40%\">"
end
@view_buffer << "\njar://img/option.png"
@view_buffer << "\n#{label}"
@accesskey=0
@view_buffer << "\n "
yield doc
@view_buffer << "\n"
@view_buffer << "\n\n\n\t\n\tClose\n\n"
end
#Create an action item in a popup menu.
#1. label: what is displayed on the title of the popup window. Default label \
#is "Options".
#2. accesskey: A short cut key (0-9) that is assigned to this menu item. If \
#not specified, it is asssinged a number sequentially.
#3. xstyle: the xforms style string for the menu item.
#==== Examples
#Refer to softkey examples
def menu(doc, label, accesskey=nil, xstyle=nil, &block)
@view_buffer << "\n"
@view_buffer << "\n" << label << ""
if block
yield doc
end
@view_buffer << "\n"
end
#Create control to do a HTTP get for a new form. Default event
#is "DOMActivate".
#1. resource: the resource url that will be loaded.
#
#==== Examples
# @xml.softkey(body, "1", "GO") do |soft1|
# @xml.load_tag(soft1, "foo2.xml")
# end
#generates the following:
#
# GO
#
#
#
def load_tag(doc, resource)
@view_buffer << "\n"
end
#Create syscall control. Refer to mobio client user manual for details usage
#of sysacll.
#1. name: the name of the syscall function. The client supports "click2call",
#"sendSMS", "audio-playback", "video-playback" and saveToPhone functions. \
#See Client User Manual for details.
#
#==== Params
#One or more parameters can be added to build the syscall by passing the param \
#name and value as a Hash. Avaliable params are:
#* :address -- specifies the phone number for click2call and sendSMS \
#or the instance data for audio and video url.
#* :message -- specifies the text message instance for sms.
#* wallpaper -- specifies the wallpaper instance.
#* ringtone -- specifies the ringtone instance.
#
#==== Examples
#* Create a button that plays an audio file, the url for the audio file should\
#be defined using an instance tag.
# @xml.button(body,"", "btn1") do |btn|
# @xml.syscall(btn, "audio-playback", :address => "instance('audios')/items/item[1]")
# end
#generates the following:
#
# btn1
#
#
#
#
#When user selects the button 'btn1', the audio file will be loaded and played.
#
#* Create a button that places a phone call:
# @xml.instance_tag(body, "phone") do |x|
# @xml.number("tel:5551212")
# end
# @xml.button(body,"", "btn1") do |btn|
# @xml.syscall(btn, "click2call", :address => "instance('phone')/number")
# end
#
#generates the following:
#
#In model
#
#
# tel:5551212
#
#
#
#In view
#
# btn1
#
#
#
#
#When user selects the button "btn1", it places a phone call to the number.
#The syscall for btn1 uses the phone number from instance data.
#
#* Create a button that saves a ringtone to the device:
# @xml.button(body,"", "btn1") do |btn|
# @xml.syscall(btn, "saveToPhone", :ringtone => "instance('store')/ringtone")
# end
#
#generates the following:
#
#
# btn1
#
#
#
#
def syscall(doc, name, params={})
@view_buffer << "\n"
if not params.nil?
params.keys.each do |x|
@view_buffer << "\n\t"
end
end
@view_buffer << "\n"
end
#Generate a click2call syscall control to a phone number
#1. phone: the phone number for the click2call control
#
#==== Examples
#* Create a button that triggers a call to the phone number:
# @xml.button(body,"", "btn1") do |btn|
# @xml.click2call(btn, "4085551212")
# end
#generates the following:
#
# btn1
#
# tel:4085551212
#
def click2call(doc, phone)
@view_buffer << "\n\n\ttel:#{phone}\n"
end
#Create Action control. Default event is "DOMActivate" if event argument is
#not defined.
#1. event: the name of DOM event to trigger the action. Refer to Mobio client\
#user manual for all event types.
#==== Examples
# @xf.action_tag(body) do |a|
# end
#generates an action control with default DOM event:
#
#
#
# @xf.action_tag(body, "xforms-ready") do |a|
# end
#generates an action control with "xforms-ready" event:
#
#
#
def action_tag(doc, event="DOMActivate")
@view_buffer << "\n"
yield doc
@view_buffer << "\n"
end
#Create exit control to exit the client.
#==== Examples
# @xml.softkey(body, "1", "exit") do |soft1|
# @xml.exit_tag(soft1)
# end
#generates a left softkey that exits the client:
#
# exit
#
#
def exit_tag(doc)
@view_buffer << "\n"
end
#Create back control to go back to previous page.
#==== Examples
# @xml.softkey(body, "3", "back") do |soft1|
# @xml.back_tag(soft1)
# end
#generates a right softkey that go back to previous page:
#
# back
#
#
def back_tag(doc)
@view_buffer << "\n"
end
#Create toggle control
#1. name: the toggle case name, default is "main" if not defined.
#==== Examples
# @xml.softkey(body, "3", "back") do |soft1|
# @xml.toggle_tag(soft1)
# end
#generates a toggle control to go back to "main" switch case:
#
#
# @xml.softkey(body, "3", "back") do |soft1|
# @xml.toggle_tag(soft1, "view")
# end
#generates a toggle control to go back to a switch case named "view":
#
#
def toggle_tag(doc, name="main")
@view_buffer << "\n"
end
#Override builder method_missing method to send output to model buffer so we
#can create arbitrary xml tags in the model. Typically combine with instance_tag
#to create model instance that can be used in any of the action tag (link, submit_tag, etc.)
#
#====Examples
# @xml.instance_tag(body, "user") do |y|
# @xml.fname
# @xml.lname("Doe")
# @xml.info("Basic", :zip=>"95014", :phone=>"415-1111111")
# end
#generates an instance data in the model:
#
#
#
# Doe
# Basic
#
#
def method_missing(sym, *options, &block)
text = nil
attrs = nil
sym = "#{sym}:#{options.shift}" if options.first.kind_of?(Symbol)
options.each do |arg|
case arg
when Hash
attrs ||= {}
attrs.merge!(arg)
else
text ||= ''
text << arg.to_s
end
end
if block
unless text.nil?
raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
end
_indent
_start_tag(sym, attrs)
_newline
_nested_structures(block)
_indent
_end_tag(sym)
_newline
elsif text.nil?
_indent
_start_tag(sym, attrs, true)
_newline
else
_indent
_start_tag(sym, attrs)
text! text
_end_tag(sym)
_newline
end
end
private
def _text(text)
@model_buffer << text
end
# Start an XML tag. If end_too is true, then the start
# tag is also the end tag (e.g.
def _start_tag(sym, attrs, end_too=false)
@model_buffer << "<#{sym}"
_insert_attributes(attrs)
@model_buffer << "/" if end_too
@model_buffer << ">"
end
# Insert an ending tag.
def _end_tag(sym)
@model_buffer << "#{sym}>"
end
# Insert the attributes (given in the hash).
def _insert_attributes(attrs, order=[])
return if attrs.nil?
order.each do |k|
v = attrs[k]
@model_buffer << %{ #{k}="#{_attr_value(v)}"} if v # " WART
end
attrs.each do |k, v|
@model_buffer << %{ #{k}="#{_attr_value(v)}"} unless order.member?(k) # " WART
end
end
# Put some default styles if user doesn't specify any
def basic_styles
#@model_buffer << ""
# took out all basic styles because client has provided a default style
#@model_buffer << ""
end
# End builder methods
end
end
end