Differences between revisions 3 and 4
Revision 3 as of 2010-01-27 11:00:28
Size: 29226
Editor: newacct
Comment:
Revision 4 as of 2010-05-23 07:52:15
Size: 29175
Editor: newacct
Comment:
Deletions are marked like this. Additions are marked like this.
Line 631: Line 631:
                 + formName.substring(1, formName.length());                  + formName.substring(1);
Line 732: Line 732:
                     return c + input.substring(pos, input.length());                      return c + input.substring(pos);
Line 754: Line 754:
             return c + input.substring(pos, input.length());              return c + input.substring(pos);

October 14, 2003

A simple adaption of the Struts Validator tag to extract the javascript code :) It's old code, but it works.

Any comments are welcome on the Velocity Developer's List <velocity-dev@jakarta.apache.org>.

Marinó A. Jónsson

--

here's an updated and cleaned up version: VelocityToolsValidatorTool

i don't have any apps set up with VelocityStruts + Validator right now that i can test this on. so, if someone would be willing to make sure i didn't screw things up, i'd appreciate it.

Nathan Bubna


{ { { 
/*
{{{ * The Apache Software License, Version 1.1 
 * 
 * Copyright (c) 2003 The Apache Software Foundation.  All rights 
 * reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 * 
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in 
 *    the documentation and/or other materials provided with the 
 *    distribution. 
 * 
 * 3. The end-user documentation included with the redistribution, if 
 *    any, must include the following acknowlegement: 
 *       "This product includes software developed by the 
 *        Apache Software Foundation (http://www.apache.org/)." 
 *    Alternately, this acknowlegement may appear in the software itself, 
 *    if and wherever such third-party acknowlegements normally appear. 
 * 
 * 4. The names "The Jakarta Project", "Velocity", and "Apache Software 
 *    Foundation" must not be used to endorse or promote products derived 
 *    from this software without prior written permission. For written 
 *    permission, please contact apache@apache.org. 
 * 
 * 5. Products derived from this software may not be called "Apache" 
 *    nor may "Apache" appear in their names without prior written 
 *    permission of the Apache Group. 
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE. 
 * ==================================================================== 
 * 
 * This software consists of voluntary contributions made by many 
 * individuals on behalf of the Apache Software Foundation.  For more 
 * information on the Apache Software Foundation, please see 
 * <http://www.apache.org/>. 
 */ 

package org.apache.velocity.tools.struts;

import org.apache.commons.validator.Field; import org.apache.commons.validator.Form; import org.apache.commons.validator.ValidatorAction; import org.apache.commons.validator.ValidatorResources; import org.apache.commons.validator.ValidatorUtil; import org.apache.commons.validator.Var; import org.apache.struts.Globals; import org.apache.struts.config.ModuleConfig; import org.apache.struts.util.MessageResources; import org.apache.struts.util.RequestUtils; import org.apache.struts.validator.Resources; import org.apache.struts.validator.ValidatorPlugIn;

import org.apache.velocity.tools.view.context.ViewContext; import org.apache.velocity.context.Context; import org.apache.velocity.tools.view.tools.ViewTool;

import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.util.*;

/** {{{ * <p>Title: ValidatorTool</p>

  • <p>Description: View tool to work with the Struts Validator to produce client side javascript validation.</p>

  • <p>Usage:

  • Template example:
  • <!-- javascript form validation -->

  • #set ($foo = $validator.setFormName("nameofyourform"))
  • $validator.javascript <-- spits out the dynamic javascript

  • or simply
  • $validator.javascript("nameOfYourForm")
  • Toolbox configuration:
  • <tool>

  • <key>validator</key>

  • <scope>request</scope>

  • <class>package org.apache.velocity.tools.struts.ValidatorTool</class>

  • </tool>

  • <p>This is a quick copy/paste of the JavascriptValidator Tag

  • from the Struts 1.1 validator library</p>

  • @author <a href="mailto:marinoj@centrum.is">Marino A. Jonsson</a>

  • @version $Revision: 1.1 $ $Date: 2003/07/24 04:59:21 $

    */ }}}

public class ValidatorTool implements ViewTool {

{{{ //


Properties


  • /**

    protected ViewContext context; /**

    protected ServletContext app; /**

    protected HttpServletRequest request; /**

    protected HttpSession session; /**

    • A reference to the Struts message resources.
    • /

    protected MessageResources resources; /**

    • The servlet context attribute key for our resources.
    • /
    protected String bundle = Globals.MESSAGES_KEY; /**
    • The name of the form that corresponds with the action name
    • in struts-config.xml. Specifying a form name places a
    • <script> </script> around the javascript.

    • /
    protected String formName = null; /**
    • The line ending string.
    • /
    protected static String lineEnd = System.getProperty("line.separator"); /**
    • The current page number of a multi-part form.
    • Only valid when the formName attribute is set.
    • /
    protected int page = 0; /**
    • This will be used as is for the JavaScript validation method name if it has a value. This is

    • the method name of the main JavaScript method that the form calls to perform validations.

    • /
    protected String methodName = null; /**
    • The static JavaScript methods will only be printed if this is set to "true".

    • /
    protected String staticJavascript = "true"; /**
    • The dynamic JavaScript objects will only be generated if this is set to "true".

    • /
    protected String dynamicJavascript = "true"; /**
    • The src attribute for html script element (used to include an external script
    • resource). The src attribute is only recognized
    • when the formName attribute is specified.
    • /
    protected String src = null; /**
    • The JavaScript methods will enclosed with html comments if this is set to "true".

    • /
    protected String htmlComment = "true"; /**
    • Hide JavaScript methods in a CDATA section for XHTML when "true".

    • /
    protected String cdata = "true";

    private String htmlBeginComment = "\n<!-- Begin \n";

    private String htmlEndComment = "//End --> \n"; private boolean xhtml = false;

    //


Constructors


  • /**
    • Default constructor. Tool must be initialized before use.
    • /

    public ValidatorTool() { } /**

    public void init(Object obj) {
    • if (!(obj instanceof ViewContext)) {

      }

      this.context = (ViewContext) obj; this.request = context.getRequest(); this.session = request.getSession(false); this.app = context.getServletContext();

      Boolean b = (Boolean)context.getAttribute(ViewContext.XHTML); if (b != null) {

      • xhtml = b.booleanValue();
      }
    }

    //


View Helpers


  • /**
    • Gets the key (form name) that will be used
    • to retrieve a set of validation rules to be
    • performed on the bean passed in for validation.
    • /
    public String getFormName() {
    • return formName;
    } /**
    • Sets the key (form name) that will be used
    • to retrieve a set of validation rules to be
    • performed on the bean passed in for validation.
    • Specifying a form name places a
    • <script> </script> tag around the javascript.

    • /
    public void setFormName(String formName) {
    • this.formName = formName;
    } /**
    • Gets the current page number of a multi-part form.
    • Only field validations with a matching page numer
    • will be generated that match the current page number.
    • Only valid when the formName attribute is set.
    • /
    public int getPage() {
    • return page;
    } /**
    • Sets the current page number of a multi-part form.
    • Only field validations with a matching page numer
    • will be generated that match the current page number.
    • Only valid when the formName attribute is set.
    • /
    public void setPage(int page) {
    • this.page = page;
    } /**
    • Gets the method name that will be used for the Javascript
    • validation method name if it has a value. This overrides
    • the auto-generated method name based on the key (form name)
    • passed in.
    • /
    public String getMethod() {
    • return methodName;
    } /**
    • Sets the method name that will be used for the Javascript
    • validation method name if it has a value. This overrides
    • the auto-generated method name based on the key (form name)
    • passed in.
    • /
    public void setMethod(String methodName) {
    • this.methodName = methodName;
    } /**
    • Gets whether or not to generate the static
    • JavaScript. If this is set to 'true', which

    • is the default, the static JavaScript will be generated.

    • /
    public String getStaticJavascript() {
    • return staticJavascript;
    } /**
    • Sets whether or not to generate the static
    • JavaScript. If this is set to 'true', which

    • is the default, the static JavaScript will be generated.

    • /
    public void setStaticJavascript(String staticJavascript) {
    • this.staticJavascript = staticJavascript;
    } /**
    • Gets whether or not to generate the dynamic
    • JavaScript. If this is set to 'true', which

    • is the default, the dynamic JavaScript will be generated.

    • /
    public String getDynamicJavascript() {
    • return dynamicJavascript;
    } /**
    • Sets whether or not to generate the dynamic
    • JavaScript. If this is set to 'true', which

    • is the default, the dynamic JavaScript will be generated.

    • /
    public void setDynamicJavascript(String dynamicJavascript) {
    • this.dynamicJavascript = dynamicJavascript;
    } /**
    • Gets whether or not to delimit the
    • JavaScript with html comments. If this is set to 'true', which

    • is the default, the htmlComment will be surround the JavaScript.

    • /
    public String getHtmlComment() {
    • return htmlComment;
    } /**
    • Sets whether or not to delimit the
    • JavaScript with html comments. If this is set to 'true', which

    • is the default, the htmlComment will be surround the JavaScript.

    • /
    public void setHtmlComment(String htmlComment) {
    • this.htmlComment = htmlComment;
    } /**
    • Gets the src attribute's value when defining
    • the html script element.
    • /
    public String getSrc() {
    • return src;
    } /**
    • Sets the src attribute's value when defining
    • the html script element. The src attribute is only recognized
    • when the formName attribute is specified.
    • /
    public void setSrc(String src) {
    • this.src = src;
    } /**
    • Render the JavaScript for to perform validations based on the form name.

    • @exception javax.servlet.jsp.JspException if a JSP exception has occurred

    • /
    public String getJavascript(String formName) throws Exception {
    • this.formName = formName;

      StringBuffer results = new StringBuffer();

      ModuleConfig config = RequestUtils.getModuleConfig(request, app); ValidatorResources resources = (ValidatorResources) app.getAttribute(

      Locale locale = StrutsUtils.getLocale(request, session); Form form = resources.get(locale, formName); if (form != null) {

      • if("true".equals(dynamicJavascript)) {
        • MessageResources messages = StrutsUtils.getMessageResources(request, app);

          List lActions = new ArrayList(); List lActionMethods = new ArrayList(); // Get List of actions for this Form for (Iterator i = form.getFields().iterator(); i.hasNext();) {

          • Field field = (Field) i.next(); for (Iterator x = field.getDependencies().iterator(); x.hasNext();) {
            • Object o = x.next();

              if (o != null && !lActionMethods.contains(o))

              • lActionMethods.add(o);
            }
          }

          // Create list of ValidatorActions based on lActionMethods for (Iterator i = lActionMethods.iterator(); i.hasNext();) {

          • String depends = (String) i.next();

            ValidatorAction va = resources.getValidatorAction(depends); // throw nicer NPE for easier debugging if (va == null) {

            • throw new NullPointerException(

              • "Depends string \

                • + depends + "\" was not found in validator-rules.xml.");
            } String javascript = va.getJavascript();

            if (javascript != null && javascript.length() > 0)

            • lActions.add(va);
            else
            • i.remove();
          } Collections.sort(lActions, new Comparator() {
          • public int compare(Object o1, Object o2) {
            • ValidatorAction va1 = (ValidatorAction) o1; ValidatorAction va2 = (ValidatorAction) o2;

              if ((va1.getDepends() == null || va1.getDepends().length() == 0)

              • && (va2.getDepends() == null || va2.getDepends().length() == 0)) { return 0;

              } else if (
              • (va1.getDepends() != null && va1.getDepends().length() > 0)

                • && (va2.getDepends() == null || va2.getDepends().length() == 0)) {

                return 1;
              } else if (
              • (va1.getDepends() == null || va1.getDepends().length() == 0)

                • && (va2.getDepends() != null && va2.getDepends().length() > 0)) {

                return -1;
              } else {
              • return va1.getDependencies().size() - va2.getDependencies().size();
              }
            }
          }); String methods = null; for (Iterator i = lActions.iterator(); i.hasNext();) {
          • ValidatorAction va = (ValidatorAction) i.next(); if (methods == null) {

            • methods = va.getMethod() + "(form)";
            } else {
            • methods += " && " + va.getMethod() + "(form)";

            }
          } results.append(getJavascriptBegin(methods)); for (Iterator i = lActions.iterator(); i.hasNext();) {
          • ValidatorAction va = (ValidatorAction) i.next(); String jscriptVar = null; String functionName = null;

            if (va.getJsFunctionName() != null && va.getJsFunctionName().length() > 0) {

            • functionName = va.getJsFunctionName();
            } else {
            • functionName = va.getName();
            } results.append(" function " + functionName + " () { \n"); for (Iterator x = form.getFields().iterator(); x.hasNext();) {
            • Field field = (Field) x.next(); // Skip indexed fields for now until there is a good way to handle // error messages (and the length of the list (could retrieve from scope?)) if (field.isIndexed()
              • || field.getPage() != page || !field.isDependency(va.getName())) { continue;
              } String message =
              • Resources.getMessage(messages, locale, va, field);

              message = (message != null) ? message : ; jscriptVar = this.getNextVar(jscriptVar); results.append(

              • " this."
                • + jscriptVar

                  + " = new Array(\ + field.getKey() + "\", \ + message + "\", ");

              results.append("new Function (\"varName\", \); Map vars = field.getVars(); // Loop through the field's variables. Iterator varsIterator = vars.entrySet().iterator(); while (varsIterator.hasNext()) {

              • Map.Entry entry = (Map.Entry) varsIterator.next(); String varName = (String) entry.getKey(); Var var = (Var) entry.getValue(); String varValue = var.getValue(); String jsType = var.getJsType(); // skip requiredif variables field, fieldIndexed, fieldTest, fieldValue if (varName.startsWith("field")) {
                • continue;
                } if (Var.JSTYPE_INT.equalsIgnoreCase(jsType)) {
                • results.append(
                  • "this."
                    • + varName + "="

                      + ValidatorUtil.replace(

                      • varValue, "\\", "\\\\")
                      + "; ");
                } else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType)) {
                • results.append(
                  • "this."
                    • + varName + "=/"

                      + ValidatorUtil.replace(

                      • varValue, "\\", "\\\\")
                      + "/; ");
                } else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType)) {
                • results.append(
                  • "this."
                    • + varName + "='"

                      + ValidatorUtil.replace(

                      • varValue, "\\", "\\\\")
                      + "'; ");
                  // So everyone using the latest format doesn't need to change their xml files immediately.
                } else if ("mask".equalsIgnoreCase(varName)) {
                • results.append(
                  • "this."
                    • + varName + "=/"

                      + ValidatorUtil.replace(

                      • varValue, "\\", "\\\\")
                      + "/; ");
                } else {
                • results.append(
                  • "this."
                    • + varName + "='"

                      + ValidatorUtil.replace(

                      • varValue, "\\", "\\\\")
                      + "'; ");
                }
              } results.append(" return this[varName];\"));\n");
            } results.append(" } \n\n");
          }
        } else if ("true".equalsIgnoreCase(staticJavascript)) {
        • results.append(this.getStartElement()); if ("true".equalsIgnoreCase(htmlComment)) {
          • results.append(htmlBeginComment);
          }
        }
      } if ("true".equalsIgnoreCase(staticJavascript)) {
      • results.append(getJavascriptStaticMethods(resources));
      } if (form != null
      • && ("true".equalsIgnoreCase(dynamicJavascript)

        • || "true".equalsIgnoreCase(staticJavascript))) {
        results.append(getJavascriptEnd());
      } return results.toString();
    } /**
    • Returns the opening script element and some initial javascript.
    • /
    • protected String getJavascriptBegin(String methods) {
      • StringBuffer sb = new StringBuffer(); String name =

        • formName.substring(0, 1).toUpperCase()
          • + formName.substring(1);
        sb.append(this.getStartElement());

        if (this.xhtml && "true".equalsIgnoreCase(this.cdata)) {

        • sb.append("<![CDATA[\r\n");

        }

        if (!this.xhtml && "true".equals(htmlComment)) {

        • sb.append(htmlBeginComment);
        } sb.append("\n var bCancel = false; \n\n");

        if (methodName == null || methodName.length() == 0) {

        • sb.append(
          • " function validate"
            • + name + "(form) { \n");
        } else {
        • sb.append(
          • " function "
            • + methodName + "(form) { \n");
        } sb.append(" if (bCancel) \n"); sb.append(" return true; \n"); sb.append(" else \n"); // Always return true if there aren't any Javascript validation methods

        if (methods == null || methods.length() == 0) {

        • sb.append(" return true; \n");
        } else {
        • sb.append(" return " + methods + "; \n");
        } sb.append(" } \n\n"); return sb.toString();
      }

      protected String getJavascriptStaticMethods(ValidatorResources resources) {

      • StringBuffer sb = new StringBuffer(); sb.append("\n\n"); Iterator actions = resources.getValidatorActions().values().iterator(); while (actions.hasNext()) {

        • ValidatorAction va = (ValidatorAction) actions.next(); if (va != null) {

          • String javascript = va.getJavascript();

            if (javascript != null && javascript.length() > 0) {

            • sb.append(javascript + "\n");
            }
          }
        } return sb.toString();
      } /**
      • Returns the closing script element.
      • /
      protected String getJavascriptEnd() {
      • StringBuffer sb = new StringBuffer(); sb.append("\n");

        if (!this.xhtml && "true".equals(htmlComment)){

        • sb.append(htmlEndComment);
        }

        if (this.xhtml && "true".equalsIgnoreCase(this.cdata)) {

        • sb.append("]]>\r\n");

        }

        sb.append("</script>\n\n"); return sb.toString();

      } /**
      • The value <code>null</code> will be returned at the end of the sequence.

      •     ex: "zz" will return <code>null</code>

      • /
      private String getNextVar(String input) {
      • if (input == null) {
        • return "aa";
        } input = input.toLowerCase();

        for (int i = input.length(); i > 0; i--) {

        • int pos = i - 1; char c = input.charAt(pos); c++;

          if (c <= 'z') {

          • if (i == 0) {
            • return c + input.substring(pos);
            } else if (i == input.length()) {
            • return input.substring(0, pos) + c;
            } else {
            • return input.substring(0, pos) + c + input.substring(pos, input.length() - 1);
            }
          } else {
          • input = replaceChar(input, pos, 'a');
          }
        } return null;
      } /**
      • Replaces a single character in a <code>String</code>

      • /
      private String replaceChar(String input, int pos, char c) {
      • if (pos == 0) {
        • return c + input.substring(pos);
        } else if (pos == input.length()) {
        • return input.substring(0, pos) + c;
        } else {
        • return input.substring(0, pos) + c + input.substring(pos, input.length() - 1);
        }
      }
    /**
    • Constructs the beginning <script> element depending on xhtml status.

    • /
    private String getStartElement() {
    • StringBuffer start = new StringBuffer("<script type=\"text/javascript\); // there is no language attribute in xhtml if (!this.xhtml) {

      • start.append(" language=\"Javascript1.1\);

      } if (this.src != null) {
      • start.append(" src=\ + src + "\);

      }

      start.append("> \n"); return start.toString();

    } /**
    • Returns the cdata setting "true" or "false".
    • @return String - "true" if JavaScript will be hidden in a CDATA section

    • /
    public String getCdata() {
    • return cdata;
    } /**
    • Sets the cdata status.
    • @param cdata The cdata to set
    • /
    public void setCdata(String cdata) {
    • this.cdata = cdata;
    } }}}

} {{{ } } }

  • }}}

ValidatorTool (last edited 2010-05-23 07:52:15 by newacct)