Changeset 556
- Timestamp:
- Jun 10, 2010, 4:45:53 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 9 added
- 8 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/studycapturing/TemplateEditorController.groovy
r544 r556 28 28 def index = { 29 29 // Check whether a right entity is given 30 _checkEntity(); 30 if( !_checkEntity() ) { 31 return 32 } 31 33 32 34 // fetch all templates for this entity 33 35 def templates = Template.findAllByEntity(entity) 34 36 35 // Check whether a template is already selected 37 // Generate a human readable entity name 38 def parts = entityName.tokenize( '.' ); 39 def humanReadableEntity = parts[ parts.size() - 1 ]; 40 41 return [ 42 entity: entity, 43 templates: templates, 44 encryptedEntity: params.entity, 45 humanReadableEntity: humanReadableEntity, 46 ]; 47 } 48 49 /** 50 * Shows the editing of a template 51 */ 52 def template = { 53 // Check whether a right entity is given 54 if( !_checkEntity() ) { 55 return 56 } 57 58 // Check whether a template is selected. If not, redirect the user to the index 36 59 def selectedTemplate = params.template; 37 60 def template = null; … … 39 62 if( selectedTemplate ) { 40 63 template = Template.get( selectedTemplate ); 41 } 64 } else { 65 redirect(action:"index",params:[entity:params.entity]) 66 return; 67 } 68 69 // fetch all templates for this entity 70 def templates = Template.findAllByEntity(entity) 71 72 // Generate a human readable entity name 73 def parts = entityName.tokenize( '.' ); 74 def humanReadableEntity = parts[ parts.size() - 1 ]; 75 76 77 78 // Find all available fields 79 def allFields = TemplateField.findAllByEntity( entity ).sort { a, b -> a.name <=> b.name } 42 80 43 81 return [ … … 46 84 encryptedEntity: params.entity, 47 85 fieldTypes: TemplateFieldType.list(), 48 49 template: template 86 humanReadableEntity: humanReadableEntity, 87 88 template: template, 89 allFields: allFields 50 90 ]; 51 } 91 92 } 93 52 94 53 95 /** … … 61 103 62 104 /** 63 * Adds a new template field using a AJAX call 105 * Creates a new template using a AJAX call 106 * 107 * @return JSON object with two entries: 108 * id: [id of this object] 109 * html: HTML to replace the contents of the LI-item that was updated. 110 * On error the method gives a HTTP response status 500 and the error 111 */ 112 def createTemplate = { 113 // Decode the entity 114 if( !_checkEntity() ) { 115 response.status = 500; 116 render "Incorrect entity given"; 117 return; 118 } 119 120 params.entity = entity; 121 122 // Create the template field and add it to the template 123 def template = new Template( params ); 124 if (template.save(flush: true)) { 125 126 def html = g.render( template: 'elements/liTemplateEditable', model: [template: template] ); 127 def output = [ id: template.id, html: html ]; 128 render output as JSON; 129 130 //render ''; 131 } else { 132 response.status = 500; 133 render 'Template could not be created because errors occurred.'; 134 return 135 } 136 } 137 138 /** 139 * Updates a selected template using a AJAX call 140 * 141 * @param id ID of the template to update 142 * @return JSON object with two entries: 143 * id: [id of this object] 144 * html: HTML to replace the contents of the LI-item that was updated. 145 * On error the method gives a HTTP response status 500 and the error 146 */ 147 def updateTemplate = { 148 // Search for the template field 149 def template = Template.get( params.id ); 150 if( !template ) { 151 response.status = 404; 152 render 'Template not found'; 153 return; 154 } 155 156 // Update the field if it is not updated in between 157 if (params.version) { 158 def version = params.version.toLong() 159 if (template.version > version) { 160 response.status = 500; 161 render 'Template was updated while you were working on it. Please reload and try again.'; 162 return 163 } 164 } 165 166 template.properties = params 167 if (!template.hasErrors() && template.save(flush: true)) { 168 def html = g.render( template: 'elements/liTemplateEditable', model: [template: template] ); 169 def output = [ id: template.id, html: html ]; 170 render output as JSON; 171 } else { 172 response.status = 500; 173 render 'Template was not updated because errors occurred.'; 174 return 175 } 176 } 177 178 /** 179 * Deletes a template using a AJAX call 180 * 181 * @param template ID of the template to move 182 * @return JSON object with one entry: 183 * id: [id of this object] 184 * On error the method gives a HTTP response status 500 and the error 185 */ 186 def deleteTemplate = { 187 // Search for the template field 188 def template = Template.get( params.template ); 189 if( !template ) { 190 response.status = 404; 191 render 'Template not found'; 192 return; 193 } 194 195 // Delete the template field 196 try { 197 template.delete(flush: true) 198 199 def output = [ id: template.id ]; 200 render output as JSON; 201 } 202 catch (org.springframework.dao.DataIntegrityViolationException e) { 203 response.status = 500; 204 render 'Template could not be deleted: ' + e.getMessage(); 205 } 206 } 207 208 209 210 211 /** 212 * Creates a new template field using a AJAX call 64 213 * 65 214 * @param template ID of the template to add a field to … … 69 218 * On error the method gives a HTTP response status 500 and the error 70 219 */ 71 def addField = {220 def createField = { 72 221 // Search for the template 73 222 def template = Template.get( params.template ); … … 78 227 return; 79 228 } 229 230 // Decode the entity, in order to set a good property 231 if( !_checkEntity() ) { 232 response.status = 500; 233 render "Incorrect entity given"; 234 return; 235 } 236 237 params.entity = entity; 238 239 // See whether this field already exists. It is checked by name, type and unit and entity 240 // The search is done using search by example (see http://grails.org/DomainClass+Dynamic+Methods, method find) 241 def uniqueParams = [ name: params.name, type: params.type, unit: params.unit, entity: params.entity ]; 242 if( TemplateField.find( new TemplateField( uniqueParams ) ) ) { 243 response.status = 500; 244 render "A field with this name, type and unit already exists."; 245 return; 246 } 80 247 81 248 // Create the template field and add it to the template 82 249 def templateField = new TemplateField( params ); 83 250 if (templateField.save(flush: true)) { 84 template.fields.add( templateField ); 85 86 def html = g.render( template: 'elements/liContent', model: [templateField: templateField, fieldTypes: TemplateFieldType.list()] ); 251 252 def html = g.render( template: 'elements/liFieldNotInUse', model: [templateField: templateField, fieldTypes: TemplateFieldType.list()] ); 87 253 def output = [ id: templateField.id, html: html ]; 88 254 render output as JSON; … … 91 257 } else { 92 258 response.status = 500; 93 render 'TemplateField could not be added because errors occurred.';259 render 'TemplateField could not be created because errors occurred.'; 94 260 return 95 261 } … … 105 271 * On error the method gives a HTTP response status 500 and the error 106 272 */ 107 def update = {273 def updateField = { 108 274 // Search for the template field 109 275 def templateField = TemplateField.get( params.id ); … … 125 291 templateField.properties = params 126 292 if (!templateField.hasErrors() && templateField.save(flush: true)) { 127 def html = g.render( template: 'elements/li Content', model: [templateField: templateField, fieldTypes: TemplateFieldType.list()] );293 def html = g.render( template: 'elements/liField', model: [templateField: templateField, fieldTypes: TemplateFieldType.list()] ); 128 294 def output = [ id: templateField.id, html: html ]; 129 295 render output as JSON; … … 136 302 137 303 /** 138 * Deletes a selected template field from the template using a AJAX call 304 * Deletes a template field using a AJAX call 305 * 306 * @param templateField ID of the templatefield to move 307 * @return JSON object with one entry: 308 * id: [id of this object] 309 * On error the method gives a HTTP response status 500 and the error 310 */ 311 def deleteField = { 312 // Search for the template field 313 def templateField = TemplateField.get( params.templateField ); 314 if( !templateField ) { 315 response.status = 404; 316 render 'TemplateField not found'; 317 return; 318 } 319 320 // Delete the template field 321 try { 322 templateField.delete(flush: true) 323 324 def output = [ id: templateField.id ]; 325 render output as JSON; 326 } 327 catch (org.springframework.dao.DataIntegrityViolationException e) { 328 response.status = 500; 329 render 'TemplateField could not be deleted: ' + e.getMessage(); 330 } 331 } 332 333 /** 334 * Adds a new template field to a template using a AJAX call 335 * 336 * @param template ID of the template to add a field to 337 * @return JSON object with two entries: 338 * id: [id of this object] 339 * html: HTML to replace the contents of the LI-item that was updated. 340 * On error the method gives a HTTP response status 404 or 500 and the error 341 */ 342 def addField = { 343 // Search for the template 344 def template = Template.get( params.template ); 345 346 if( !template ) { 347 response.status = 404; 348 render 'Template not found'; 349 return; 350 } 351 352 // Search for the template field 353 def templateField = TemplateField.get( params.templateField ); 354 if( !templateField ) { 355 response.status = 404; 356 render 'TemplateField does not exist'; 357 return; 358 } 359 360 // The template field should exist within the template 361 if( template.fields.contains( templateField ) ) { 362 response.status = 500; 363 render 'TemplateField is already found within template'; 364 return; 365 } 366 if( !params.position || Integer.parseInt( params.position ) == -1) { 367 template.fields.add( templateField ) 368 } else { 369 template.fields.add( Integer.parseInt( params.position ), templateField ) 370 } 371 372 def html = g.render( template: 'elements/liFieldSelected', model: [templateField: templateField, template: template, fieldTypes: TemplateFieldType.list()] ); 373 def output = [ id: templateField.id, html: html ]; 374 render output as JSON; 375 } 376 377 378 /** 379 * Removes a selected template field from the template using a AJAX call 139 380 * 140 381 * @param templateField ID of the field to update 141 382 * @param template ID of the template for which the field should be removed 142 * @return Status code 200 on success, 500 otherwise 143 */ 144 def delete = { 383 * @return JSON object with two entries: 384 * id: [id of this object] 385 * html: HTML to replace the contents of the LI-item that was updated. 386 * On error the method gives a HTTP response status 404 or 500 and the error 387 */ 388 def removeField = { 145 389 // Search for the template 146 390 def template = Template.get( params.template ); … … 171 415 template.fields.remove( currentIndex ); 172 416 template.save(); 173 render ''; 174 175 /* 176 *try { 177 templateField.delete(flush: true) 178 render ""; 179 return; 180 } catch (org.springframework.dao.DataIntegrityViolationException e) { 181 response.status = 500; 182 render "Templatefield not deleted: " + e.getMessage(); 183 return; 184 } 185 */ 417 418 419 def html = g.render( template: 'elements/liField', model: [templateField: templateField, fieldTypes: TemplateFieldType.list()] ); 420 def output = [ id: templateField.id, html: html ]; 421 render output as JSON; 186 422 } 187 423 … … 197 433 * On error the method gives a HTTP response status 500 and the error 198 434 */ 199 def move = {435 def moveField = { 200 436 // Search for the template 201 437 def template = Template.get( params.template ); … … 227 463 template.fields.add( Integer.parseInt( params.position ), moveField ); 228 464 229 def html = g.render( template: 'elements/li Content', model: [templateField: templateField, fieldTypes: TemplateFieldType.list()] );465 def html = g.render( template: 'elements/liFieldSelected', model: [templateField: templateField, template: template, fieldTypes: TemplateFieldType.list()] ); 230 466 def output = [ id: templateField.id, html: html ]; 231 467 render output as JSON; 232 468 } 469 470 /** 471 * Checks how many template use a specific template field 472 * 473 * @param id ID of the template field 474 * @return int Number of uses 475 */ 476 def numFieldUses = { 477 // Search for the template field 478 def templateField = TemplateField.get( params.id ); 479 if( !templateField ) { 480 response.status = 404; 481 render 'TemplateField not found'; 482 return; 483 } 484 485 render templateField.numUses(); 486 } 233 487 234 488 /** … … 252 506 if( !entity ) { 253 507 error(); 254 retur ;false508 return false 255 509 } 256 510 -
trunk/grails-app/domain/dbnp/studycapturing/Template.groovy
r550 r556 1 1 package dbnp.studycapturing 2 import java.lang.reflect.Method 2 3 3 4 /** … … 96 97 97 98 /** 99 * Checks whether this template is used by any object 100 * 101 * @returns true iff this template is used by any object, false otherwise 102 */ 103 def inUse() { 104 return (numUses() > 0 ); 105 } 106 107 /** 108 * The number of objects that use this template 109 * 110 * @returns the number of objects that use this template. 111 */ 112 def numUses() { 113 // This template can only be used in objects of the right entity. Find objects of that 114 // entity and see whether they use this method. 115 // 116 // Unfortunately, due to the grails way of creating classes, we can not use reflection for this 117 def elements; 118 switch( this.entity ) { 119 case Event: 120 elements = Event.findAllByTemplate( this ); break; 121 case Sample: 122 elements = Sample.findAllByTemplate( this ); break; 123 case Study: 124 elements = Study.findAllByTemplate( this ); break; 125 case Subject: 126 elements = Subject.findAllByTemplate( this ); break; 127 default: 128 return 0; 129 } 130 131 return elements.size(); 132 } 133 134 /** 98 135 * overloading the findAllByEntity method to make it function as expected 99 136 * @param Class entity (for example: dbnp.studycapturing.Subject) -
trunk/grails-app/domain/dbnp/studycapturing/TemplateField.groovy
r550 r556 53 53 return name.toLowerCase().replaceAll("([^a-z0-9])", "_") 54 54 } 55 56 /** 57 * overloading the findAllByEntity method to make it function as expected 58 * @param Class entity (for example: dbnp.studycapturing.Subject) 59 * @return ArrayList 60 */ 61 public static findAllByEntity(java.lang.Class entity) { 62 def results = [] 63 // 'this' should not work in static context, so taking Template instead of this 64 TemplateField.findAll().each() { 65 if (entity.equals(it.entity)) { 66 results[results.size()] = it 67 } 68 } 69 70 return results 71 } 72 73 /** 74 * Checks whether this template field is used in a template 75 * 76 * @returns true iff this template field is used in a template (even if the template is never used), false otherwise 77 */ 78 def inUse() { 79 return numUses() > 0; 80 } 81 82 /** 83 * The number of templates that use this template 84 * 85 * @returns the number of templates that use this template. 86 */ 87 def numUses() { 88 def templates = Template.findAll(); 89 def elements; 90 if( templates && templates.size() > 0 ) { 91 elements = templates.findAll { template -> template.fields.contains( this ) }; 92 } else { 93 return 0; 94 } 95 96 return elements.size(); 97 } 98 99 55 100 } -
trunk/grails-app/views/templateEditor/elements/_available.gsp
r544 r556 1 1 <li class="ui-state-default" id="templateField_${it.id}"> 2 <g:render template="elements/liContent" model="['templateField': it, 'fieldTypes': fieldTypes]"/>2 <g:render template="elements/liField" model="['templateField': it, 'fieldTypes': fieldTypes]"/> 3 3 </li> -
trunk/grails-app/views/templateEditor/elements/_liFieldNotInUse.gsp
r544 r556 1 < a class="title" href="#" onClick="showTemplateFieldForm( 'templateField_' + ${templateField.id}); this.blur(); return false;">2 <span class="ui-icon ui-icon-arrowthick-2-n-s"></span>3 <b>${templateField.name}</b>4 (<g:render template="elements/${templateField.type.toString().toLowerCase().replaceAll(/ /,'_')}" />) 5 </ a>1 <span class="listButtons"> 2 <img onClick="showTemplateFieldForm( 'templateField_' + ${templateField.id}); this.blur(); return false;" src="${createLinkTo( dir: 'images', file: 'icons/famfamfam/application_edit.png')}" alt="Edit template field properties" title="Edit template field properties"> 3 <img onClick="if( confirm( 'Are you sure?' ) ) { deleteTemplateField( ${templateField.id} ); }" src="${createLinkTo( dir: 'images', file: 'icons/famfamfam/delete.png')}" alt="Delete this template field" title="Delete this template field"> 4 <img onClick="addTemplateField( ${templateField.id} ); moveFieldListItem( ${templateField.id}, '#selectedTemplateFields' );" src="${createLinkTo( dir: 'images', file: 'icons/famfamfam/add.png')}" alt="Add field to template" title="Add field to template"> 5 </span> 6 6 7 <form class="templateField_form" id="templateField_${templateField.id}_form" action="update"> 7 <b>${templateField.name}</b> 8 (<g:if test="${templateField.unit}">${templateField.unit}, </g:if><g:render template="elements/${templateField.type.toString().toLowerCase().replaceAll(/ /,'_')}" model="[templateField: templateField]" />) 9 10 <form class="templateField_form" id="templateField_${templateField.id}_form" action="updateField"> 8 11 <g:hiddenField name="id" value="${templateField.id}" /> 9 12 <g:hiddenField name="version" value="${templateField.version}" /> … … 11 14 <div class="templateFieldButtons"> 12 15 <input type="button" value="Save" onClick="updateTemplateField( ${templateField.id} );"> 13 <input type="button" value="Delete" onClick="deleteTemplateField( ${templateField.id} );">14 16 <input type="button" value="Close" onClick="hideTemplateFieldForm( ${templateField.id} );"> 15 17 </div> -
trunk/grails-app/views/templateEditor/index.gsp
r544 r556 24 24 <body> 25 25 26 <script type="text/javascript"> 27 $(function() { 28 $("#templateFields").sortable({ 29 placeholder: 'ui-state-highlight', 30 cancel: '.empty', 26 <div class="templateEditorStep" id="step1_template"> 27 <h3>Select template</h3> 28 <p>Showing templates for <b>${humanReadableEntity}</b>.</p> 29 <p>Please select a template to edit or create a new template</p> 31 30 32 update: updateTemplateFieldPosition 33 }); 34 $("#templateFields").disableSelection(); 35 //$('#templateFields li').bind('dblclick', showTemplateFormEvent); 36 }); 37 </script> 38 39 <p>Please select a template to edit or create a new template</p> 40 <g:form action="index" name="templateChoice"> 41 <g:hiddenField name="entity" value="${encryptedEntity}" /> 42 <select name="template" id="templateSelect" onChange="this.form.submit();"> 43 <option value=""></option> 31 <ul id="templates"> 32 <li class="empty ui-state-default" <g:if test="${templates.size() > 0 }">style='display: none;'</g:if>>There are no templates for ${humanReadableEntity}. Use the 'Add template' button to add fields.</li> 44 33 <g:each in="${templates}" var="currentTemplate"> 45 <g:if test="${currentTemplate.id==template?.id}"> 46 <option selected value="${currentTemplate.id}">${currentTemplate.name}</option> 47 </g:if> 48 <g:else> 49 <option value="${currentTemplate.id}">${currentTemplate.name}</option> 50 </g:else> 34 <li id="template_${currentTemplate.id}"class="ui-state-default"> 35 <g:if test="${currentTemplate.inUse()}"> 36 <g:render template="elements/liTemplateNonEditable" model="['template': currentTemplate]"/> 37 </g:if> 38 <g:else> 39 <g:render template="elements/liTemplateEditable" model="['template': currentTemplate]"/> 40 </g:else> 41 </li> 51 42 </g:each> 52 </select>53 </g:form>54 55 <g:if test="${template}">56 <p>Currently, this template contains the following fields. Drag fields to reorder and double click fields to edit.</p>57 <ul id="templateFields">58 <li class="empty ui-state-default" <g:if test="${template.fields?.size() > 0 }">style='display: none;'</g:if>>This template does not yet contain any fields. Use the 'Add new field' button to add fields.</li>59 <g:render template="elements/all" collection="${template.fields}" />60 43 </ul> 61 44 62 45 <div id="addNew"> 63 <a href="#" onClick=" showTemplateFieldForm( 'templateField_new' ); this.blur(); return false;">64 <b> Add new field</b>46 <a href="#" onClick="editTemplate( 'new' ); this.blur(); return false;"> 47 <b>Create new template</b> 65 48 </a> 66 49 67 <form class="templateField_form" id="templateField_new_form" action="addField"> 68 <g:render template="elements/fieldForm" model="['templateField': null, 'fieldTypes': fieldTypes]"/> 50 <form class="templateField_form" id="template_new_form" action="createTemplate"> 51 <g:hiddenField name="entity" value="${encryptedEntity}" /> 52 <g:render template="elements/templateForm" model="['template': null]"/> 69 53 <div class="templateFieldButtons"> 70 <input type="button" value="Save" onClick=" addTemplateField( 'new' );">71 <input type="button" value="Cancel" onClick="hideTemplateF ieldForm( 'new' );">54 <input type="button" value="Save" onClick="createTemplate( 'new' );"> 55 <input type="button" value="Cancel" onClick="hideTemplateForm( 'new' );"> 72 56 </div> 73 57 </form> 74 58 </div> 75 </g:if> 59 60 <g:form action="template" name="templateChoice" method="GET"> 61 <g:hiddenField name="entity" value="${encryptedEntity}" /> 62 <input type="hidden" name="template" id="templateSelect" value="${template?.id}"> 63 </g:form> 64 </div> 76 65 77 66 </body> -
trunk/test/unit/dbnp/studycapturing/TemplateFieldTests.groovy
r507 r556 28 28 ); 29 29 30 // Add static methods to Template 31 mockDomain( Template, [testTemplate] ); 32 mockDomain( TemplateField, testTemplate.fields ); 33 30 34 this.testEvent = new Event( 31 35 template: testTemplate, 32 36 startTime: 3600, 33 37 endTime: 7200 34 ) 38 ); 39 40 mockDomain( Event, [testEvent] ); 41 this.testEvent.save(); 35 42 } 36 43 … … 38 45 super.tearDown() 39 46 } 47 48 void testInUse() { 49 50 // All template fields in the testTemplate are in use (even in use on a object) 51 assert testEvent.template.fields.size() == 3; 52 testEvent.template.fields.each { 53 if( it != null ) { 54 assert it.inUse(); 55 } 56 } 57 58 // Create 2 template fields and use the first in a template, the second is not used 59 TemplateField t1 = new TemplateField( 60 name: 'test1', 61 type: TemplateFieldType.DATE, 62 entity: dbnp.studycapturing.Event 63 ).save(); 64 TemplateField t2 = new TemplateField( 65 name: 'test2', 66 type: TemplateFieldType.DATE, 67 entity: dbnp.studycapturing.Event 68 ).save(); 69 70 mockDomain( TemplateField, [t1, t2] ); 71 72 def template1 = new Template( 73 name: 'Template for testing inUse', 74 entity: dbnp.studycapturing.Event, 75 fields: [ 76 t1 77 ] 78 ).save(); 79 80 assert t1.inUse(); 81 assert !t2.inUse(); 82 83 } 40 84 41 85 void testRelTimeFieldCreation() { -
trunk/test/unit/dbnp/studycapturing/TemplateTests.groovy
r496 r556 12 12 } 13 13 14 void testSomething() { 14 void testInUse() { 15 Template t1 = new Template( entity: dbnp.studycapturing.Subject ); 16 Template t2 = new Template( entity: dbnp.studycapturing.Subject ); 17 Template t3 = new Template( entity: dbnp.studycapturing.Subject ); 18 19 Subject s1 = new Subject( template: t1 ); 20 Subject s2 = new Subject( template: t1 ); 21 Subject s3 = new Subject( template: t2 ); 22 23 mockDomain(Template, [t1, t2, t3 ]) 24 mockDomain(Subject, [ s1, s2, s3] ) 25 26 assert t1.inUse(); 27 assert t2.inUse(); 28 assert !t3.inUse(); 15 29 16 30 } -
trunk/web-app/css/templateEditor.css
r544 r556 1 #templateFields { 2 list-style-type: none; 3 margin: 0; 4 padding: 0; 5 width: 400px; 6 } 7 #templateFields li { 8 margin: 0 5px 5px 5px; padding: 5px; 9 } 10 html>body #templateFields li { 11 line-height: 16px; vertical-align: center; 12 } 13 .ui-state-highlight { 14 height: 1.5em; line-height: 1.2em; 15 } 16 #templateFields .ui-icon { 17 display: inline-block; 18 } 1 /** 2 * Formatting the template editor with two columns 3 */ 4 .templateEditorStep { float: left; padding: 10px 0px; margin: 0 10px; } 5 .templateEditorStep h3 { margin: 0 0 10px 0; padding-bottom: 10px; border-bottom: 1px solid #BBD; } 6 #step2_selectedFields p, #step3_availableFields p { height: 42px; } 19 7 20 #templateFields .empty { opacity: 0.6; padding: 5px 25px; } 8 #step1_template { width:340px; } 9 #step2_selectedFields { width: 340px; margin-right: 20px; } 10 #step3_availableFields { width: 340px; } 21 11 12 /** 13 * Formatting the template list and the forms to add/edit them 14 */ 15 16 #templates { list-style-type: none; margin: 0; padding: 0; width: 330px; } 17 #templates li { margin: 0 5px 5px 5px; padding: 5px; color: #2779AA; } 18 html>body #templates li { line-height: 16px; vertical-align: center; } 19 20 /* Butons within a list item */ 21 .listButtons { display: block; float: right; } 22 .listButtons img { margin: 0 3px; cursor: pointer; } 23 .listButtons img.disabled { cursor: default; opacity: 0.3; } 24 25 /** 26 * Formatting of the template fields and the forms to edit/add them 27 */ 28 .templateFields { list-style-type: none; margin: 0; padding: 0; width: 330px; } 29 .templateFields li { margin: 0 5px 3px 5px; padding: 3px 5px; } 30 html>body .templateFields li { line-height: 16px; vertical-align: center; } 31 .ui-state-highlight { height: 17px; } 32 .templateFields .ui-icon { display: inline-block; height: 13px; } 33 34 .templateName { color: #2779AA; } 35 a.switch { font-size: small; color: #68BFEF; text-decoration: none; } 36 37 /* Box to show a list is empty */ 38 .templateFields .empty { opacity: 0.6; padding: 5px 25px; } 39 40 /* The position where an item can be dropped in the available list will be red */ 41 #availableTemplateFields .ui-state-highlight { background: #FFD6D6; border-color: #EAAEAE; } 42 43 /* Form to edit or add a template field, but also for editing a template itself */ 22 44 .templateField_form { display: none; margin: 5px; padding-top: 8px; border-top: 1px solid #BBD; } 23 45 .templateField_form .templateFieldButtons { margin-top: 8px; padding-top: 8px; border-top: 1px solid #BBD; } 24 .templateField_form label { width: 100px; float: left; display: block; } 25 .templateField_form textarea {width: 240px; height: 100px; } 46 .templateField_form label { width: 80px; float: left; display: block; } 47 .templateField_form textarea {width: 145px; height: 100px; } 48 .templateField_form input[type=text], 49 .templateField_form select {width: 145px; } 26 50 51 /* Add new form */ 27 52 #addNew { 28 width: 3 88px;53 width: 318px; 29 54 line-height: 16px; 30 55 background-color: #EBF9D7; … … 40 65 #addNew a { 41 66 display: block; 42 padding: 7px 25px;67 padding: 7px 7px; 43 68 cursor: pointer; 44 69 color:#79AA27; -
trunk/web-app/js/templateEditor.js
r544 r556 15 15 var formOpened = false; 16 16 17 /************************************* 18 * 19 * Methods for the index page with templates on it 20 * 21 *************************************/ 22 23 /** 24 * Sends the user to the page where the fields of this template can be edited 25 */ 26 function editFields( id ) { 27 $( '#templateSelect' ).val( id ); 28 $( '#templateChoice' ).submit(); 29 } 30 31 /** 32 * Shows the form to edit template properties 33 */ 34 function editTemplate( id ) { 35 // Show the form is this item is not disabled 36 if( !formOpened ) { 37 formOpened = true; 38 39 // Show the form 40 $( '#template_' + id + '_form' ).show(); 41 } 42 } 43 44 /** 45 * Hides the form to edit a template 46 */ 47 function hideTemplateForm( id ) { 48 $( '#template_' + id + '_form' ).hide(); 49 50 formOpened = false; 51 } 52 53 /** 54 * Creates a new template using AJAX 55 */ 56 function createTemplate( id ) { 57 var formEl = $( '#template_' + id + '_form' ); 58 59 // Update the field 60 $.ajax({ 61 url: baseUrl + '/templateEditor/' + formEl.attr( 'action' ), 62 data: formEl.serialize(), 63 dataType: 'json', 64 type: "POST", 65 success: function(data, textStatus, request) { 66 hideTemplateForm( id ); 67 addTemplateListItem( data.id, data.html ); 68 }, 69 error: function( request ) { 70 alert( "Could not create template: " + request.responseText ); 71 } 72 }); 73 } 74 75 /** 76 * Updates the properties of a template using AJAX 77 */ 78 function updateTemplate( id ) { 79 var formEl = $( '#template_' + id + '_form' ); 80 81 // Update the field 82 $.ajax({ 83 url: baseUrl + '/templateEditor/' + formEl.attr( 'action' ), 84 dataType: 'json', 85 data: formEl.serialize(), 86 type: "POST", 87 success: function(data, textStatus, request) { 88 hideTemplateForm( id ); 89 updateTemplateListItem( id, data.html ); 90 }, 91 error: function( request ) { 92 alert( "Could not update template: " + request.responseText ); 93 } 94 }); 95 } 96 97 /** 98 * Deletes a template field using AJAX 99 */ 100 function deleteTemplate( id ) { 101 // Update the field 102 $.ajax({ 103 url: baseUrl + '/templateEditor/deleteTemplate', 104 data: 'template=' + id, 105 type: "POST", 106 success: function(data, textStatus, request) { 107 // Remove the list item 108 deleteTemplateListItem( id ); 109 110 showHideEmpty( '#templates' ); 111 }, 112 error: function( request ) { 113 alert( "Could not delete template: " + request.responseText ); 114 } 115 }); 116 117 return true; 118 } 119 120 // Adds a new listitem when a field has been added 121 function addTemplateListItem( id, newHTML ) { 122 // Create a new listitem 123 var li = $( '<li></li>' ); 124 li.attr( 'id', 'template_' + id ); 125 li.addClass( "ui-state-default" ); 126 127 // Insert the right HTML 128 li.html( newHTML ); 129 130 // Append the listitem to the list 131 $( '#templates li:last').after( li ); 132 133 // Hide the 'empty' listitem, if needed 134 showHideEmpty( '#templates' ); 135 } 136 137 // Updates the contents of the listitem when something has changed 138 function updateTemplateListItem( id, newHTML ) { 139 var li = $( '#template_' + id ); 140 li.html( newHTML ); 141 } 142 143 // Removes a listitem when the template field has been deleted 144 function deleteTemplateListItem( id ) { 145 var li = $( '#template_' + id ); 146 li.remove(); 147 148 // Show the 'empty' listitem if the last item is deleted 149 showHideEmpty( '#templates' ); 150 } 151 152 /************************************* 153 * 154 * Methods for the template page with templatefields on it 155 * 156 *************************************/ 157 17 158 /** 18 159 * Is called on double click on a listitem … … 34 175 35 176 // Disable all other listitems 36 $( '# templateFields li:not(#' + list_item_id + ')').addClass( 'ui-state-disabled' );177 $( '#availableTemplateFields li:not(#' + list_item_id + ')').addClass( 'ui-state-disabled' ); 37 178 38 179 if( list_item_id != 'templateField_new' ) { … … 50 191 51 192 // Enable all other listitems 52 $( '# templateFields li:not(#templateField_' + id + ')').removeClass( 'ui-state-disabled' );193 $( '#availableTemplateFields li:not(#templateField_' + id + ')').removeClass( 'ui-state-disabled' ); 53 194 $( '#addNew').removeClass( 'ui-state-disabled' ); 54 195 55 196 formOpened = false; 197 } 198 199 200 201 /** 202 * Adds a new template field using AJAX 203 */ 204 function createTemplateField( id ) { 205 var formEl = $( '#templateField_' + id + '_form' ); 206 var templateId = $('#templateSelect').val(); 207 208 // Update the field 209 $.ajax({ 210 url: baseUrl + '/templateEditor/' + formEl.attr( 'action' ), 211 data: "template=" + templateId + "&" + formEl.serialize(), 212 dataType: 'json', 213 type: "POST", 214 success: function(data, textStatus, request) { 215 hideTemplateFieldForm( id ); 216 addFieldListItem( data.id, data.html ); 217 }, 218 error: function( request ) { 219 alert( "Could not add template field: " + request.responseText ); 220 } 221 }); 222 } 223 224 /** 225 * Updates the properties of a template field using AJAX 226 */ 227 function updateTemplateField( id ) { 228 var formEl = $( '#templateField_' + id + '_form' ); 229 230 // Update the field 231 $.ajax({ 232 url: baseUrl + '/templateEditor/' + formEl.attr( 'action' ), 233 dataType: 'json', 234 data: formEl.serialize(), 235 type: "POST", 236 success: function(data, textStatus, request) { 237 hideTemplateFieldForm( id ); 238 updateFieldListItem( id, data.html ); 239 }, 240 error: function( request ) { 241 alert( "Could not update template field: " + request.responseText ); 242 } 243 }); 56 244 } 57 245 … … 61 249 */ 62 250 function updateTemplateFieldPosition( event, ui ) { 251 // If the item is dragged to the 'availableTemplateFIelds list, we should not 'move' it 252 // Otherwise, when the item is dragged onto the selectedTemplateFields, but the 'sender' is availableTemplateFields, 253 // the item is added, and does not need to be moved 254 if( 255 ui.item.parent().attr( 'id' ) == 'availableTemplateFields' || 256 ui.item.parent().attr( 'id' ) == 'selectedTemplateFields' && ui.sender != null && ui.sender.attr( 'id' ) == 'availableTemplateFields' 257 ) { 258 // Return true, otherwise the move operation is canceled by jquery 259 return true; 260 } 63 261 // Find the new position of the element in the list 64 262 // http://stackoverflow.com/questions/2979643/jquery-ui-sortable-position 65 var newposition = ui.item.index(); 263 // 264 // Because there is also a hidden 'empty template' list item in the list, 265 // the number is decreased by 1 266 var newposition = ui.item.index() - 1; 66 267 67 268 // Find the ID of the templateField and template … … 71 272 72 273 // Create a URL to call and call it 73 var url = baseUrl + '/templateEditor/move ';274 var url = baseUrl + '/templateEditor/moveField'; 74 275 75 276 // Disable sorting until this move has been saved (in order to prevent collisions … … 83 284 type: 'POST', 84 285 success: function(data, textStatus, request) { 85 update ListItem( templateFieldId, data.html );286 updateFieldListItem( templateFieldId, data.html ); 86 287 $( '#templateFields' ).sortable( 'enable' ); 87 288 }, 88 error: function() { 89 alert( "Could not move template field" ); 90 } 91 }); 92 } 93 94 /** 95 * Adds a new template field using AJAX 96 */ 97 function addTemplateField( id ) { 98 var formEl = $( '#templateField_' + id + '_form' ); 289 error: function( request ) { 290 alert( "Could not move template field: " + request.responseText ); 291 } 292 }); 293 } 294 295 /** 296 * Adds a new template field to the template using AJAX 297 */ 298 function addTemplateFieldEvent( event, ui ) { 299 // Find the new position of the element in the list 300 // http://stackoverflow.com/questions/2979643/jquery-ui-sortable-position 301 // 302 // Because there is also a hidden 'empty template' list item in the list, 303 // the number is decreased by 1 304 var newposition = ui.item.index() - 1; 305 306 var item_id = ui.item.context.id; 307 var id = item_id.substring( item_id.lastIndexOf( '_' ) + 1 ); 308 309 return addTemplateField( id, newposition ); 310 } 311 312 /** 313 * Adds a new template field to the template using AJAX 314 */ 315 function addTemplateField( id, newposition ) { 316 if( newposition == null ) { 317 newposition = -1; 318 } 99 319 var templateId = $('#templateSelect').val(); 100 320 101 321 // Update the field 102 322 $.ajax({ 103 url: baseUrl + '/templateEditor/' + formEl.attr( 'action' ), 104 data: "template=" + templateId + "&" + formEl.serialize(), 105 dataType: 'json', 106 type: "POST", 107 success: function(data, textStatus, request) { 108 hideTemplateFieldForm( id ); 109 addListItem( data.id, data.html ); 110 }, 111 error: function() { 112 alert( "Could not add template field" ); 113 } 114 }); 115 } 116 117 /** 118 * Updates the properties of a template field using AJAX 119 */ 120 function updateTemplateField( id ) { 121 var formEl = $( '#templateField_' + id + '_form' ); 122 123 // Update the field 124 $.ajax({ 125 url: baseUrl + '/templateEditor/' + formEl.attr( 'action' ), 126 dataType: 'json', 127 data: formEl.serialize(), 128 type: "POST", 129 success: function(data, textStatus, request) { 130 hideTemplateFieldForm( id ); 131 updateListItem( id, data.html ); 132 }, 133 error: function() { 134 alert( "Could not update template field" ); 135 } 136 }); 323 url: baseUrl + '/templateEditor/addField', 324 data: "template=" + templateId + "&templateField=" + id + "&position=" + newposition, 325 dataType: 'json', 326 type: "POST", 327 success: function(data, textStatus, request) { 328 // Put the new HTML into the list item 329 updateFieldListItem( id, data.html ); 330 331 showHideEmpty( '#selectedTemplateFields' ); 332 showHideEmpty( '#availableTemplateFields' ); 333 }, 334 error: function( request ) { 335 alert( "Could not add template field: " + request.responseText ); 336 } 337 }); 338 } 339 340 341 /** 342 * Deletes a template field from a template using AJAX 343 */ 344 function removeTemplateFieldEvent( event, ui ) { 345 var item_id = ui.item.context.id; 346 var id = item_id.substring( item_id.lastIndexOf( '_' ) + 1 ); 347 348 // The field should only be removed when the study is not in use 349 // If field is used, the li has class 'inUse' 350 if( !ui.item.hasClass( 'inUse' ) ) { 351 return removeTemplateField( id ); 352 } else { 353 alert( "Field can not be removed, because the template is in use." ); 354 return false; 355 } 356 } 357 358 /** 359 * Removes a template field from a template using AJAX 360 */ 361 function removeTemplateField( id ) { 362 var templateId = $('#templateSelect').val(); 363 364 // Update the field 365 $.ajax({ 366 url: baseUrl + '/templateEditor/removeField', 367 data: 'template=' + templateId + '&templateField=' + id, 368 type: "POST", 369 success: function(data, textStatus, request) { 370 // Put the new HTML into the list item 371 updateFieldListItem( id, data.html ); 372 373 showHideEmpty( '#selectedTemplateFields' ); 374 showHideEmpty( '#availableTemplateFields' ); 375 376 }, 377 error: function( request ) { 378 alert( "Could not delete template field: " + request.responseText ); 379 } 380 }); 381 382 return true; 137 383 } 138 384 … … 141 387 */ 142 388 function deleteTemplateField( id ) { 143 var templateId = $('#templateSelect').val(); 144 145 // Update the field 146 $.ajax({ 147 url: baseUrl + '/templateEditor/delete', 148 data: 'template=' + templateId + '&templateField=' + id, 149 type: "POST", 150 success: function(data, textStatus, request) { 151 hideTemplateFieldForm( id ); 152 deleteListItem( id ); 153 }, 154 error: function() { 155 alert( "Could not delete template field" ); 156 } 157 }); 158 } 159 389 // Delete the field 390 $.ajax({ 391 url: baseUrl + '/templateEditor/deleteField', 392 data: 'templateField=' + id, 393 type: "POST", 394 success: function(data, textStatus, request) { 395 // Put the new HTML into the list item 396 deleteFieldListItem( id ); 397 398 showHideEmpty( '#availableTemplateFields' ); 399 }, 400 error: function( request ) { 401 alert( "Could not delete template field: " + request.responseText ); 402 } 403 }); 404 405 return true; 406 } 160 407 161 408 // Adds a new listitem when a field has been added 162 function add ListItem( id, newHTML ) {409 function addFieldListItem( id, newHTML ) { 163 410 // Create a new listitem 164 411 var li = $( '<li></li>' ); … … 170 417 171 418 // Append the listitem to the list 172 $( '# templateFields li:last').after( li );419 $( '#availableTemplateFields li:last').after( li ); 173 420 174 421 // Hide the 'empty' listitem 175 $( '#templateFields .empty' ).hide();422 showHideEmpty( '#availableTemplateFields' ); 176 423 } 177 424 178 425 // Updates the contents of the listitem when something has changed 179 function update ListItem( id, newHTML ) {426 function updateFieldListItem( id, newHTML ) { 180 427 var li = $( '#templateField_' + id ); 181 428 li.html( newHTML ); … … 183 430 184 431 // Removes a listitem when the template field has been deleted 185 function delete ListItem( id ) {432 function deleteFieldListItem( id ) { 186 433 var li = $( '#templateField_' + id ); 187 434 li.remove(); 188 435 189 436 // Show the 'empty' listitem if the last item is deleted 190 if( $( '#templateFields li:not(.empty)' ).length == 0 ) { 191 $( '#templateFields .empty' ).show(); 192 } 193 194 } 437 showHideEmpty( '#availableTemplateFields' ); 438 } 439 440 // Moves a listitem from one list to another 441 function moveFieldListItem( id, toSelector ) { 442 var li = $( '#templateField_' + id ); 443 li.remove(); 444 445 $( toSelector ).append( li ); 446 } 447 448 /** 449 * Shows or hides the list item, indicating that a list is empty 450 */ 451 function showHideEmpty( selector ) { 452 // Show the 'empty' listitem if the last item is deleted 453 if( $( selector + ' li:not(.empty)' ).length == 0 ) { 454 $( selector + ' .empty' ).show(); 455 } else { 456 $( selector + ' .empty' ).hide(); 457 } 458 }
Note: See TracChangeset
for help on using the changeset viewer.