[ 
https://issues.apache.org/jira/browse/TAPESTRY-1246?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jesse Kuhnert updated TAPESTRY-1246:
------------------------------------

    Fix Version/s:     (was: 4.1.3)
                   4.1.4

> Clientside validation patch
> ---------------------------
>
>                 Key: TAPESTRY-1246
>                 URL: https://issues.apache.org/jira/browse/TAPESTRY-1246
>             Project: Tapestry
>          Issue Type: Improvement
>          Components: JavaScript
>    Affects Versions: 4.1.2
>         Environment: Any
>            Reporter: Andrea Chiumenti
>            Priority: Minor
>             Fix For: 4.1.4
>
>         Attachments: validation.js
>
>
> I've patched the client side validation script file so that an input field in 
> exception status reports its related exceptions with a dojo tooltip.
> When the validation is performed a second time all the exception  tooltip 
> widgets are disposed and recreated as necessary.
> I hope you find it useful.
> Ciao,
> kiuma
> vlidation.js
> ===============================================================================================
> dojo.provide("tapestry.form.validation");
> dojo.require("dojo.validate.check");
> dojo.require("dojo.html.style");
> dojo.require("dojo.widget.*");
> dojo.require("tapestry.widget.AlertDialog");
> dojo.require("dojo.widget.Tooltip");
> dojo.require("dojo.collections.ArrayList");
> tapestry.form.validation={
>       //exceptionWidgets: [], //new dojo.collections.ArrayList(), 
>       missingClass:"fieldMissing", // default css class that will be applied 
> to fields missing a value
>       invalidClass:"fieldInvalid", // default css class applied to fields 
> with invalid data
>       
>       dialogName:"tapestry:AlertDialog",
>       
>       /**
>        * Main entry point for running form validation. The
>        * props object passed in contains a number of fields that 
>        * are managed by tapestry.form:
>        * 
>        *              props = {
>        *                      validateForm:[true|false] // whether to run 
> validation at all
>        *                      profiles:[profile1, profile2] // set of 
> dojo.validate.check() style profiles
>        *                                                                      
>           // that may have been registered with form
>        *              }
>        * 
>        * The individual profiles will contain any of the data described by 
> the dojo documentation
>        * for dojo.validate.check(). In addition to that, each profile will 
> also have a corresponding
>        * string message to display if the specified condition has been met. 
> For example, if you have
>        * specified that a select field named "select1" was required your 
> profile would look something
>        * like:
>        * 
>        *              profile = {
>        *                      "required":["select1"], // normal 
> dojo.validate.check data
>        *                      "select1":{ // tapestry field/error type 
> specific data
>        *                              "required":"You must select a value for 
> select1."
>        *                      }
>        *              }
>        * 
>        * It is intended for you to call dojo.validate.check(form, profile) 
> for each profile
>        * stored in the "profiles" field, as well as deciding how to display 
> errors / warnings.
>        * 
>        * @return Boolean indicating if form submission should continue. If 
> false the form
>        *                      will ~not~ be submitted. 
>        */
>       validateForm:function(form, props){
>               if (typeof form == "undefined") {return false;}
>               if (typeof props == "undefined") {return true;} // form exists 
> but no profile? just submit I guess..
>               if (!props.validateForm) {return true;}
>               
>               try {
>                       this.clearValidationDecorations(form, props);           
>         
>                       for (var i=0; i < props.profiles.length; i++) {
>                               this._clearExceptionWidgets(props.profiles[i]);
>                               var results=dojo.validate.check(form, 
> props.profiles[i]);                               
>                               if (!this.processResults(form, results, 
> props.profiles[i])) {
>                                       this.summarizeErrors(form, results, 
> props.profiles[i]);
>                                       return false;
>                               }
>                       }
>               } catch (e) { 
>                       // since so many dynamic function calls may happen in 
> here it's best that we 
>                       // catch all of them and log them or else peoples forms 
> might still get submitted
>                       // and they'd never be able to figure out what was wrong
>                       dojo.log.exception("Error validating", e, true);
>                       return false;
>               }
>               
>               return true;
>       },
>       
>       /**
>        * Called for each registered profile on a form after 
>        * dojo.validate.check() has been called. This function is 
>        * expected to do UI related notifications of fields in error.
>        * 
>        * @param form The form that was validated.
>        * @param results The result of calling 
> dojo.validate.check(form,profile)
>        * @param profile The original profile used to validate form, also 
> holds 
>        *                                validation error messages to be used 
> for each field.
>        * 
>        * @return Boolean, if false form should not be submitted and all 
> validation 
>        *                 should be stopped. If true validation will continue 
> and eventually
>        *                 form will be submitted.
>        */
>       processResults:function(form, results, profile){
>               if (results.isSuccessful()) { return true; } 
>               
>               var formValid=true;
>               if (results.hasMissing()) {
>                       var missing=results.getMissing();
>                       for (var i=0; i < missing.length; i++) {
>                               this.handleMissingField(missing[i], profile);
>                       }
>                       
>                       formValid=false;
>               }
>               
>               if (results.hasInvalid()) {
>                       var invalid=results.getInvalid();
>                       for (var i=0; i < invalid.length; i++) {
>                               this.handleInvalidField(invalid[i], profile);
>                       }
>                       
>                       formValid=false;
>               }
>               
>               return formValid; // if got past successful everything is 
> invalid
>       },
>       
>       /**
>        * Default field decorator for missing fields.
>        * 
>        * @param field The field element that was missing data.
>        * @param profile The form validation profile.
>        */
>       handleMissingField:function(field, profile){
>               field=dojo.byId(field);
>               if (dj_undef("type", field)) {return;}
>               dojo.html.removeClass(field, this.invalidClass);
>               
>               if (!dojo.html.hasClass(field, this.missingClass)){
>                       dojo.html.prependClass(field, this.missingClass);
>               }
>       },
>       
>       /**
>        * Default field decorator for invalid fields.
>        * 
>        * @param field The field element that had invalid data.
>        * @param profile The form validation profile.
>        */
>       handleInvalidField:function(field, profile){
>               field=dojo.byId(field);
>               if (dj_undef("type", field)) {return;}
>               dojo.html.removeClass(field, this.missingClass);
>               
>               if (!dojo.html.hasClass(field, this.invalidClass)){
>                       dojo.html.prependClass(field, this.invalidClass);
>               }
>       },
>       
>       /**
>        * Clears out previous css classes set on fields 
>        * in error.
>        */
>       clearValidationDecorations:function(form, props){
>               for (var i=0; i< form.elements.length; i++) {
>                       if (dj_undef("type", form.elements[i]) || typeof 
> form.elements[i].type == "undefined"
>                               || form.elements[i].type == "submit" 
>                               || form.elements[i].type == "hidden") { 
> continue; }
>                       
>                       dojo.html.removeClass(form.elements[i], 
> this.missingClass);
>                       dojo.html.removeClass(form.elements[i], 
> this.invalidClass);
>               }
>       },
>       
>       /**
>        * Optionally allows an alert dialog/dhtml dialog/etc to 
>        * be displayed to user to alert them to the invalid state
>        * of their form if validation errors have occurred. 
>        * 
>        * @param form The form being validated.
>        * @param results Returned value of dojo.validate.check(form, profile)
>        * @param profile Validation profile definition 
>        */
>       summarizeErrors:function(form, results, profile){
>               var merrs=[];
>               var ierrs=[];
>               var fieldErrs=[];
>               
>               tapestry.form.currentFocus=null;
>               //this._clearExceptionWidgets();
>               if (results.hasMissing()){
>                       var fields=results.getMissing();
>                       for (var i=0; i<fields.length; i++){
>                               fieldErrs=[];
>                               if(i==0 && !tapestry.form.currentFocus){
>                                       tapestry.form.currentFocus=fields[i];
>                               }
>                               
>                               if (profile[fields[i]] && 
> profile[fields[i]]["required"]){
>                                       if 
> (dojo.lang.isArray(profile[fields[i]]["required"])) {                         
>                
>                                               for (var z=0; z < 
> profile[fields[i]]["required"].length; z++) {
>                                                       
> merrs.push(profile[fields[i]]["required"][z]);
>                                                       
> fieldErrs.push(profile[fields[i]]["required"][z]);
>                                               }
>                                       } else {
>                                               
> merrs.push(profile[fields[i]]["required"]);
>                                               
> fieldErrs.push(profile[fields[i]]["required"]);
>                                       }
>                                       //alert(fields[i]);
>                                       
> this._buildExceptionTooltipWidget(profile, fields[i], fieldErrs, null);
>                               }                               
>                       }
>               }
>               if (results.hasInvalid()){
>                       var fields=results.getInvalid();
>                       for (var i=0; i<fields.length; i++){
>                               fieldErrs=[];
>                               if(i==0 && !tapestry.form.currentFocus){
>                                       tapestry.form.currentFocus=fields[i];
>                               }
>                               if (profile[fields[i]] && 
> profile[fields[i]]["constraints"]){
>                                       if 
> (dojo.lang.isArray(profile[fields[i]]["constraints"])) {
>                                               for (var z=0; z < 
> profile[fields[i]]["constraints"].length; z++) {
>                                                       
> ierrs.push(profile[fields[i]]["constraints"][z]);
>                                                       
> fieldErrs.push(profile[fields[i]]["constraints"][z]);
>                                               }
>                                       } else {
>                                               
> ierrs.push(profile[fields[i]]["constraints"]);
>                                               
> fieldErrs.push(profile[fields[i]]["constraints"]);
>                                       }
>                                       //alert(fields[i]);
>                                       
> this._buildExceptionTooltipWidget(profile, fields[i], null, fieldErrs);
>                               }
>                       }
>               }
>               
>               var msg="";
>               if (merrs.length > 0) {
>                       msg+='<ul class="missingList">';
>                       for (var i=0; i<merrs.length;i++) {
>                               msg+="<li>"+merrs[i]+"</li>";
>                       }
>                       msg+="</ul>";
>               }
>               if (ierrs.length > 0) {
>                       msg+='<ul class="invalidList">';
>                       for (var i=0; i<ierrs.length;i++) {
>                               msg+="<li>"+ierrs[i]+"</li>";
>                       }
>                       msg+="</ul>";
>               }
>               
>               var ad=dojo.widget.byId("validationDialog");
>               if (ad) {
>                       ad.setMessage(msg);
>                       ad.show();
>                       return;
>               }
>               
>               var node=document.createElement("span");
>               document.body.appendChild(node);
>               var dialog=dojo.widget.createWidget(this.dialogName, 
>                                               {
>                                                       
> widgetId:"validationDialog",
>                                                       message:msg
>                                               }, node);
>               dialog.show();
>       },
>       
>       /**
>        * Clears all exception tooltip widgets
>        *       
>        */
>       _clearExceptionWidgets: function(profile) {
>               if (!profile.exceptionWidgets) {
>                       profile.exceptionWidgets = new 
> dojo.collections.ArrayList();
>               }
>               var iter = profile.exceptionWidgets.getIterator();
>               
>               while (widget = iter.get()) {
>                       try {
>                               widget.destroy()
>                       } catch (e) {
>                               dojo.log.exception("Error destroying widget.", 
> e, true);
>                       }
>                       
>               }
>               profile.exceptionWidgets.clear();
>       },
>       /**
>        * Creates the field exception tooltip if necessary.
>        * 
>        * @param fieldId The id of the field that has to expose an exception 
> tooltip
>        * @return Returns The exception tooltip dom element.
>        */
>       _createExceptionTooltip: function(fieldId) {            
>               
>               var id = fieldId + "-err";
>               
>               var el = dojo.byId(id);
>               if (!el) {
>                       el = document.createElement("div");             
>                       el.id=id;
>                       el.className="exceptionTooltip";                        
>                       dojo.dom.insertBefore(el, dojo.byId(fieldId));          
>         
>               }                       
>               el.innerHTML = "";
>               return el;              
>       },
>       /**
>        * Fills the content of the exception tooltip with exception messages
>        * if messages is not empty
>        *       
>        * @param exceptions The exception message array 
>        * @param listType May be 'missingList' or 'invalidList', default is 
> 'missingList'.
>        *
>        * @return Returns the innerHTML that needs to be added to the tooltip 
> dom element
>        */
>       _buildExceptionTooltip: function(exceptions, listType) {                
>               var msg ="";
>               
>               if ((exceptions)&&(exceptions.length > 0)) {
>                       if (!listType) {
>                               listType = "missingList";
>                       }
>                       msg+='<ul class="'+listType+'">';
>                       for (var i=0; i<exceptions.length;i++) {
>                               msg+="<li>"+exceptions[i]+"</li>";
>                       }
>                       msg+="</ul>";
>               }
>               return msg;             
>       },
>       /**
>        * Creates a tooltip exception widget.
>        *
>        * @param fieldId. The id of the field in exception status.
>        * @param missingListExceptions The array containing missing value 
> exception messages
>        * @param invalidListExceptions The array containing invalid value 
> exception messages
>        */
>       _buildExceptionTooltipWidget: function(profile, fieldId, 
> missingListExceptions, invalidListExceptions) {
>               if (!profile.exceptionWidgets) {
>                       profile.exceptionWidgets = new 
> dojo.collections.ArrayList();
>               }
>               var tooltipEl = this._createExceptionTooltip(fieldId);
>               tooltipEl.innerHTML = 
> this._buildExceptionTooltip(missingListExceptions, "missingList");
>               tooltipEl.innerHTML += 
> this._buildExceptionTooltip(invalidListExceptions, "invalidList");
>               var widget = dojo.widget.createWidget("Tooltip", {id:fieldId + 
> "-tip", connectId:fieldId, toggle:"explode"}, tooltipEl);                
>               profile.exceptionWidgets.add(widget);
>       },
>       /**
>        * Validates that the input value matches the given 
>        * regexp pattern.
>        * 
>        * @param value The string value to be evaluated.
>        * @param pattern The regexp pattern used to match against value.
>        */
>       isValidPattern:function(value, pattern){
>               if (typeof value != "string" || typeof pattern != "string") { 
> return false; }
>               
>               var re = new RegExp(pattern);
>               return re.test(value);
>       },
>       
>       isPalleteSelected:function(elem){
>               if (elem.length > 0) { return true; }
>               return false;
>       }
> }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to