Changeset 96
- Timestamp:
- Jan 19, 2010, 4:18:33 PM (13 years ago)
- Location:
- trunk/grails-app
- Files:
-
- 3 deleted
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/taglib/dbnp/studycapturing/WizardTagLib.groovy
r92 r96 1 1 package dbnp.studycapturing 2 2 3 import org.codehaus.groovy.grails.plugins.web.taglib.JavascriptTagLib 3 4 … … 5 6 * Wizard tag library 6 7 * 7 * @author 8 * @since 8 * @author Jeroen Wesbeek 9 * @since 20100113 9 10 * @package wizard 10 11 * … … 15 16 */ 16 17 class WizardTagLib extends JavascriptTagLib { 17 18 18 // define the tag namespace (e.g.: <wizard:action ... /> 19 static namespace = "wizard" 19 20 20 21 21 // define the AJAX provider to use 22 static ajaxProvider = "jquery" 22 23 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) 24 // define default text field width 25 static defaultTextFieldSize = 25; 47 26 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()") 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'] 65 45 66 // render button 67 out << button 68 } 46 // fetch the element name from the attributes 47 def elementName = attrs['name'].replaceAll(/ /, "_") 69 48 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]) 49 // generate a normal submitToRemote button 50 def button = submitToRemote(attrs, body) 77 51 78 // render navigation buttons 79 out << render(template:"/wizard/common/buttons") 80 } 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 } 81 76 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]) 77 // render button 78 out << button 79 } 90 80 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 } 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]) 98 88 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 } 89 // render navigation buttons 90 out << render(template: "/wizard/common/buttons") 91 } 108 92 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>' 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]) 117 101 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 } 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 def textFieldElement = {attrs, body -> 111 // set default size, or scale to max length if it is less than the default size 112 if (!attrs.get("size")) { 113 if (attrs.get("maxlength")) { 114 attrs.size = ((attrs.get("maxlength") as int) > defaultTextFieldSize) ? defaultTextFieldSize : attrs.get("maxlength") 115 } else { 116 attrs.size = defaultTextFieldSize 117 } 118 } 119 120 // render a text element 121 out << '<div class="element">' 122 out << ' <div class="description">' 123 out << body() 124 out << ' </div>' 125 out << ' <div class="input">' 126 out << textField(attrs) 127 out << ' </div>' 128 129 // add help icon? 130 if (attrs.get('help')) { 131 out << ' <div class="help">' 132 out << ' <div class="icon"><img src="../images/icons/famfamfam/help.png"></div>' 133 out << ' <div class="content">' 134 out << ' <div class="text">' 135 out << ' ' + attrs.get('help') 136 out << ' </div>' 137 out << ' </div>' 138 out << ' </div>' 139 } 140 141 out << '</div>' 142 } 132 143 } -
trunk/grails-app/views/layouts/main.gsp
r54 r96 2 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3 3 <html xmlns="http://www.w3.org/1999/xhtml" lang="en-EN" xml:lang="en-EN"> 4 <head> 5 <title><g:layoutTitle default="Grails" /></title> 6 <link rel="stylesheet" href="${resource(dir:'css',file:session.style+'.css')}" /> 7 <link rel="stylesheet" href="${resource(dir:'css',file:'login_panel.css')}" /> 8 <link rel="shortcut icon" href="${resource(dir:'images',file:'favicon.ico')}" type="image/x-icon" /> 9 <my:jquery/> 10 <!-- layouthead //--> 11 <g:layoutHead /> 12 <!-- /layouthead //--> 13 <script type="text/javascript" src="${resource(dir:'js', file:'login_panel.js')}"></script> 14 <script type="text/javascript" src="${resource(dir:'js', file:'topnav.js')}"></script> 15 </head> 16 <body> 17 <g:render template="/common/login_panel" /> 18 <div class="container"> 19 <div id="header"> 20 <g:render template="/common/topnav" /> 21 </div> 22 <div id="content"><g:layoutBody /></div> 23 <div id="footer"> 24 Copyright © 2008 - <g:formatDate format="yyyy" date="${new Date()}"/> NMC & NuGO. All rights reserved. 25 ( style: <%=session.style%>, 26 <a href="?showSource=true">show page source</a>)</div> 27 </div> 28 </body> 4 <head> 5 <title><g:layoutTitle default="Grails"/></title> 6 <link rel="stylesheet" href="${resource(dir: 'css', file: session.style + '.css')}"/> 7 <link rel="stylesheet" href="${resource(dir: 'css', file: 'login_panel.css')}"/> 8 <link rel="shortcut icon" href="${resource(dir: 'images', file: 'favicon.ico')}" type="image/x-icon"/> 9 <g:javascript library="jquery"/> 10 <script src="${createLinkTo(dir: 'js', file: 'jquery-ui-1.7.2.custom.min.js')}" type="text/javascript"></script> 11 <link rel="stylesheet" href="${createLinkTo(dir: 'css/jquery-ui', file: 'jquery-ui-1.7.2.custom.css')}"/> 12 <!-- layouthead //--> 13 <g:layoutHead/> 14 <!-- /layouthead //--> 15 <script type="text/javascript" src="${resource(dir: 'js', file: 'login_panel.js')}"></script> 16 <script type="text/javascript" src="${resource(dir: 'js', file: 'topnav.js')}"></script> 17 </head> 18 <body> 19 <g:render template="/common/login_panel"/> 20 <div class="container"> 21 <div id="header"> 22 <g:render template="/common/topnav"/> 23 </div> 24 <div id="content"><g:layoutBody/></div> 25 <div id="footer"> 26 Copyright © 2008 - <g:formatDate format="yyyy" date="${new Date()}"/> NMC & NuGO. All rights reserved. 27 ( style: <%=session.style%>, 28 <a href="?showSource=true">show page source</a>)</div> 29 </div> 30 </body> 29 31 </html>
Note: See TracChangeset
for help on using the changeset viewer.