文本区域的Dojo验证

时间:2011-11-09 21:47:11

标签: validation textarea dojo required

我第一次尝试使用dojo,所以这可能是显而易见的。

我有一个非常简单的表单,其中有一个textarea需要填写。

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js"></script>
<form id='form1' action="" method="" dojoType="dijit.form.Form">
  <label for="dob">desc:</label>
  <textarea class='multilinecontrol' dojoType="dijit.form.Textarea" selected='true' required='true'></textarea>
  <button type='submit' id="next" name="next" dojoType="dijit.form.Button">
    Next</button>
</form>

我添加了'required'属性,因此我可以确保表单在用户可以继续之前有效。

然而,当表单显示时,textarea周围有一个红色的焦点环,其他小部件都不像这样,它真的很烦人。

知道怎么摆脱它?

我可以通过添加某种默认文本来解决它,比如'把东西放在这里'然后我必须做额外的验证工作 - 我现在无法解决该怎么做。

5 个答案:

答案 0 :(得分:4)

不是复制整个现有的类,而是使用mixin:

define(["dojo/_base/declare", "dojo/_base/lang", "dijit/form/SimpleTextarea", "dijit/form/ValidationTextBox"],
function(declare, lang, SimpleTextarea, ValidationTextBox) {

  return declare('dijit.form.ValidationTextArea', [SimpleTextarea, ValidationTextBox], {
    constructor: function(params){
      this.constraints = {};
      this.baseClass += ' dijitValidationTextArea';
    },    
    templateString: "<textarea ${!nameAttrSetting} data-dojo-attach-       point='focusNode,containerNode,textbox' autocomplete='off'></textarea>",
    validator: function(value, constraints) {
      return (new RegExp("^(?:" + this._computeRegexp(constraints) + ")"+(this.required?"":"?")+"$",["m"])).test(value) &&
        (!this.required || !this._isEmpty(value)) &&
        (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
    }
    })
  })

不幸的是,我无法通过红色感叹号和验证输入获得完全相同的行为 - 因为Textarea调整了大小的功能,所以我已经完成了CSS技巧:

.dijitValidationTextAreaError, .dijitValidationTextAreaError.dijitTextBoxHover {
 background-image: url("error.png");
 background-position: right;
 background-repeat: no-repeat;
}

需要将error.png从claro主题复制到css位置。它显示在文本区域内,而不是在文本区域之外,但它是唯一的,非常小的区别。

答案 1 :(得分:0)

dijit.form.Textarea不做任何验证。这是面向同一问题的任何人的自定义ValidationTextArea:

dojo.provide("dijit.form.ValidationTextArea");

dojo.require("dojo.i18n");

dojo.require("dijit.form.TextBox");
dojo.require("dijit.Tooltip");

dojo.requireLocalization("dijit.form", "validate");

/*=====
    dijit.form.ValidationTextBox.__Constraints = function(){
        // locale: String
        //        locale used for validation, picks up value from this widget's lang attribute
        // _flags_: anything
        //        various flags passed to regExpGen function
        this.locale = "";
        this._flags_ = "";
    }
=====*/

dojo.declare(
    "dijit.form.ValidationTextArea",
    dijit.form.TextBox,
    {
        // summary:
        //        Base class for textbox widgets with the ability to validate content of various types and provide user feedback.
        // tags:
        //        protected

        templateString: "<textarea name=${name} ${nameAttrSetting} dojoAttachPoint='focusNode,containerNode,textbox' autocomplete='off'></textarea>",
        baseClass: "dijitTextArea",

        attributeMap: dojo.delegate(dijit.form._FormValueWidget.prototype.attributeMap, {
            rows:"textbox", cols: "textbox"
        }),

        // rows: Number
        //        The number of rows of text.
        rows: "3",

        // rows: Number
        //        The number of characters per line.
        cols: "20",

        // required: Boolean
        //        User is required to enter data into this field.
        required: false,

        // promptMessage: String
        //        If defined, display this hint string immediately on focus to the textbox, if empty.
        //        Think of this like a tooltip that tells the user what to do, not an error message
        //        that tells the user what they've done wrong.
        //
        //        Message disappears when user starts typing.
        promptMessage: "",

        // invalidMessage: String
        //         The message to display if value is invalid.
        invalidMessage: "$_unset_$", // read from the message file if not overridden

        // constraints: dijit.form.ValidationTextBox.__Constraints
        //        user-defined object needed to pass parameters to the validator functions
        constraints: {},

        // regExp: [extension protected] String
        //        regular expression string used to validate the input
        //        Do not specify both regExp and regExpGen
        regExp: "(.|[\r\n])*",

        regExpGen: function(/*dijit.form.ValidationTextBox.__Constraints*/constraints){
            // summary:
            //        Overridable function used to generate regExp when dependent on constraints.
            //        Do not specify both regExp and regExpGen.
            // tags:
            //        extension protected
            return this.regExp; // String
        },

        // state: [readonly] String
        //        Shows current state (ie, validation result) of input (Normal, Warning, or Error)
        state: "",

        // tooltipPosition: String[]
        //        See description of `dijit.Tooltip.defaultPosition` for details on this parameter.
        tooltipPosition: [],

        _setValueAttr: function(){
            // summary:
            //        Hook so attr('value', ...) works.
            this.inherited(arguments);
            this.validate(this._focused);
        },

        validator: function(/*anything*/value, /*dijit.form.ValidationTextBox.__Constraints*/constraints){
            // summary:
            //        Overridable function used to validate the text input against the regular expression.
            // tags:
            //        protected
            return (new RegExp("^(?:" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
                (!this.required || !this._isEmpty(value)) &&
                (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
        },

        _isValidSubset: function(){
            // summary:
            //        Returns true if the value is either already valid or could be made valid by appending characters.
            //        This is used for validation while the user [may be] still typing.
            return this.textbox.value.search(this._partialre) == 0;
        },

        isValid: function(/*Boolean*/ isFocused){
            // summary:
            //        Tests if value is valid.
            //        Can override with your own routine in a subclass.
            // tags:
            //        protected
            return this.validator(this.textbox.value, this.constraints);
        },

        _isEmpty: function(value){
            // summary:
            //        Checks for whitespace
            return /^\s*$/.test(value); // Boolean
        },

        getErrorMessage: function(/*Boolean*/ isFocused){
            // summary:
            //        Return an error message to show if appropriate
            // tags:
            //        protected
            return this.invalidMessage; // String
        },

        getPromptMessage: function(/*Boolean*/ isFocused){
            // summary:
            //        Return a hint message to show when widget is first focused
            // tags:
            //        protected
            return this.promptMessage; // String
        },

        _maskValidSubsetError: true,
        validate: function(/*Boolean*/ isFocused){
            // summary:
            //        Called by oninit, onblur, and onkeypress.
            // description:
            //        Show missing or invalid messages if appropriate, and highlight textbox field.
            // tags:
            //        protected
            var message = "";
            var isValid = this.disabled || this.isValid(isFocused);
            if(isValid){ this._maskValidSubsetError = true; }
            var isValidSubset = !isValid && isFocused && this._isValidSubset();
            var isEmpty = this._isEmpty(this.textbox.value);
            if(isEmpty){ this._maskValidSubsetError = true; }
            this.state = (isValid || (!this._hasBeenBlurred && isEmpty) || isValidSubset) ? "" : "Error";
            if(this.state == "Error"){ this._maskValidSubsetError = false; }
            this._setStateClass();
            dijit.setWaiState(this.focusNode, "invalid", isValid ? "false" : "true");
            if(isFocused){
                if(isEmpty){
                    message = this.getPromptMessage(true);
                }
                if(!message && (this.state == "Error" || (isValidSubset && !this._maskValidSubsetError))){
                    message = this.getErrorMessage(true);
                }
            }
            this.displayMessage(message);
            return isValid;
        },

        // _message: String
        //        Currently displayed message
        _message: "",

        displayMessage: function(/*String*/ message){
            // summary:
            //        Overridable method to display validation errors/hints.
            //        By default uses a tooltip.
            // tags:
            //        extension
            if(this._message == message){ return; }
            this._message = message;
            dijit.hideTooltip(this.domNode);
            if(message){
                dijit.showTooltip(message, this.domNode, this.tooltipPosition);
            }
        },

        _refreshState: function(){
            // Overrides TextBox._refreshState()
            this.validate(this._focused);
            this.inherited(arguments);
        },

        //////////// INITIALIZATION METHODS ///////////////////////////////////////

        constructor: function(){
            this.constraints = {};
        },

        postMixInProperties: function(){
            // Copy value from srcNodeRef, unless user specified a value explicitly (or there is no srcNodeRef)
            if(!this.value && this.srcNodeRef){
                this.value = this.srcNodeRef.value;
            }
            this.inherited(arguments);
            this.constraints.locale = this.lang;
            this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
            if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }
            var p = this.regExpGen(this.constraints);
            this.regExp = p;
            var partialre = "";
            // parse the regexp and produce a new regexp that matches valid subsets
            // if the regexp is .* then there's no use in matching subsets since everything is valid
            if(p != ".*"){ this.regExp.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g,
                function (re){
                    switch(re.charAt(0)){
                        case '{':
                        case '+':
                        case '?':
                        case '*':
                        case '^':
                        case '$':
                        case '|':
                        case '(':
                            partialre += re;
                            break;
                        case ")":
                            partialre += "|$)";
                            break;
                         default:
                            partialre += "(?:"+re+"|$)";
                            break;
                    }
                }
            );}
            try{ // this is needed for now since the above regexp parsing needs more test verification
                "".search(partialre);
            }catch(e){ // should never be here unless the original RE is bad or the parsing is bad
                partialre = this.regExp;
                console.warn('RegExp error in ' + this.declaredClass + ': ' + this.regExp);
            } // should never be here unless the original RE is bad or the parsing is bad
            this._partialre = "^(?:" + partialre + ")$";
        },

        filter: function(/*String*/ value){
            // Override TextBox.filter to deal with newlines... specifically (IIRC) this is for IE which writes newlines
            // as \r\n instead of just \n
            if(value){
                value = value.replace(/\r/g,"");
            }
            return this.inherited(arguments);
        },

        _setDisabledAttr: function(/*Boolean*/ value){
            this.inherited(arguments);    // call FormValueWidget._setDisabledAttr()
            this._refreshState();
        },

        _setRequiredAttr: function(/*Boolean*/ value){
            this.required = value;
            dijit.setWaiState(this.focusNode,"required", value);
            this._refreshState();
        },

        postCreate: function(){
            if(dojo.isIE){ // IE INPUT tag fontFamily has to be set directly using STYLE
                var s = dojo.getComputedStyle(this.focusNode);
                if(s){
                    var ff = s.fontFamily;
                    if(ff){
                        this.focusNode.style.fontFamily = ff;
                    }
                }
            }
            this.inherited(arguments);
            if(dojo.isIE && this.cols){ // attribute selectors is not supported in IE6
                dojo.addClass(this.textbox, "dijitTextAreaCols");
            }
        },

        reset:function(){
            // Overrides dijit.form.TextBox.reset() by also
            // hiding errors about partial matches
            this._maskValidSubsetError = true;
            this.inherited(arguments);
        },

        _onBlur: function(){
            this.displayMessage('');
            this.inherited(arguments);
        },

        _previousValue: "",
        _onInput: function(/*Event?*/ e){
            // Override TextBox._onInput() to enforce maxLength restriction
            if(this.maxLength){
                var maxLength = parseInt(this.maxLength);
                var value = this.textbox.value.replace(/\r/g,'');
                var overflow = value.length - maxLength;
                if(overflow > 0){
                    if(e){ dojo.stopEvent(e); }
                    var textarea = this.textbox;
                    if(textarea.selectionStart){
                        var pos = textarea.selectionStart;
                        var cr = 0;
                        if(dojo.isOpera){
                            cr = (this.textbox.value.substring(0,pos).match(/\r/g) || []).length;
                        }
                        this.textbox.value = value.substring(0,pos-overflow-cr)+value.substring(pos-cr);
                        textarea.setSelectionRange(pos-overflow, pos-overflow);
                    }else if(dojo.doc.selection){ //IE
                        textarea.focus();
                        var range = dojo.doc.selection.createRange();
                        // delete overflow characters
                        range.moveStart("character", -overflow);
                        range.text = '';
                        // show cursor
                        range.select();
                    }
                }
                this._previousValue = this.textbox.value;
            }
            this.inherited(arguments);
        }
    }
);

答案 2 :(得分:0)

这是我的SimpleValidationTextArea。基本上我已经合并了dijit / form / ValidationTextBox和dijit / form / TextArea。这段代码很难看,需要一些改进,但它有效;)

define("dijit/form/SimpleValidationTextArea", [
    "dojo/_base/declare", // declare
    "dojo/_base/kernel", // kernel.deprecated
    "dojo/i18n", // i18n.getLocalization
    "./TextBox",
    "../Tooltip",
    "dojo/text!./templates/ValidationTextBox.html",
    "dojo/dom-class", // domClass.add
    "dojo/sniff", // has("ie") has("opera")
    "dojo/i18n!./nls/validate"
], function(declare, kernel, i18n, TextBox, Tooltip, template, domClass, has){

//To use this widget you need to add this line to your css file
//errorBorder{ border-color: #D46464; }

var SimpleValidationTextArea;
return SimpleValidationTextArea = declare("dijit.form.SimpleValidationTextArea", TextBox, {
    /* from SimpleTextarea */

    // summary:
    //      A simple textarea that degrades, and responds to
    //      minimal LayoutContainer usage, and works with dijit/form/Form.
    //      Doesn't automatically size according to input, like Textarea.
    //
    // example:
    //  |   <textarea data-dojo-type="dijit/form/SimpleTextarea" name="foo" value="bar" rows=30 cols=40></textarea>
    //
    // example:
    //  |   new SimpleTextarea({ rows:20, cols:30 }, "foo");

    baseClass: "dijitValidationTextBox dijitTextArea",

    // rows: Number
    //      The number of rows of text.
    rows: "3",

    // rows: Number
    //      The number of characters per line.
    cols: "20",

    templateString: "<textarea ${!nameAttrSetting} data-dojo-attach-point='focusNode,containerNode,textbox' autocomplete='off'></textarea>",

    buildRendering: function(){
        this.inherited(arguments);
        if(has("ie") && this.cols){ // attribute selectors is not supported in IE6
            domClass.add(this.textbox, "dijitTextAreaCols");
        }
    },

    filter: function(/*String*/ value){
        // Override TextBox.filter to deal with newlines... specifically (IIRC) this is for IE which writes newlines
        // as \r\n instead of just \n
        if(value){
            value = value.replace(/\r/g,"");
        }
        return this.inherited(arguments);
    },

    _onInput: function(/*Event?*/ e){
        // Override TextBox._onInput() to enforce maxLength restriction
        if(this.maxLength){
            var maxLength = parseInt(this.maxLength);
            var value = this.textbox.value.replace(/\r/g,'');
            var overflow = value.length - maxLength;
            if(overflow > 0){
                var textarea = this.textbox;
                if(textarea.selectionStart){
                    var pos = textarea.selectionStart;
                    var cr = 0;
                    if(has("opera")){
                        cr = (this.textbox.value.substring(0,pos).match(/\r/g) || []).length;
                    }
                    this.textbox.value = value.substring(0,pos-overflow-cr)+value.substring(pos-cr);
                    textarea.setSelectionRange(pos-overflow, pos-overflow);
                }else if(this.ownerDocument.selection){ //IE
                    textarea.focus();
                    var range = this.ownerDocument.selection.createRange();
                    // delete overflow characters
                    range.moveStart("character", -overflow);
                    range.text = '';
                    // show cursor
                    range.select();
                }
            }
        }
        this.inherited(arguments);
    },

    /* -from SimpleTextarea */

    // summary:
    //      Base class for textbox widgets with the ability to validate content of various types and provide user feedback.

    // required: Boolean
    //      User is required to enter data into this field.
    required: false,

    // promptMessage: String
    //      If defined, display this hint string immediately on focus to the textbox, if empty.
    //      Also displays if the textbox value is Incomplete (not yet valid but will be with additional input).
    //      Think of this like a tooltip that tells the user what to do, not an error message
    //      that tells the user what they've done wrong.
    //
    //      Message disappears when user starts typing.
    promptMessage: "",

    // invalidMessage: String
    //      The message to display if value is invalid.
    //      The translated string value is read from the message file by default.
    //      Set to "" to use the promptMessage instead.
    invalidMessage: "$_unset_$",

    // missingMessage: String
    //      The message to display if value is empty and the field is required.
    //      The translated string value is read from the message file by default.
    //      Set to "" to use the invalidMessage instead.
    missingMessage: "$_unset_$",

    // message: String
    //      Currently error/prompt message.
    //      When using the default tooltip implementation, this will only be
    //      displayed when the field is focused.
    message: "",

    // constraints: __Constraints
    //      user-defined object needed to pass parameters to the validator functions
    constraints: {},

    // pattern: [extension protected] String|Function(constraints) returning a string.
    //      This defines the regular expression used to validate the input.
    //      Do not add leading ^ or $ characters since the widget adds these.
    //      A function may be used to generate a valid pattern when dependent on constraints or other runtime factors.
    //      set('pattern', String|Function).
    pattern: ".*",

    // regExp: Deprecated [extension protected] String.  Use "pattern" instead.
    regExp: "",

    regExpGen: function(/*__Constraints*/ /*===== constraints =====*/){
        // summary:
        //      Deprecated.  Use set('pattern', Function) instead.
    },

    // state: [readonly] String
    //      Shows current state (ie, validation result) of input (""=Normal, Incomplete, or Error)
    state: "",

    // tooltipPosition: String[]
    //      See description of `dijit/Tooltip.defaultPosition` for details on this parameter.
    tooltipPosition: [],

    _deprecateRegExp: function(attr, value){
        if(value != SimpleValidationTextArea.prototype[attr]){
            kernel.deprecated("SimpleValidationTextArea id="+this.id+", set('" + attr + "', ...) is deprecated.  Use set('pattern', ...) instead.", "", "2.0");
            this.set('pattern', value);
        }
    },
    _setRegExpGenAttr: function(/*Function*/ newFcn){
        this._deprecateRegExp("regExpGen", newFcn);
        this.regExpGen = this._getPatternAttr; // backward compat with this.regExpGen(this.constraints)
    },
    _setRegExpAttr: function(/*String*/ value){
        this._deprecateRegExp("regExp", value);
    },

    _setValueAttr: function(){
        // summary:
        //      Hook so set('value', ...) works.
        this.inherited(arguments);
        this.validate(this.focused);
    },

    validator: function(/*anything*/ value, /*__Constraints*/ constraints){
        // summary:
        //      Overridable function used to validate the text input against the regular expression.
        // tags:
        //      protected
        return (new RegExp("^(?:" + this._getPatternAttr(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
            (!this.required || !this._isEmpty(value)) &&
            (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
    },

    _isValidSubset: function(){
        // summary:
        //      Returns true if the value is either already valid or could be made valid by appending characters.
        //      This is used for validation while the user [may be] still typing.
        return this.textbox.value.search(this._partialre) == 0;
    },

    isValid: function(/*Boolean*/ /*===== isFocused =====*/){
        // summary:
        //      Tests if value is valid.
        //      Can override with your own routine in a subclass.
        // tags:
        //      protected
        return this.validator(this.textbox.value, this.constraints);
    },

    _isEmpty: function(value){
        // summary:
        //      Checks for whitespace
        return (this.trim ? /^\s*$/ : /^$/).test(value); // Boolean
    },

    getErrorMessage: function(/*Boolean*/ /*===== isFocused =====*/){
        // summary:
        //      Return an error message to show if appropriate
        // tags:
        //      protected
        var invalid = this.invalidMessage == "$_unset_$" ? this.messages.invalidMessage :
            !this.invalidMessage ? this.promptMessage : this.invalidMessage;
        var missing = this.missingMessage == "$_unset_$" ? this.messages.missingMessage :
            !this.missingMessage ? invalid : this.missingMessage;
        return (this.required && this._isEmpty(this.textbox.value)) ? missing : invalid; // String
    },

    getPromptMessage: function(/*Boolean*/ /*===== isFocused =====*/){
        // summary:
        //      Return a hint message to show when widget is first focused
        // tags:
        //      protected
        return this.promptMessage; // String
    },

    _maskValidSubsetError: true,
    validate: function(/*Boolean*/ isFocused){
        // summary:
        //      Called by oninit, onblur, and onkeypress.
        // description:
        //      Show missing or invalid messages if appropriate, and highlight textbox field.
        // tags:
        //      protected
        var message = "";
        var isValid = this.disabled || this.isValid(isFocused);
        if(isValid){ this._maskValidSubsetError = true; }
        var isEmpty = this._isEmpty(this.textbox.value);
        var isValidSubset = !isValid && isFocused && this._isValidSubset();
        this._set("state", isValid ? "" : (((((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && (this._maskValidSubsetError || (isValidSubset && !this._hasBeenBlurred && isFocused))) ? "Incomplete" : "Error"));
        this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true");

        if(this.state == "Error"){
            this._maskValidSubsetError = isFocused && isValidSubset; // we want the error to show up after a blur and refocus
            message = this.getErrorMessage(isFocused);
            domClass.add(this.domNode, "errorBorder");
        }else if(this.state == "Incomplete"){
            message = this.getPromptMessage(isFocused); // show the prompt whenever the value is not yet complete
            this._maskValidSubsetError = !this._hasBeenBlurred || isFocused; // no Incomplete warnings while focused
        }else if(isEmpty){
            message = this.getPromptMessage(isFocused); // show the prompt whenever there's no error and no text
        }else if(this.state == ''){ //everything is fine
            domClass.remove(this.domNode, "errorBorder");
        }
        this.set("message", message);

        return isValid;
    },

    displayMessage: function(/*String*/ message){
        // summary:
        //      Overridable method to display validation errors/hints.
        //      By default uses a tooltip.
        // tags:
        //      extension
        if(message && this.focused){
            Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
        }else{
            Tooltip.hide(this.domNode);
        }
    },

    _refreshState: function(){
        // Overrides TextBox._refreshState()
        if(this._created){
            this.validate(this.focused);
        }
        this.inherited(arguments);
    },

    //////////// INITIALIZATION METHODS ///////////////////////////////////////

    constructor: function(params /*===== , srcNodeRef =====*/){
        // summary:
        //      Create the widget.
        // params: Object|null
        //      Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
        //      and functions, typically callbacks like onClick.
        //      The hash can contain any of the widget's properties, excluding read-only properties.
        // srcNodeRef: DOMNode|String?
        //      If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree.

        this.constraints = {};
        this.baseClass += ' dijitSimpleValidationTextArea';
    },

    startup: function(){
        this.inherited(arguments);
        this._refreshState(); // after all _set* methods have run
    },

    _setConstraintsAttr: function(/*__Constraints*/ constraints){
        if(!constraints.locale && this.lang){
            constraints.locale = this.lang;
        }
        this._set("constraints", constraints);
        this._refreshState();
    },

    _setPatternAttr: function(/*String|Function*/ pattern){
        this._set("pattern", pattern); // don't set on INPUT to avoid native HTML5 validation
    },

    _getPatternAttr: function(/*__Constraints*/ constraints){
        // summary:
        //      Hook to get the current regExp and to compute the partial validation RE.
        var p = this.pattern;
        var type = (typeof p).toLowerCase();
        if(type == "function"){
            p = this.pattern(constraints || this.constraints);
        }
        if(p != this._lastRegExp){
            var partialre = "";
            this._lastRegExp = p;
            // parse the regexp and produce a new regexp that matches valid subsets
            // if the regexp is .* then there's no use in matching subsets since everything is valid
            if(p != ".*"){
                p.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g,
                function(re){
                    switch(re.charAt(0)){
                        case '{':
                        case '+':
                        case '?':
                        case '*':
                        case '^':
                        case '$':
                        case '|':
                        case '(':
                            partialre += re;
                            break;
                        case ")":
                            partialre += "|$)";
                            break;
                         default:
                            partialre += "(?:"+re+"|$)";
                            break;
                    }
                });
            }
            try{ // this is needed for now since the above regexp parsing needs more test verification
                "".search(partialre);
            }catch(e){ // should never be here unless the original RE is bad or the parsing is bad
                partialre = this.pattern;
                console.warn('RegExp error in ' + this.declaredClass + ': ' + this.pattern);
            } // should never be here unless the original RE is bad or the parsing is bad
            this._partialre = "^(?:" + partialre + ")$";
        }
        return p;
    },

    postMixInProperties: function(){
        if(!this.value && this.srcNodeRef){
            this.value = this.srcNodeRef.value;
        }
        this.inherited(arguments);
        this.messages = i18n.getLocalization("dijit.form", "validate", this.lang);
        this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls attachPoints
    },

    _setDisabledAttr: function(/*Boolean*/ value){
        this.inherited(arguments);  // call FormValueWidget._setDisabledAttr()
        this._refreshState();
    },

    _setRequiredAttr: function(/*Boolean*/ value){
        this._set("required", value);
        this.focusNode.setAttribute("aria-required", value);
        this._refreshState();
    },

    _setMessageAttr: function(/*String*/ message){
        this._set("message", message);
        this.displayMessage(message);
    },

    reset:function(){
        // Overrides dijit/form/TextBox.reset() by also
        // hiding errors about partial matches
        this._maskValidSubsetError = true;
        this.inherited(arguments);
    },

    _onBlur: function(){
        // the message still exists but for back-compat, and to erase the tooltip
        // (if the message is being displayed as a tooltip), call displayMessage('')
        this.displayMessage('');

        this.inherited(arguments);
    }
});
});

答案 3 :(得分:0)

我的方法与前两个答案略有不同,但希望更简洁,因为它不涉及编写任何验证码。

开箱即用的dijit / form / SimpleTextarea通过用&lt; textarea&gt;

替换控件来扩展TextBox

我的解决方案是通过扩展ValidationTextBox来定义新的文本区域Dijit。

也就是说,从SimpleTextarea获取源代码(90行及其大部分注释)并将TextBox替换为ValidationTextBox。同样覆盖默认的正则表达式模式(。*)以允许换行符号。

基于SimpleTextarea.js.uncompressed.js

define("custom/ValidationTextarea", [
"dojo/_base/declare", // declare
"dojo/dom-class", // domClass.add
"dojo/sniff", // has("ie") has("opera")
"dijit/form/ValidationTextBox"
], function(declare, domClass, has, ValidationTextBox){

return declare("custom/ValidationTextarea", ValidationTextBox, {        

    baseClass: "dijitValidationTextBox dijitTextBox dijitTextArea",

...
    pattern: "[\\S\\s]+", /* Match not-whitepsace or whitespace. Default pattern for ValidationTextBox is .* which does not match new line characters */

... remaining lines

答案 4 :(得分:0)

根据您的问题,我猜您使用的是dojo 1.6

这是我的ValidationTextarea。它使用SimpleTextArea来支持&#39; row&#39;和&#39; cols&#39;和ValidationTextBox用于验证。

这个想法与另一个答案类似,只是在这种情况下,我没有为小部件定义templateString

dojo.provide('mynamespace.ValidationTextarea');
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.form.SimpleTextarea");

//ValidationTextarea: Validation class that hide the displayMessage and 
//implement the validate method used by forms
dojo.declare("mynamespace.ValidationTextarea",[dijit.form.ValidationTextBox,dijit.form.SimpleTextarea], {

//int
// The maximum number of characters
maxLength: 255,

validate: function() {
if (arguments.length==0)
        return this.validate(false);

    return this.inherited(arguments);
},            

onFocus: function() {
    if (!this.isValid()) {
        this.displayMessage(this.getErrorMessage());
    }
},

onBlur: function() {
    this.validate(false);
},

filter: function(/*String*/ value){
    // Override TextBox.filter to deal with newlines... specifically (IIRC) this is for IE which writes newlines
    // as \r\n instead of just \n
    if(value){
        value = value.replace(/\r/g,"");
    }
    return this.inherited(arguments);
},

displayMessage: function(/*String*/ message) { 

}

});