In MUM, most of the templates call Freemarker macros to display their content. We use macros to consistently generate user interface widgets in HTML. Macros are declared in our "widget" templates, the files /web/templates/widget_*.ftl, divided them in two areas:
- Widgets that display information to the user (even when they are interactive) are defined in the @show area.
- Widgets whose main purpose is to allow the user to input information are defined in the @edit area.
Nested content
Many of our macros use h3. Nested content. I strongly recommend that you make yourself confortable with the documentation of Freemarker macros.
Internationalization bundles and keys
MUM searches for keys following the ususal Webwork search order.
Information display macros
Macros to show data are declared inside the widget_show.ftl template.
TOP
@show.page
Shows the html header and body. This includes all necessary CSS and Javascript files, the document type, and so on. Any content you nest in this tag will be added to the body.
The macro also shows flash messages that might have been added by the actions.
Parameters
page title="" lookAndFeel="mum" pageTitle=title onLoad="" debug=false
- title (optional, default empty)
- the page's main header text.
- debug (optional boolean, default false)
- if true, will show field errors on the top of the page. It's useful during development.
- askForFeedback (optional boolean, default true)
- if true, will show the "send us comments" links on the page footer.
- lookAndFeel (optional, default mum)
- define the look and feel of the page
- onLoad (optional, default empty)
- a javascript to execute when the body finishes loading.
TOP
@show.tree
This higly specialized macro displays a tree starting from one Marbles object. It also generates javascript controls for drag-and-drop operations associated with an update action. When a node A is dropped on node B, the tree calls an action to update the system, passing A's id as the source id and B's id as the target id.
The root element is always a PObject, as are the first-level elements (which are displayed as the root's children, of course). For each element, the tree searches for its children property effectively displaying a tree of objects.
Parameters
- name (required)
- name of the tree
- updateAction (required)
- url of the action that will be called to update the tree.
- srcParam (required)
- name of the action paramater to pass the source node's id when a drop occurs.
- destParam (required)
- name of the action parameter to send the target node's id when a drop occurs.
- root (optional, default model)
- the persistent object to generate the tree from
- elements (optional, default root[name])
- you can override the first-level elements of the tree with this parameter
- highlight (optional, default empty)
- an object that must be highlighted when encountered in the tree (usually used for "the current value" kind of trees)
- rootIcon (optional, default empty)
- an icon to give for the root node.
- rootId (optional, default root.id)
- the id of persistent object
- rootName (optional, default root.name)
- the name of persistent object
- editable (true/false)
- if true, allows to drag and drop the nodes
Nested content
Each element from the tree is passed to the h3. Nested content, which is usually a @show.node macro.
Example
Here's the group tree call from MUM beta4:
<@show.tree updateAction="${base}/group/set-parent.action"
name="rootGroups"
root=zone
srcParam="groupId"
destParam="parentId"
rootIcon="${base}/pics/tree/branch_active.gif"
; node >
</@show.tree>
The call above will use the zone as root element, fetching the first level from the zone's rootGroups property. When a group g1 is dropped on a group g2, an Ajax post will call /{base}/group/set-parent.action?groupId={g1.id}&parentId={g2.id}. This macro will then pass each of the elements it fetched to the omitted inner tag, which contains @show.node tags.
TOP
@show.node
Displays a draggable tree node for use with @show.tree.
Parameters
- id (required)
- object's id
- label (required)
- the text to show as node content
- editable (required true/false)
- if true, allows to drag and drop the nodes
- draggable (optional, default true)
- if true, the node can be dragged
- droppable (optional, default true)
- if true, other nodes can be dropped onto this node
- onClick (optional, default empty)
- some javascript to execute when the node is clicked
- icon (optional, defautl empty)
- url of an image to use as node icon
- tooltip (optional, default empty)
- text to use as node tooltip ( title attribute).
Nested content
Whatever you nest inside the node will be considered additional content to be displayed when the user hovers the mouse over the node. Usually, we put links inside to make menus.
Example
The corresponding node call for the tree example above is:
<@show.node
id=node.id
label=node.name
icon="${base}/pics/tree/leaf.gif"
tooltip="drag node to move it">
<@show.link obj=node idParam="groupId" label="Manage group" />
</@show.node>
TOP
@show.tabbedPane
Displays a tabbed pane with user actions as links. See also @show.tab below.
Parameters
- name (required string)
- each tabbed pane on a page must have a unique name
- active (optional, default empty)
- if provided, will automatically open the tab with the given name.
TOP
@show.tab
Adds a tab to a tabbed pane. By default, tabs use an Ajax call to fetch content from the server and display it inside the tabbed pane. If the content is fetched with Ajax, any forms it contains will be modified to submit their content using Ajax too.
Parameters
- name (required)
- name of the tab, must be unique within the pane
- url (required)
- the url the tab-content is loaded using ajax
- title (optional, default empty)
- a title for the tab link
- newPage (optional boolean, default false)
- if true, the tab link will open in a new page
- linkClass (optional, default empty)
- an extra css class for the tab link
- separator (optional, defaults to "|")
- an extra span with the given text will be shown
- processForm (optional boolean, default true)
- if true, process the forms in the HTML result to use an ajax hook from the tabbed pane.
Example
<@show.tabbedPane name="main">
<@show.tab name="first" url="first.action?id=${someId?c}" />
<@show.tab name="second" url="second.action" processForm=false />
<@show.tab name="third" url="third.action" newPage=true separator="" />
</@show.tabbedPane>
The macro call above will create a tabbed pane called groupCrud with three tabs. The first two tabs will fetch their content using Ajax, but the second tab will not process its form. This means that the form delivered by second.action will submit to a new page (unless the form itself uses javascript to submit its contents).
The third tab is effectively a normal html link.
TOP
@show.text
Works exactly as @show.string
TOP
@show.time
This Macro will display an instance of org.joda.time.LocalTime or org.joda.time.TimeOfDay as a formatted String according to the locale submitted by the browser. If the requested locale is not found it defaults to U.S. format.
Parameters
- name (required)
- name of the time attribute
- obj (optional)
- the PObject (default: ${model})
- label (optional)
- the label for the property. By default it will be fetched from the bundle key label.{obj.type.name}.{name}, then label.property.{name}. If the argument is missing and none of the keys is found, it uses the value of the name parameter
- cssClass (optional, defaults to "label")
- a CSS class to give to the paragraph.
TOP
@show_date
This Macro will display an instance of org.joda.time.DateMidnight as a formatted String according to the locale submitted by the browser. If the requested locale is not found it defaults to U.S. format.
Parameters
- name
- name of the time attribute
- obj(optional)
- the PObject (default: ${model})
- label (optional)
- the label for the property. By default it will be fetched from the bundle key label.{obj.type.name}.{name}, then label.property.{name}. If the argument is missing and none of the keys is found, it uses the value of the name parameter
- cssClass (optional, defaults to "label")
- a CSS class to give to the paragraph.
TOP
@show.a
Shows an html <a> tag, trimmed at the borders and safe against html hacking (see the freemarker documentation for more details).
Parameters
- target (required)
- url of the link target
- label (required)
- link text to show (inside the <a> element)
- title (optional, default empty)
- the link title (shown by most browsers as a tooltip).
- targetFrame (optional, default _top)
- define wich window will open the link
TOP
@show.menu
Shows a menu with user options. Use with @show.menuItem.
Parameters
- title (optional string, default empty)
- menu title as text. The macro searches the bundle key menu.{title} or gives the text as plain text.
- showHome (optional boolean, defaults to true)
- if true shows a link to the home page (/index.action) at the beginning.
- homeLink
- url for the home
TOP
@show.menuItem
Shows one link in a menu.
Parameters
- target (required)
- URL for the link target
- label (required)
- the link text. The macro searches the bundle key menu.{label}, then {label}, then gives it back as plain text.
- title (optional, default empty)
- the link title (shown by most browsers as a tooltip).
- targetFrame (optional, default _top)
- define wich window will open the link
TOP
@show.string
Shows a paragraph displaying one property of an object. It's intended to be used with Marbles objects but if you provide a label, anything will do.
Parameters
- name (required)
- name of the property
- obj (optional, defaults to model)
- object from which to fetch the property
- label (optional)
- the label for the property. By default it will be fetched from the bundle key label.{obj.type.name}.{name}, then label.property.{name}. If the argument is missing and none of the keys is found, it uses the value of the name parameter
- defaultValue (optional, default empty)
- default value used when the property is empty.
- cssClass (optional, defaults to "label")
- a CSS class to give to the paragraph.
TOP
@show.elementList
Shows an element list inside a <ul> tag. It's only used internally, but you might want to write your own macros with it.
Parameters
- name (required)
- the list's name
- elements (required)
- a sequence (i.e. a list, set, array, etc) of objects
- idPrefix (required)
- a prefix to the ids of the HTML elements
- cssClass (optional, default empty)
- a CSS class to the <ul> element.
Nested content
The macro will print the Nested content inside each <li> element it produces, passing the element as parameter. See the @show.collection macro below for a good example (@show.collection uses @show.elementList).
TOP
@show.collection
Shows a list of objects. It's used for lists and search results, taking care of proper HTML semantic.
Parameters
- elements
- The collection of objects that will be displayed
- title (optional string, default empty)
- list title, displayed inside an <h2> header when provided. The macro searches the bundle key message.results.{title} and passes the collection size as an argument.
Nested content
The Nested content will be called for each of the collection elements, appearing inside <li> elements. Example:
<@show.collection elements=["one", "two", "three"] title="numbers" ; el >
little piggy number ${el?html}
</@show.collection>
Let's say I have an i18n message with key message.results.numbers and value "little piggy number {0}". The HTML output for the call above will be (element ids ellipsed):
<div class="results">
<h2>Showing 3 piggies</h2>
<ul id="..." >
<li id="...">little piggy number one</li>
<li id="...">little piggy number two</li>
<li id="...">little piggy number three</li>
</ul>
</div>
TOP
@show.link
Displays a link to perform an action on a persistent (i.e. Marbles) object.
Parameters
- obj (optional, default model)
- the persistent object to manipulate
- actionName (optional, default "view")
- the name of the action to be called.
- namespace (optional)
- the namespace to call the action, used to build the URL. By default, we use the object's type lowercased, so that an object of type "Zone" has a namespace "/{base}/zone", where {base} is the web application root.
- idParam (optional)
- the name of the parameter to send as the object id. Defaults, like the namespace, to the lowercase form of the object's type, but followed by "Id". So an object of type "Group" has the idParam set to "groupId" by default.
- label (optional, default empty)
- used to to find the bundle key. See below for a complete explanation.
- linkMessageKey (optional, default "link.message")
- used to build the title property of the <a> tag.
- targetFrame (optional, default _top)
- define wich window will open the link
- cssClass (optional, default empty)
- class name for the link
- attribute (optional, default name)
- the attribute used to get the data to show.
Label and title
The link's labels and titles are fetched from the resource bundle, usually using the object type. The title is fetched trying the keys action.{obj.type.name}.{actionName}, then action.{actionName}. This title is passed as default value and also as a parameter to {linkMessageKey}. For example, let's say the key action.Group.view is defined as "manage group", and the key link.message is defined as the message format "click to {0}" (this is the default, actually). The final title for the link will be "click to manage group".
If a label parameter is given, we search action.{obj.type.name}.{label}, then action.{label}, then {label}. If it's not provided, we load the message format in message.{obj.type.name}.{actionName}, then message.{actionName}, passing the object's name as parameter.
Example
Let's say you want to link to an object of type "User" with id 34 and name "dukejeffrie"
<@show.link obj=user />
This will generate a link similar to:
<a href="/user/view.action?userId=34" title="click to view">dukejeffrie</a>
TOP
@show.info
Shows an information box with one HTML paragraph. Used for notifications to the user such as "your request is being processed."
Parameters
- title (optional, default empty)
- title text, shown in an <h2> tag if provided. The macro searches the bundle key label.info. {title} and passes the value through if not found.
Example
<@show.info>All your bases are belong to us</@show.info>
will be translated as:
<div class="information">
<p>All your bases are belong to us</p>
</div>
TOP
@show.help
Shows a help box with an optional title.
Parameters
- title (optional, default "Did you know...")
- title text, shown in an <h2> tag if provided.
TOP
@show.screenshot
Shows a screenshot image inside a div (so it's formatted properly)
Parameters
- file
- a filename to be looked under the path /pics/screenshots/.
-
- title
- the image title
- alt
- alternate text, defaults to the image title.
TOP
@show.flashMessages
Shows flash messages created by previous actions to the user. Flash messages are useful when an action executes and then redirects to another url, but needs to show a notification. It creates a <div> with class "flash_messages" and shows each message inside a paragraph. This macro has no parameters
TOP
@show.errors
Shows all action and field errors inside a div with class "errors". Useful for displaying what's wrong when an action fails.
Parameters
- title (optional, defaults empty)
- if provided, the macro adds a tag <h2> with the given text inside the div.
- showFieldErrors(optional, defaults true)
- if true will show field errors.
- showActionErrors=true (optional, defaults true)
- if true will show the action errors.
TOP
Information input macros
Macros to show data are declared inside the widget_edit.ftl template.
TOP
@edit.emptyModel
This function gets a name and returns a hash that can be used to replace an empty Marbles object inside a template. We use it mostly for creation forms.
Parameters
- typeName (required)
- the name of a persistent type. Usually, it can be anything, but many macros use the type information to look up i18n keys.
Result
A hash with one key called type. The value of type is another hash with the mapping name => typeName.
TOP
@edit.form
Displays a form to edit a Marbles object. It's a very smart macro that is coupled with our action model, so it needs a more detailed description.
Parameters
- model (required)
- a Marbles object. The macro will pass this reference to other macros that display the property editors.
- formId (optional, default empty)
- id of the HTML
- namespace (optional)
- the namespace to call the action, used to build the URL. By default, we use the object's type lowercased, so that an object of type "Zone" has a namespace "/{base}/zone", where {base} is the web application root.
- actionName (optional, default "save")
- the name of the action to execute
- formAction (optional, default empty)
- value for the form action. If empty, the macro uses {path}{actionName}.action
- title (optional, default empty)
- a title for the form. If provided, text is shown inside an <h2> tag.
- idParam (optional)
- the name of the parameter to send as the object id. Defaults, like the namespace, to the lowercase form of the object's type, but followed by "Id". So an object of type "Group" has the idParam set to "groupId" by default.
- method (optional, default "post")
- the form submission method, as described in HTML specification.
- onSubmit (optional, default empty)
- javascript code to be executed upon submit.
- cssClass (optional, default empty)
- css class name.
- enctype (optional, default application/x-www-form-urlencoded)
- encryption type.
- target (optional, default empty)
- target.
Form confirmation
Some actions require a special confirmation token to prevent hacking scripts and <img> calls. The macro tests if a confirmation id is required and generates a hidden field called confirmationId for it.
Model id
If the model argument has an id, it's automatically included as a hidden field with name defined by the idParam parameter.
Nested content
The h3. Nested content is shown inside the