Dojo валидиране на текстово поле

Опитвам се да използвам доджо за първи път, така че това може да е очевидно.

Имам много прост формуляр с едно текстово поле в него, което трябва да се попълни.

<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>

Добавих свойството „задължително“, така че мога да се уверя, че формулярът е валиден, преди потребителят да може да продължи.

Въпреки това, когато формулярът е показан, текстовото поле има червен пръстен за фокусиране около него, нито една от другите джаджи не се държи така и това е наистина досадно.

Някаква идея как да се отърва от него?

Бих могъл да го хакна, като сложа някакъв текст по подразбиране като „Поставете неща тук“, но тогава трябва да направя допълнителна работа по валидиране - което в момента не мога да разбера как да направя.


person push 22    schedule 09.11.2011    source източник


Отговори (5)


Вместо да копирате всички съществуващи класове, достатъчно е да използвате 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 местоположение. Показва се вътре в текстовата област, а не извън нея, но това е единствената, съвсем малка разлика.

person Danubian Sailor    schedule 21.10.2013
comment
Намерихте ли начин да получите типичното поведение при грешка (червен текст под текстовата област) вместо подсказката при задържане? - person noobsharp; 07.02.2017

Ето моето 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);
    }
});
});
person malan    schedule 18.04.2013

Моят подход е малко по-различен от предишните два отговора, но се надяваме, че е по-сбит, тъй като не включва писане на код за валидиране.

Извън кутията dijit/form/SimpleTextarea разширява TextBox чрез замяна на контролата с ‹textarea›

Моето решение просто дефинира нова текстова област Dijit чрез разширяване на ValidationTextBox.

Тоест вземете източника от 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
person techscreen    schedule 27.07.2013

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);
        }
    }
);
person rptmat57    schedule 23.10.2012

Въз основа на вашия въпрос, предполагам, че използвате dojo 1.6

Това е моят ValidationTextarea. Той използва SimpleTextArea за поддръжка на 'row' и 'cols' и 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) { 

}

}); 
person German Attanasio    schedule 29.05.2014