Changeset 101
- Timestamp:
- Jan 20, 2010, 5:01:26 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/studycapturing/WizardController.groovy
r88 r101 1 1 package dbnp.studycapturing 2 2 3 import dbnp.studycapturing.* 3 4 import grails.converters.* … … 9 10 * through the study capturing wizard. 10 11 * 11 * @author 12 * @since 12 * @author Jeroen Wesbeek 13 * @since 20100107 13 14 * @package studycapturing 14 15 * … … 19 20 */ 20 21 class WizardController { 21 22 23 24 25 26 27 28 29 30 31 32 33 redirect(action:'pages')34 22 /** 23 * index method, redirect to the webflow 24 * @void 25 */ 26 def index = { 27 /** 28 * Do you believe it in your head? 29 * I can go with the flow 30 * Don't say it doesn't matter (with the flow) matter anymore 31 * I can go with the flow (I can go) 32 * Do you believe it in your head? 33 */ 34 redirect(action: 'pages') 35 } 35 36 36 /** 37 * WebFlow definition 38 * @see http://grails.org/WebFlow 39 * @void 40 */ 41 def pagesFlow = { 42 // start the flow 43 onStart { 44 println "wizard started" 45 46 // define flow variables 47 flow.page = 0 48 flow.pages = [ 49 [title:'Een'], 50 [title:'Twoooo'], 51 [title:'Trois'] 52 ] 53 54 } 55 onEnd { 56 println "wizard ended" 57 } 37 /** 38 * WebFlow definition 39 * @see http://grails.org/WebFlow 40 * @void 41 */ 42 def pagesFlow = { 43 // start the flow 44 onStart { 45 println "wizard started" 58 46 59 // render the main wizard page 60 mainPage { 61 onRender { 62 println "render main page" 63 flow.page = 1 64 } 65 render(view:"/wizard/index") 66 on("next") { 67 println "next page!" 68 }.to "pageTwo" 69 } 47 // define flow variables 48 flow.page = 0 49 flow.pages = [ 50 [title: 'Een'], 51 [title: 'Twoooo'], 52 [title: 'Trois'] 53 ] 70 54 71 pageOne { 72 onRender { 73 println "render page one" 74 flow.page = 1 75 } 76 render(view:"_one") 77 on("next") { 78 println "next page!" 79 }.to "pageTwo" 80 } 55 } 81 56 82 // render page two 83 pageTwo { 84 onRender { 85 println "render page two" 86 flow.page = 2 87 } 88 render(view:"_two") 89 on("next") { 90 println "next page!" 91 }.to "pageThree" 92 on("previous") { 93 println "previous page!" 94 }.to "pageOne" 95 } 57 // render the main wizard page 58 mainPage { 59 render(view: "/wizard/index") 60 onRender { 61 flow.page = 1 62 } 63 on("next").to "pageOne" 64 } 96 65 97 // render page three 98 pageThree { 99 onRender { 100 println "render page three" 101 flow.page = 3 102 } 103 render(view:"_three") 104 on("previous") { 105 println "previous page!" 106 }.to "pageTwo" 107 } 108 } 66 pageOne { 67 render(view: "_one") 68 onRender { 69 println "render page one" 70 flow.page = 1 71 } 72 on("next") { 73 // create a study instance 74 /* 75 println params 76 def study = new Study(params) 77 78 79 if (study.validate()) { 80 println "study validates" 81 } else { 82 println "errorrrs" 83 error() 84 } 85 */ 86 }.to "pageTwo" 87 } 88 89 // render page two 90 pageTwo { 91 render(view: "_two") 92 onRender { 93 println "render page two" 94 flow.page = 2 95 } 96 on("next") { 97 println "next page!" 98 }.to "pageThree" 99 on("previous") { 100 println "previous page!" 101 }.to "pageOne" 102 } 103 104 // render page three 105 pageThree { 106 render(view: "_three") 107 onRender { 108 println "render page three" 109 flow.page = 3 110 } 111 on("previous") { 112 println "previous page!" 113 }.to "pageTwo" 114 } 115 } 109 116 } -
trunk/grails-app/domain/dbnp/studycapturing/Study.groovy
r100 r101 21 21 22 22 static constraints = { 23 owner(nullable:true,blank:true) 24 template(nullable:true,blank:true) 23 owner(nullable: true, blank: true) 24 title(nullable: false, blank: false) 25 template(nullable: true, blank: true) 25 26 } 26 27 -
trunk/grails-app/taglib/dbnp/studycapturing/WizardTagLib.groovy
r99 r101 32 32 * <wizard:ajaxButton name="myAction" value="myButton ... /> 33 33 * 34 * you can also provide a javascript function to execute after 35 * success. This behaviour differs from the default 'after' 36 * action which always fires after a button press... 37 * 34 38 * @see http://blog.osx.eu/2010/01/18/ajaxifying-a-grails-webflow/ 35 39 * @see http://www.grails.org/WebFlow … … 40 44 * @param Closure body 41 45 */ 42 def ajaxButton = { attrs, body ->46 def ajaxButton = { attrs, body -> 43 47 // get the jQuery version 44 48 def jQueryVersion = grailsApplication.getMetadata()['plugins.jquery'] … … 46 50 // fetch the element name from the attributes 47 51 def elementName = attrs['name'].replaceAll(/ /, "_") 52 53 // javascript function to call after success 54 def afterSuccess = attrs['afterSuccess'] 48 55 49 56 // generate a normal submitToRemote button … … 74 81 button = button.replaceFirst(/data\:jQuery/, "data:\'_eventId_${elementName}=1&\'+jQuery") 75 82 } 76 83 84 // add an after success function call? 85 // usefull for performing actions on success data (hence on refreshed 86 // wizard pages, such as attaching tooltips) 87 if (afterSuccess) { 88 button = button.replaceFirst(/\.html\(data\)\;/, '.html(data);' + afterSuccess + ';') 89 } 90 91 // replace double semi colons 92 button = button.replaceAll(/;{2,}/, '!!!') 93 77 94 // render button 78 95 out << button 96 } 97 98 /** 99 * generate ajax webflow redirect javascript 100 * 101 * As we have an Ajaxified webflow, the initial wizard page 102 * cannot contain a wizard form, as upon a failing submit 103 * (e.g. the form data does not validate) the form should be 104 * shown again. However, the Grails webflow then renders the 105 * complete initial wizard page into the success div. As this 106 * ruins the page layout (a page within a page) we want the 107 * initial page to redirect to the first wizard form to enter 108 * the webflow correctly. We do this by emulating an ajax post 109 * call which updates the wizard content with the first wizard 110 * form. 111 * 112 * Usage: <wizard:ajaxFlowRedirect form="form#wizardForm" name="next" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" /> 113 * form = the form identifier 114 * name = the action to execute in the webflow 115 * update = the divs to update upon success or error 116 * 117 * Example initial webflow action to work with this javascript: 118 * ... 119 * mainPage { 120 * render(view: "/wizard/index") 121 * onRender { 122 * flow.page = 1 123 * } 124 * on("next").to "pageOne" 125 * } 126 * ... 127 * 128 * @param Map attributes 129 * @param Closure body 130 */ 131 def ajaxFlowRedirect = { attrs, body -> 132 // define AJAX provider 133 setProvider([library: ajaxProvider]) 134 135 // generate an ajax button 136 def button = this.ajaxButton(attrs, body) 137 138 // strip the button part to only leave the Ajax call 139 button = button.replaceFirst(/<[^\"]*\"jQuery.ajax/,'jQuery.ajax') 140 button = button.replaceFirst(/return false.*/,'') 141 142 // change form if a form attribute is present 143 if (attrs.get('form')) { 144 button = button.replaceFirst(/this\.form/, 145 "\\\$('" + attrs.get('form') + "')" 146 ) 147 } 148 149 // generate javascript 150 out << '<script language="JavaScript">' 151 out << '$(document).ready(function() {' 152 out << button 153 out << '});' 154 out << '</script>' 79 155 } 80 156 … … 124 200 out << '<div class="element">' 125 201 out << ' <div class="description">' 126 out << body()202 out << attrs.get('description') 127 203 out << ' </div>' 128 204 out << ' <div class="input">' … … 131 207 132 208 // add help icon? 133 if ( attrs.get('help')) {209 if (body()) { 134 210 out << ' <div class="help">' 135 211 out << ' <div class="icon"></div>' 136 212 out << ' <div class="content">' 137 out << ' ' + attrs.get('help')213 out << ' ' + body() 138 214 out << ' </div>' 139 215 out << ' </div>' -
trunk/grails-app/views/wizard/common/_navigation.gsp
r88 r101 15 15 %> 16 16 <div class="navigation"> 17 <g:if test="${page>1}"><wizard:ajaxButton name="previous" value="« prev" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" class="prevnext" /></g:if>17 <g:if test="${page>1}"><wizard:ajaxButton name="previous" value="« prev" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" afterSuccess="attachHelpTooltips()" class="prevnext" /></g:if> 18 18 <g:if test="${page>1 && page<pages.size}"> | </g:if> 19 <g:if test="${page<pages.size}"><wizard:ajaxButton name="next" value="next »" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" class="prevnext" /></g:if>19 <g:if test="${page<pages.size}"><wizard:ajaxButton name="next" value="next »" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" afterSuccess="attachHelpTooltips()" class="prevnext" /></g:if> 20 20 </div> -
trunk/grails-app/views/wizard/common/_wizard.gsp
r88 r101 1 1 <% 2 /**3 * Wizard template with first page rendered4 *5 * @authorJeroen Wesbeek6 * @since201001137 * @package wizard8 * @seedbnp.studycapturing.WizardTagLib9 * @seedbnp.studycapturing.WizardController10 *11 * Revision information:12 * $Rev$13 * $Author$14 * $Date$15 */2 /** 3 * Wizard template with first page rendered 4 * 5 * @author Jeroen Wesbeek 6 * @since 20100113 7 * @package wizard 8 * @see dbnp.studycapturing.WizardTagLib 9 * @see dbnp.studycapturing.WizardController 10 * 11 * Revision information: 12 * $Rev$ 13 * $Author$ 14 * $Date$ 15 */ 16 16 %> 17 18 19 <g:form action="pages" name="_wizard">20 21 <g:render template="pages/one"/>22 23 24 25 17 <div id="wizard" class="wizard"> 18 <h1>Proof of concept AJAXified Grails Webflow Wizard</h1> 19 <g:form action="pages" name="wizardForm" id="wizardForm"> 20 <div id="wizardPage"> 21 <wizard:ajaxFlowRedirect form="form#wizardForm" name="next" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" afterSuccess="handleHelpTooltips()" /> 22 </div> 23 <g:render template="common/error"/> 24 </g:form> 25 </div> -
trunk/grails-app/views/wizard/pages/_one.gsp
r92 r101 1 1 <% 2 2 /** 3 * Wizard page one3 * Study page 4 4 * 5 5 * @author Jeroen Wesbeek … … 16 16 %> 17 17 <wizard:pageContent> 18 <wizard:textFieldElement name="studyTitle" help="The title of the study you are creating">Title</wizard:textFieldElement> 19 <wizard:textFieldElement name="studyCode" help="A code to reference your study by">Code</wizard:textFieldElement> 20 <wizard:textFieldElement name="studyResearchQuestion" help="The research question">Research Question</wizard:textFieldElement> 21 <wizard:textFieldElement name="studyDescription">Description</wizard:textFieldElement> 22 <wizard:textFieldElement name="studyEcCode">Ethical Committee Code</wizard:textFieldElement> 18 <wizard:textFieldElement name="studyTitle" description="Title"> 19 The title of the study you are creating 20 </wizard:textFieldElement> 21 <wizard:textFieldElement name="studyCode" description="Code"> 22 A code to reference your study by 23 </wizard:textFieldElement> 24 <wizard:textFieldElement name="studyResearchQuestion" description="Research Question"> 25 The research question 26 </wizard:textFieldElement> 27 <wizard:textFieldElement name="studyDescription" description="Description" /> 28 <wizard:textFieldElement name="studyEcCode" description="Ethical Committee Code" /> 23 29 </wizard:pageContent> -
trunk/grails-app/views/wizard/pages/_three.gsp
r92 r101 1 1 <% 2 /**3 * Wizard page three4 *5 * @authorJeroen Wesbeek6 * @since201001137 * @package wizard8 * @seedbnp.studycapturing.WizardTagLib::previousNext9 * @seedbnp.studycapturing.WizardController10 *11 * Revision information:12 * $Rev$13 * $Author$14 * $Date$15 */2 /** 3 * Wizard page three 4 * 5 * @author Jeroen Wesbeek 6 * @since 20100113 7 * @package wizard 8 * @see dbnp.studycapturing.WizardTagLib::previousNext 9 * @see dbnp.studycapturing.WizardController 10 * 11 * Revision information: 12 * $Rev$ 13 * $Author$ 14 * $Date$ 15 */ 16 16 %> 17 17 <wizard:pageContent> 18 <wizard:textFieldElement name="myZero" value="12" help="some help text" maxlength="4">more than four?</wizard:textFieldElement> 19 <wizard:textFieldElement name="myFirstName" value="my value" help="my help">Please fill in you name bla bla bla</wizard:textFieldElement> 20 <wizard:textFieldElement name="mySecondName" value="1234" size="4">another text field</wizard:textFieldElement> 21 <wizard:textFieldElement name="myThirdName" value="a lotta description" help="so much for help"> 22 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur pretium dignissim tellus, id pharetra erat tempus sed. Sed bibendum libero eu lorem pretium nec fermentum ligula faucibus. Morbi gravida interdum ornare. Praesent lectus mi, ullamcorper nec semper nec, vulputate ornare elit. Nam eros metus, egestas a varius eget, facilisis ac purus. Maecenas lectus erat, rutrum id consequat ac, scelerisque ut diam. Donec euismod, tellus facilisis semper elementum, neque lorem volutpat ante, ac consectetur lectus ante sit amet neque. Donec hendrerit, libero quis suscipit iaculis, lacus ligula viverra nibh, eu condimentum diam dui sit amet quam. Praesent turpis orci, laoreet sodales adipiscing eget, ultrices at augue. Nullam sed dolor a velit posuere euismod. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut libero mauris, fermentum id congue sit amet, pharetra in purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam a blandit quam. Cras porta tempus lectus, vel varius lacus vulputate in. Aenean ac nunc lectus, hendrerit tempor elit. Sed ut varius diam. 23 </wizard:textFieldElement> 18 <wizard:textFieldElement name="myThirdName" value="a lotta description" description="very fancy help text"> 19 <img src="http://www.grails.org/images/new/grailslogo_topNav.png"/><br/> 20 This is made with <a href="http://www.grails.org/" target="_new">Grails</a>... 21 </wizard:textFieldElement> 22 <wizard:textFieldElement name="myZero" value="12" description="more than four?" maxlength="4"> 23 you cannot enter more than 4 elements here, and also the 24 width of this field is automatically scaled to the maximum character 25 size 26 </wizard:textFieldElement> 27 <wizard:textFieldElement name="myThirdName" value="a lotta description" description="long help text"> 28 <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur pretium dignissim tellus, id pharetra erat tempus sed. Sed bibendum libero eu lorem pretium nec fermentum ligula faucibus. Morbi gravida interdum ornare. Praesent lectus mi, ullamcorper nec semper nec, vulputate ornare elit. Nam eros metus, egestas a varius eget, facilisis ac purus. Maecenas lectus erat, rutrum id consequat ac, scelerisque ut diam.</p> 29 <p>Donec euismod, tellus facilisis semper elementum, neque lorem volutpat ante, ac consectetur lectus ante sit amet neque. Donec hendrerit, libero quis suscipit iaculis, lacus ligula viverra nibh, eu condimentum diam dui sit amet quam. Praesent turpis orci, laoreet sodales adipiscing eget, ultrices at augue. Nullam sed dolor a velit posuere euismod. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut libero mauris, fermentum id congue sit amet, pharetra in purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 30 <p>Nullam a blandit quam. Cras porta tempus lectus, vel varius lacus vulputate in. Aenean ac nunc lectus, hendrerit tempor elit. Sed ut varius diam.</p> 31 </wizard:textFieldElement> 24 32 </wizard:pageContent> -
trunk/web-app/js/wizard.js
r98 r101 14 14 */ 15 15 $(document).ready(function() { 16 attachHelpTooltips(); 17 }); 18 19 function attachHelpTooltips() { 16 20 // attach help action on all wizard help icons 17 21 $('div#wizard').find('div.help').each(function() { … … 19 23 content: 'leftMiddle', 20 24 position: { 21 corner: {22 tooltip: 'leftMiddle',23 target: 'rightMiddle'24 }25 corner: { 26 tooltip: 'leftMiddle', 27 target: 'rightMiddle' 28 } 25 29 }, 26 30 style: { 27 border: {28 width: 5,29 radius: 1030 },31 padding: 10,32 textAlign: 'center',33 tip: true, // Give it a speech bubble tip with automatic corner detection34 name: 'blue' // Style it according to the preset 'cream' style31 border: { 32 width: 5, 33 radius: 10 34 }, 35 padding: 10, 36 textAlign: 'center', 37 tip: true, // Give it a speech bubble tip with automatic corner detection 38 name: 'blue' // Style it according to the preset 'cream' style 35 39 }, 36 40 content: $(this).find('div.content').html(), … … 39 43 }) 40 44 }) 41 } );45 }
Note: See TracChangeset
for help on using the changeset viewer.