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

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