You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by bu...@apache.org on 2004/07/02 15:59:41 UTC

DO NOT REPLY [Bug 29885] New: - Action based client side validation

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=29885>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=29885

Action based client side validation

           Summary: Action based client side validation
           Product: Struts
           Version: Nightly Build
          Platform: Other
        OS/Version: Other
            Status: NEW
          Severity: Normal
          Priority: Other
         Component: Custom Tags
        AssignedTo: dev@struts.apache.org
        ReportedBy: modi_kalpesh@yahoo.com
                CC: modi_kalpesh@yahoo.com


Hi,
I patched <html:javascript> tag with help from Adrian Lanning, to allow
PER-METHOD (or Per-Action depending on if you use the VLDAction) client-side
validation. This is especially useful when using Brandon's VLDAction since each
method in the action (read "button on the page") can use an independent
Validator form defined in validation.xml and still have client-side validation.  

[Background] Brandon's ValidatorLookupDispatchAction lets you define
mappings in your struts-config file directly to specific methods.  If 
your action is User, you can have User.view, User.add, User.delete, and 
User.edit all handled in the same Action and Action-Mapping.[/Background]

The <html:javascript> tag code is as follows :
===============================================

/*
 * $Header:
/home/cvspublic/jakarta-struts/src/share/org/apache/struts/taglib/html/JavascriptValidatorTag.java,v
1.50 2004/03/14 06:23:46 sraeburn Exp $
 * $Revision: 1.50 $
 * $Date: 2004/03/14 06:23:46 $
 *
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.atsva.glin.helper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;

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.validator.Resources;
import org.apache.struts.validator.ValidatorPlugIn;
import java.util.StringTokenizer;
import org.apache.struts.util.RequestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.validator.ValidatorPlugIn;
import org.apache.commons.validator.util.ValidatorUtils;
import org.apache.struts.taglib.TagUtils;

/**
 * Custom tag that generates JavaScript for client side validation based
 * on the validation rules loaded by the <code>ValidatorPlugIn</code>
 * defined in the struts-config.xml file.
 *
 * @version $Revision: 1.50 $ $Date: 2004/03/14 06:23:46 $
 * @since Struts 1.1
 */
public class CustomJavascriptTag extends BodyTagSupport {

    /**
     * A Comparator to use when sorting ValidatorAction objects.
     */
    private static final Comparator actionComparator = 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();
            }
        }
    };

    /**
     * The start of the HTML comment hiding JavaScript from old browsers.
     * @since Struts 1.2
     */
    protected static final String HTML_BEGIN_COMMENT = "\n<!-- Begin \n";

    /**
     * The end of the HTML comment hiding JavaScript from old browsers.
     * @since Struts 1.2
     */
    protected static final String HTML_END_COMMENT = "//End --> \n";

    // ----------------------------------------------------------- Properties

    /**
     * The servlet context attribute key for our resources.
     */
    protected String bundle = Globals.MESSAGES_KEY;

    /**
     * The default locale on our server.
     * @deprecated This variable is no longer used.
     */
    protected static Locale defaultLocale = Locale.getDefault();

    /**
     * The name of the form that corresponds with the form name
     * in struts-config.xml. Specifying a form name places a
     * &lt;script&gt; &lt;/script&gt; around the javascript.
     */
    protected String formName = null;
    
    /**
     * The name of the form that corresponds with the action name
     * in struts-config.xml. Specifying a form name places a
     * &lt;script&gt; &lt;/script&gt; around the javascript.
     */
    protected String formNames = 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 formNames 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;

    /**
     * Include language attribute in the &lt;script&gt; element.  This property is
     * ignored in XHTML mode.
     * @since Struts 1.2
     */
    protected boolean scriptLanguage = true;

    /**
     * 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 formNames 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";

    /**
     * Gets the key (form names) 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
     * &lt;script&gt; &lt;/script&gt; tag around the javascript.
     */
    public void setFormName(String formName) {
        this.formName = formName;
    }
    
    /**
     * Gets the key (form names) that will be used
     * to retrieve a set of validation rules to be
     * performed on the actions passed in for validation.
     */
    public String getFormNames() {
        return formNames;
    }

    /**
     * Sets the key (form name) that will be used
     * to retrieve a set of validation rules to be
     * performed on the actions passed in for validation.
     */
    public void setFormNames(String formNames) {
        this.formNames = formNames;
    }
    
    /**
     * 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 formNames 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 formNames 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 formNames attribute is specified.
     */
    public void setSrc(String src) {
        this.src = src;
    }

    /**
     * Render the JavaScript for to perform validations based on the form name.
     *
     * @exception JspException if a JSP exception has occurred
     */
    public int doStartTag() throws JspException {
        JspWriter writer = pageContext.getOut();
        try{
            StringBuffer results = new StringBuffer();

            ModuleConfig config = RequestUtils.getModuleConfig(pageContext);
            ValidatorResources resources = (ValidatorResources)
pageContext.getAttribute(
                                    ValidatorPlugIn.VALIDATOR_KEY +
config.getPrefix(),
                                    PageContext.APPLICATION_SCOPE);

            Locale locale = RequestUtils.retrieveUserLocale(this.pageContext, null);
            String[] formArray;
            Form form = null;
            if(formName != null){
                form = resources.get(locale, formName);
                if ("true".equalsIgnoreCase(dynamicJavascript) && form == null){
                        throw new JspException("No form found under '"
                                               + form.getName()
                                               + "' in locale '"
                                               + locale
                                               + "'");
                }
                if(form != null){
                    if ("true".equalsIgnoreCase(dynamicJavascript)){
                        results.append(this.renderStartElement());
                        results.append(this.renderAfterStartElement());
                        results.append(this.createDynamicJavascript(config,
resources, locale, form,form.getName()));
                    }else if("true".equalsIgnoreCase(staticJavascript)){
                        results.append(this.renderStartElement());
                        if ("true".equalsIgnoreCase(htmlComment)){
                            results.append(HTML_BEGIN_COMMENT);
                        }
                    }
                }
                if("true".equalsIgnoreCase(staticJavascript)){
                    results.append(getJavascriptStaticMethods(resources));
                }
                if (form != null
                    && ("true".equalsIgnoreCase(dynamicJavascript)
                    || "true".equalsIgnoreCase(staticJavascript))){

                    results.append(getJavascriptEnd());
                }
            }
            if(formNames != null){
                
                formArray = formNames.split(",");
                if(formArray != null){
                    results.append(this.renderStartElement());
                    results.append(this.renderAfterStartElement());
                    for(int i=0;i<formArray.length;i++){
                        form = resources.get(locale, formArray[i].trim());
                        if ("true".equalsIgnoreCase(dynamicJavascript) && form
== null){
                            throw new JspException("No form found under '"
                                                   + formArray[i].trim()
                                                   + "' in locale '"
                                                   + locale
                                                   + "'");
                        }
                        if(form != null){
                            if ("true".equalsIgnoreCase(dynamicJavascript)){
                               
results.append(this.createDynamicJavascript(config, resources, locale,
form,formArray[i]));
                            }
                        }
                    }
                }
                if(form != null){
                    if("true".equalsIgnoreCase(staticJavascript) &&
"false".equalsIgnoreCase(dynamicJavascript)){
                        results.append(this.renderStartElement());
                        if ("true".equalsIgnoreCase(htmlComment)){
                            results.append(HTML_BEGIN_COMMENT);
                        }
                    }
                }
                if("true".equalsIgnoreCase(staticJavascript)){
                    results.append(getJavascriptStaticMethods(resources));
                }
                if (form != null
                    && ("true".equalsIgnoreCase(dynamicJavascript)
                    || "true".equalsIgnoreCase(staticJavascript))){

                    results.append(getJavascriptEnd());
                }
            }
            
            writer.print(results.toString());

        } catch (IOException e) {
            throw new JspException(e.getMessage());
        }

        return EVAL_BODY_TAG;

    }

    
    /**
     * Generates the dynamic JavaScript for the form.
     * @param config
     * @param resources
     * @param locale
     * @param form
     */
    private String createDynamicJavascript(
        ModuleConfig config,
        ValidatorResources resources,
        Locale locale,
        Form form, String formName) {

        StringBuffer results = new StringBuffer();

        MessageResources messages =
            (MessageResources) pageContext.getAttribute(
                bundle + config.getPrefix(),
                PageContext.APPLICATION_SCOPE);

        List actions = this.createActionList(resources, form);
        HashMap hm = new HashMap();
        for(Iterator k = actions.iterator();k.hasNext(); ){
            ValidatorAction va = (ValidatorAction)k.next();
            String method = va.getMethod();
            String funcName = null;
            String finalFName = null;
            if (va.getJsFunctionName() != null &&
va.getJsFunctionName().length() > 0){
                funcName = va.getJsFunctionName();
            }else{
                funcName = va.getName();
            }
            
            String fName = form.getName();
            fName = fName.replace('/','_');
            fName = fName.replace('.','_');
            if(fName.charAt(0) == '_'){
                finalFName = fName.substring(1) + "_" + funcName;
            }else{
                finalFName = fName + "_" + funcName;
            }
            // create a hashmap for the method name and corresponding actions
            hm.put(method,finalFName);
        }
        
        final String methods =
this.createMethods(actions,hm,this.stopOnError(config));
        results.append(this.getJavascriptBegin(methods,formName));

        for (Iterator i = actions.iterator(); i.hasNext();) {
            ValidatorAction va = (ValidatorAction) i.next();
            int jscriptVar = 0;
            String functionName = null;


            if (va.getJsFunctionName() != null
                && va.getJsFunctionName().length() > 0) {
                functionName = va.getJsFunctionName();
            } else {
                functionName = va.getName();
            }

            formName = formName.replace('/','_');
            formName = formName.replace('.','_');
            if(formName.charAt(0) == '_'){
                formName = formName.substring(1);
            }
            String finalFunctionName = formName + "_" + functionName;
            results.append("    function " + finalFunctionName + " () { \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 : "";

                // prefix variable with 'a' to make it a legal identifier
                results.append(
                    "     this.a"
                        + jscriptVar++
                        + " = new Array(\""
                        + field.getKey()
                        + "\", \""
                        + escapeQuotes(message)
                        + "\", ");

                results.append("new Function (\"varName\", \"");

                Map vars = field.getVars();
                // Loop through the field's variables.
                Iterator varsIterator = vars.keySet().iterator();
                while (varsIterator.hasNext()) {
                    String varName = (String) varsIterator.next();
                    Var var = (Var) vars.get(varName);
                    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");
        }

        return results.toString();
    }

    private String escapeQuotes(String in)
    {
        if (in == null || in.indexOf("\"") == -1)
        {
            return in;
        }
        StringBuffer buffer = new StringBuffer();
        StringTokenizer tokenizer = new StringTokenizer(in, "\"", true);

        while (tokenizer.hasMoreTokens())
        {
            String token = tokenizer.nextToken();
            if (token.equals("\""))
            {
                buffer.append("\\");
            }
            buffer.append(token);
        }

        return buffer.toString();
    }

    
    /**
     * Determines if validations should stop on an error.
     * @param config The <code>ModuleConfig</code> used to lookup the
     * stopOnError setting.
     * @return <code>true</code> if validations should stop on errors.
     */
    private boolean stopOnError(ModuleConfig config) {
        Object stopOnErrorObj =
            pageContext.getAttribute(
                ValidatorPlugIn.STOP_ON_ERROR_KEY + '.' + config.getPrefix(),
                PageContext.APPLICATION_SCOPE);

        boolean stopOnError = true;

        if (stopOnErrorObj instanceof Boolean) {
            stopOnError = ((Boolean) stopOnErrorObj).booleanValue();
        }

        return stopOnError;
    }


    /**
     * Creates the JavaScript methods list from the given actions.
     * @param actions A List of ValidatorAction objects.
     * @param stopOnError If true, behaves like released version of struts 1.1
     *        and stops after first error. If false, evaluates all validations.
     * @return JavaScript methods.
     */
    private String createMethods(List actions,HashMap hm,boolean stopOnError) {
        String methods = null;
	final String methodOperator = stopOnError ? " && " : " & ";
        

        Iterator iter = actions.iterator();
        while (iter.hasNext()) {
            ValidatorAction va = (ValidatorAction) iter.next();
            String met = va.getMethod();
            String strMet = met.substring(8);
            
            if(hm.containsKey(met)){
                String s = hm.get(met).toString();
                if(methods == null){
                    methods = met + "(form," + s + ")";
                }else{
                    methods += methodOperator + met + "(form," + s + ")";
                }
            }
       }
       return methods;
    }

    /**
     * Get List of actions for the given Form.
     * @param resources
     * @param form
     * @return A sorted List of ValidatorAction objects.
     */
    private List createActionList(ValidatorResources resources, Form form) {

        List actionMethods = new ArrayList();

        Iterator iterator = form.getFields().iterator();
        while (iterator.hasNext()) {
            Field field = (Field) iterator.next();

            for (Iterator x = field.getDependencies().iterator(); x.hasNext();) {
                Object o = x.next();
                if (o != null && !actionMethods.contains(o)) {
                    actionMethods.add(o);
                }
            }
        }

        List actions = new ArrayList();

        // Create list of ValidatorActions based on actionMethods
        iterator = actionMethods.iterator();
        while (iterator.hasNext()) {
            String depends = (String) iterator.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.");
            }

            if (va.getJavascript() != null && va.getJavascript().length() > 0) {
                actions.add(va);
            } else {
                iterator.remove();
            }
        }

        Collections.sort(actions, actionComparator);

        return actions;
    }

    /**
     * Release any acquired resources.
     */
    public void release() {
        super.release();
        bundle = Globals.MESSAGES_KEY;
        formName = null;
        formNames = null;
        page = 0;
        methodName = null;
        staticJavascript = "true";
        dynamicJavascript = "true";
        htmlComment = "true";
        cdata = "true";
        src = null;
    }

    /**
     * Returns the opening script element and some initial javascript.
     */
    protected String getJavascriptBegin(String methods,String formName) {
        StringBuffer sb = new StringBuffer();
        String name = formName.replace('/', '_'); // remove any '/' characters
        name = name.replace('.','_');
        // if formNames attribute used
        if(name.charAt(0) == '_'){
            name = name.substring(1, 2).toUpperCase()
                + name.substring(2);
        }else{                                      // if formName attribute used
            name = name.substring(0,1).toUpperCase()
                + name.substring(1);
        }
        
        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 {
            //Making Sure that Bitwise operator works:
            sb.append(" var formValidationResult;\n");
            sb.append("       formValidationResult = " + methods + "; \n");
            sb.append("     return (formValidationResult == 1);\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.isXhtml() && "true".equals(htmlComment)){
            sb.append(HTML_END_COMMENT);
        }

        if (this.isXhtml() && "true".equalsIgnoreCase(this.cdata)) {
            sb.append("]]>\r\n");
        }

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

        return sb.toString();
    }

    /**
     * Constructs the beginning &lt;script&gt; element depending on XHTML
     * status.
     * @since Struts 1.2
     */
    protected String renderStartElement() {
        StringBuffer start = new StringBuffer("<script type=\"text/javascript\"");

        // there is no language attribute in XHTML
        if (!this.isXhtml() && this.scriptLanguage) {
            start.append(" language=\"Javascript1.1\"");
        }

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

        start.append("> \n");
        return start.toString();
    }
    
    /**
     *
     */
    protected String renderAfterStartElement(){
        StringBuffer afterStart = new StringBuffer();
        if (this.isXhtml() && "true".equalsIgnoreCase(this.cdata)) {
            afterStart.append("<![CDATA[\r\n");
        }

        if (!this.isXhtml() && "true".equals(htmlComment)) {
            afterStart.append(HTML_BEGIN_COMMENT);
        }
        afterStart.append("\n     var bCancel = false; \n\n");
        return afterStart.toString();
    }
    
    /**
     * Returns true if this is an xhtml page.
     */
    private boolean isXhtml() {
        return RequestUtils.isXhtml(this.pageContext);
    }

    /**
     * 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;
    }

    /**
     * Gets whether or not the &lt;script&gt; element will include the
     * language attribute.
     * @return true if language attribute will be included.
     * @since Struts 1.2
     */
    public boolean getScriptLanguage() {
        return this.scriptLanguage;
    }

    /**
     * Sets whether or not the &lt;script&gt; element will include the
     * language attribute.
     * @since Struts 1.2
     */
    public void setScriptLanguage(boolean scriptLanguage) {
        this.scriptLanguage = scriptLanguage;
    }

}


The following changes needs to be done to the javacript code of the
validator-rules.xml. We pass the method name along with the form to the
javascript function :
====================================================================
            function validateRequired(form,action) {
                var isValid = true;
                var focusField = null;
                var i = 0;
                var fields = new Array();
                oRequired = new action();
                for (x in oRequired) {
                	var field = form[oRequired[x][0]];

The rest of the validator-rules.xml file remains same. Just need to change the
signature of all the javascript functions.


Let me know any suggestions/comments.

Thanks everybody,
-Kalpesh

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org