source: trunk/grails-app/taglib/dbnp/studycapturing/WizardTagLib.groovy @ 92

Last change on this file since 92 was 92, checked in by duh, 11 years ago
  • added sample template data in bootstrap
  • upgraded jQuery
  • improved study capture wizard
  • fixed selenium test
  • Property svn:keywords set to Rev Author Date
File size: 4.3 KB
Line 
1package dbnp.studycapturing
2import org.codehaus.groovy.grails.plugins.web.taglib.JavascriptTagLib
3
4/**
5 * Wizard tag library
6 *
7 * @author  Jeroen Wesbeek
8 * @since   20100113
9 * @package wizard
10 *
11 * Revision information:
12 * $Rev: 92 $
13 * $Author: duh $
14 * $Date: 2010-01-19 13:25:45 +0000 (di, 19 jan 2010) $
15 */
16class WizardTagLib extends JavascriptTagLib {
17  // define the tag namespace (e.g.: <wizard:action ... />
18  static namespace = "wizard"
19
20  // define the AJAX provider to use
21  static ajaxProvider = "jquery"
22
23  // define default text field width
24  static defaultTextFieldSize = 25;
25 
26  /**
27   * ajaxButton tag, this is a modified version of the default
28   * grails submitToRemote tag to work with grails webflows.
29   * Usage is identical to submitToRemote with the only exception
30   * that a 'name' form element attribute is required. E.g.
31   * <wizard:ajaxButton name="myAction" value="myButton ... />
32   *
33   * @see   http://blog.osx.eu/2010/01/18/ajaxifying-a-grails-webflow/
34   * @see   http://www.grails.org/WebFlow
35   * @see   http://www.grails.org/Tag+-+submitToRemote
36   * @todo  perhaps some methods should be moved to a more generic
37   *        'webflow' taglib
38   * @param Map     attributes
39   * @param Closure body
40   */
41  def ajaxButton = { attrs, body ->
42    // fetch the element name from the attributes
43    def elementName = attrs['name'].replaceAll(/ /,"_")
44   
45    // generate a normal submitToRemote button
46    def button = submitToRemote(attrs,body)
47
48    /**
49     * as of now (grails 1.2.0 and jQuery 1.3.2.4) the grails webflow does
50     * not properly work with AJAX as the submitToRemote button does not
51     * handle and submit the form properly. In order to support webflows
52     * this method modifies two parts of a 'normal' submitToRemote button:
53     *
54     * 1) replace 'this' with 'this.form' as the 'this' selector in a button
55     *    action refers to the button and / or the action upon that button.
56     *    However, it should point to the form the button is part of as the
57     *    the button should submit the form data.
58     * 2) prepend the button name to the serialized data. The default behaviour
59     *    of submitToRemote is to remove the element name altogether, while
60     *    the grails webflow expects a parameter _eventId_BUTTONNAME to execute
61     *    the appropriate webflow action. Hence, we are going to prepend the
62     *    serialized formdata with an _eventId_BUTTONNAME parameter.
63     */
64    button = button.replaceFirst(/data\:jQuery\(this\)\.serialize\(\)/, "data:\'_eventId_${elementName}=1&\'+jQuery(this.form).serialize()")
65
66    // render button
67    out << button
68  }
69
70  /**
71   * wizard navigation buttons render wrapper, in order to be able to add
72   * functionality in the future
73   */
74  def previousNext = { attrs ->
75    // define AJAX provider
76    setProvider([library:ajaxProvider])
77
78    // render navigation buttons
79    out << render(template:"/wizard/common/buttons")
80  }
81
82  /**
83   * render the content of a particular wizard page
84   * @param Map     attrs
85   * @param Closure body
86   */
87  def pageContent = { attrs, body ->
88    // define AJAX provider
89    setProvider([library:ajaxProvider])
90
91    // render new body content
92    out << render(template:"/wizard/common/tabs")
93    out << '<div class="content">'
94    out << body()
95    out << '</div>'
96    out << render(template:"/wizard/common/navigation")
97  }
98
99  def textFieldElement = { attrs, body ->
100    // set default size, or scale to max length if it is less than the default size
101    if (!attrs.get("size")) {
102      if (attrs.get("maxlength")) {
103        attrs.size = ((attrs.get("maxlength") as int) > defaultTextFieldSize) ? defaultTextFieldSize : attrs.get("maxlength") 
104      } else {
105        attrs.size = defaultTextFieldSize
106      }
107    }
108
109    // render a text element
110    out << '<div class="element">'
111    out << ' <div class="description">'
112    out << body()
113    out << ' </div>'
114    out << ' <div class="input">'
115    out << textField(attrs)
116    out << ' </div>'
117
118    // add help icon?
119    if (attrs.get('help')) {
120      out << ' <div class="help">'
121      out << '  <div class="icon"><img src="../images/icons/famfamfam/help.png"></div>'
122      out << '  <div class="content">'
123      out << '   <div class="text">'
124      out << '    '+attrs.get('help')
125      out << '   </div>'
126      out << '  </div>'
127      out << ' </div>'
128    }
129   
130    out << '</div>'
131  }
132}
Note: See TracBrowser for help on using the repository browser.