2150 |
mathias |
1 |
if(!dojo._hasResource["dijit.form.ValidationTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dijit.form.ValidationTextBox"] = true;
|
|
|
3 |
dojo.provide("dijit.form.ValidationTextBox");
|
|
|
4 |
|
|
|
5 |
dojo.require("dojo.i18n");
|
|
|
6 |
|
|
|
7 |
dojo.require("dijit.form.TextBox");
|
|
|
8 |
dojo.require("dijit.Tooltip");
|
|
|
9 |
|
|
|
10 |
dojo.requireLocalization("dijit.form", "validate", null, "ko,zh-cn,zh,ja,zh-tw,ru,it,hu,ROOT,fr,pt,pl,es,de,cs");
|
|
|
11 |
|
|
|
12 |
dojo.declare(
|
|
|
13 |
"dijit.form.ValidationTextBox",
|
|
|
14 |
dijit.form.TextBox,
|
|
|
15 |
{
|
|
|
16 |
// summary:
|
|
|
17 |
// A subclass of TextBox.
|
|
|
18 |
// Over-ride isValid in subclasses to perform specific kinds of validation.
|
|
|
19 |
|
|
|
20 |
templateString:"<table style=\"display: -moz-inline-stack;\" class=\"dijit dijitReset dijitInlineTable\" cellspacing=\"0\" cellpadding=\"0\"\n\tid=\"widget_${id}\" name=\"${name}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse\" waiRole=\"presentation\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitInputField\" width=\"100%\"\n\t\t\t><input dojoAttachPoint='textbox,focusNode' dojoAttachEvent='onfocus,onblur:_onMouse,onkeyup,onkeypress:_onKeyPress' autocomplete=\"off\"\n\t\t\ttype='${type}' name='${name}'\n\t\t/></td\n\t\t><td class=\"dijitReset dijitValidationIconField\" width=\"0%\"\n\t\t\t><div dojoAttachPoint='iconNode' class='dijitValidationIcon'></div><div class='dijitValidationIconText'>Χ</div\n\t\t></td\n\t></tr\n></table>\n",
|
|
|
21 |
baseClass: "dijitTextBox",
|
|
|
22 |
|
|
|
23 |
// default values for new subclass properties
|
|
|
24 |
// required: Boolean
|
|
|
25 |
// Can be true or false, default is false.
|
|
|
26 |
required: false,
|
|
|
27 |
// promptMessage: String
|
|
|
28 |
// Hint string
|
|
|
29 |
promptMessage: "",
|
|
|
30 |
// invalidMessage: String
|
|
|
31 |
// The message to display if value is invalid.
|
|
|
32 |
invalidMessage: "$_unset_$", // read from the message file if not overridden
|
|
|
33 |
// constraints: Object
|
|
|
34 |
// user-defined object needed to pass parameters to the validator functions
|
|
|
35 |
constraints: {},
|
|
|
36 |
// regExp: String
|
|
|
37 |
// regular expression string used to validate the input
|
|
|
38 |
// Do not specify both regExp and regExpGen
|
|
|
39 |
regExp: ".*",
|
|
|
40 |
// regExpGen: Function
|
|
|
41 |
// user replaceable function used to generate regExp when dependent on constraints
|
|
|
42 |
// Do not specify both regExp and regExpGen
|
|
|
43 |
regExpGen: function(constraints){ return this.regExp; },
|
|
|
44 |
|
|
|
45 |
// state: String
|
|
|
46 |
// Shows current state (ie, validation result) of input (Normal, Warning, or Error)
|
|
|
47 |
state: "",
|
|
|
48 |
|
|
|
49 |
setValue: function(){
|
|
|
50 |
this.inherited('setValue', arguments);
|
|
|
51 |
this.validate(false);
|
|
|
52 |
},
|
|
|
53 |
|
|
|
54 |
validator: function(value,constraints){
|
|
|
55 |
// summary: user replaceable function used to validate the text input against the regular expression.
|
|
|
56 |
return (new RegExp("^(" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
|
|
|
57 |
(!this.required || !this._isEmpty(value)) &&
|
|
|
58 |
(this._isEmpty(value) || this.parse(value, constraints) !== null);
|
|
|
59 |
},
|
|
|
60 |
|
|
|
61 |
isValid: function(/* Boolean*/ isFocused){
|
|
|
62 |
// summary: Need to over-ride with your own validation code in subclasses
|
|
|
63 |
return this.validator(this.textbox.value, this.constraints);
|
|
|
64 |
},
|
|
|
65 |
|
|
|
66 |
_isEmpty: function(value){
|
|
|
67 |
// summary: Checks for whitespace
|
|
|
68 |
return /^\s*$/.test(value); // Boolean
|
|
|
69 |
},
|
|
|
70 |
|
|
|
71 |
getErrorMessage: function(/* Boolean*/ isFocused){
|
|
|
72 |
// summary: return an error message to show if appropriate
|
|
|
73 |
return this.invalidMessage;
|
|
|
74 |
},
|
|
|
75 |
|
|
|
76 |
getPromptMessage: function(/* Boolean*/ isFocused){
|
|
|
77 |
// summary: return a hint to show if appropriate
|
|
|
78 |
return this.promptMessage;
|
|
|
79 |
},
|
|
|
80 |
|
|
|
81 |
validate: function(/* Boolean*/ isFocused){
|
|
|
82 |
// summary:
|
|
|
83 |
// Called by oninit, onblur, and onkeypress.
|
|
|
84 |
// description:
|
|
|
85 |
// Show missing or invalid messages if appropriate, and highlight textbox field.
|
|
|
86 |
var message = "";
|
|
|
87 |
var isValid = this.isValid(isFocused);
|
|
|
88 |
var isEmpty = this._isEmpty(this.textbox.value);
|
|
|
89 |
this.state = (isValid || (!this._hasBeenBlurred && isEmpty)) ? "" : "Error";
|
|
|
90 |
this._setStateClass();
|
|
|
91 |
dijit.setWaiState(this.focusNode, "invalid", (isValid? "false" : "true"));
|
|
|
92 |
if(isFocused){
|
|
|
93 |
if(isEmpty){
|
|
|
94 |
message = this.getPromptMessage(true);
|
|
|
95 |
}
|
|
|
96 |
if(!message && !isValid){
|
|
|
97 |
message = this.getErrorMessage(true);
|
|
|
98 |
}
|
|
|
99 |
}
|
|
|
100 |
this._displayMessage(message);
|
|
|
101 |
},
|
|
|
102 |
|
|
|
103 |
// currently displayed message
|
|
|
104 |
_message: "",
|
|
|
105 |
|
|
|
106 |
_displayMessage: function(/*String*/ message){
|
|
|
107 |
if(this._message == message){ return; }
|
|
|
108 |
this._message = message;
|
|
|
109 |
this.displayMessage(message);
|
|
|
110 |
},
|
|
|
111 |
|
|
|
112 |
displayMessage: function(/*String*/ message){
|
|
|
113 |
// summary:
|
|
|
114 |
// User overridable method to display validation errors/hints.
|
|
|
115 |
// By default uses a tooltip.
|
|
|
116 |
if(message){
|
|
|
117 |
dijit.showTooltip(message, this.domNode);
|
|
|
118 |
}else{
|
|
|
119 |
dijit.hideTooltip(this.domNode);
|
|
|
120 |
}
|
|
|
121 |
},
|
|
|
122 |
|
|
|
123 |
_hasBeenBlurred: false,
|
|
|
124 |
|
|
|
125 |
_onBlur: function(evt){
|
|
|
126 |
this._hasBeenBlurred = true;
|
|
|
127 |
this.validate(false);
|
|
|
128 |
this.inherited('_onBlur', arguments);
|
|
|
129 |
},
|
|
|
130 |
|
|
|
131 |
onfocus: function(evt){
|
|
|
132 |
// TODO: change to _onFocus?
|
|
|
133 |
this.validate(true);
|
|
|
134 |
this._onMouse(evt); // update CSS classes
|
|
|
135 |
},
|
|
|
136 |
|
|
|
137 |
onkeyup: function(evt){
|
|
|
138 |
this.onfocus(evt);
|
|
|
139 |
},
|
|
|
140 |
|
|
|
141 |
//////////// INITIALIZATION METHODS ///////////////////////////////////////
|
|
|
142 |
constructor: function(){
|
|
|
143 |
this.constraints = {};
|
|
|
144 |
},
|
|
|
145 |
|
|
|
146 |
postMixInProperties: function(){
|
|
|
147 |
this.inherited('postMixInProperties', arguments);
|
|
|
148 |
this.constraints.locale=this.lang;
|
|
|
149 |
this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
|
|
|
150 |
if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }
|
|
|
151 |
var p = this.regExpGen(this.constraints);
|
|
|
152 |
this.regExp = p;
|
|
|
153 |
// make value a string for all types so that form reset works well
|
|
|
154 |
}
|
|
|
155 |
}
|
|
|
156 |
);
|
|
|
157 |
|
|
|
158 |
dojo.declare(
|
|
|
159 |
"dijit.form.MappedTextBox",
|
|
|
160 |
dijit.form.ValidationTextBox,
|
|
|
161 |
{
|
|
|
162 |
// summary:
|
|
|
163 |
// A subclass of ValidationTextBox.
|
|
|
164 |
// Provides a hidden input field and a serialize method to override
|
|
|
165 |
|
|
|
166 |
serialize: function(val, /*Object?*/options){
|
|
|
167 |
// summary: user replaceable function used to convert the getValue() result to a String
|
|
|
168 |
return (val.toString ? val.toString() : "");
|
|
|
169 |
},
|
|
|
170 |
|
|
|
171 |
toString: function(){
|
|
|
172 |
// summary: display the widget as a printable string using the widget's value
|
|
|
173 |
var val = this.filter(this.getValue());
|
|
|
174 |
return (val!=null) ? ((typeof val == "string") ? val : this.serialize(val, this.constraints)) : "";
|
|
|
175 |
},
|
|
|
176 |
|
|
|
177 |
validate: function(){
|
|
|
178 |
this.valueNode.value = this.toString();
|
|
|
179 |
this.inherited('validate', arguments);
|
|
|
180 |
},
|
|
|
181 |
|
|
|
182 |
postCreate: function(){
|
|
|
183 |
var textbox = this.textbox;
|
|
|
184 |
var valueNode = (this.valueNode = document.createElement("input"));
|
|
|
185 |
valueNode.setAttribute("type", textbox.type);
|
|
|
186 |
valueNode.setAttribute("value", this.toString());
|
|
|
187 |
dojo.style(valueNode, "display", "none");
|
|
|
188 |
valueNode.name = this.textbox.name;
|
|
|
189 |
this.textbox.name = "_" + this.textbox.name + "_displayed_";
|
|
|
190 |
this.textbox.removeAttribute("name");
|
|
|
191 |
dojo.place(valueNode, textbox, "after");
|
|
|
192 |
|
|
|
193 |
this.inherited('postCreate', arguments);
|
|
|
194 |
}
|
|
|
195 |
}
|
|
|
196 |
);
|
|
|
197 |
|
|
|
198 |
dojo.declare(
|
|
|
199 |
"dijit.form.RangeBoundTextBox",
|
|
|
200 |
dijit.form.MappedTextBox,
|
|
|
201 |
{
|
|
|
202 |
// summary:
|
|
|
203 |
// A subclass of MappedTextBox.
|
|
|
204 |
// Tests for a value out-of-range
|
|
|
205 |
/*===== contraints object:
|
|
|
206 |
// min: Number
|
|
|
207 |
// Minimum signed value. Default is -Infinity
|
|
|
208 |
min: undefined,
|
|
|
209 |
// max: Number
|
|
|
210 |
// Maximum signed value. Default is +Infinity
|
|
|
211 |
max: undefined,
|
|
|
212 |
=====*/
|
|
|
213 |
|
|
|
214 |
// rangeMessage: String
|
|
|
215 |
// The message to display if value is out-of-range
|
|
|
216 |
rangeMessage: "",
|
|
|
217 |
|
|
|
218 |
compare: function(val1, val2){
|
|
|
219 |
// summary: compare 2 values
|
|
|
220 |
return val1 - val2;
|
|
|
221 |
},
|
|
|
222 |
|
|
|
223 |
rangeCheck: function(/* Number */ primitive, /* Object */ constraints){
|
|
|
224 |
// summary: user replaceable function used to validate the range of the numeric input value
|
|
|
225 |
var isMin = (typeof constraints.min != "undefined");
|
|
|
226 |
var isMax = (typeof constraints.max != "undefined");
|
|
|
227 |
if(isMin || isMax){
|
|
|
228 |
return (!isMin || this.compare(primitive,constraints.min) >= 0) &&
|
|
|
229 |
(!isMax || this.compare(primitive,constraints.max) <= 0);
|
|
|
230 |
}else{ return true; }
|
|
|
231 |
},
|
|
|
232 |
|
|
|
233 |
isInRange: function(/* Boolean*/ isFocused){
|
|
|
234 |
// summary: Need to over-ride with your own validation code in subclasses
|
|
|
235 |
return this.rangeCheck(this.getValue(), this.constraints);
|
|
|
236 |
},
|
|
|
237 |
|
|
|
238 |
isValid: function(/* Boolean*/ isFocused){
|
|
|
239 |
return this.inherited('isValid', arguments) &&
|
|
|
240 |
((this._isEmpty(this.textbox.value) && !this.required) || this.isInRange(isFocused));
|
|
|
241 |
},
|
|
|
242 |
|
|
|
243 |
getErrorMessage: function(/* Boolean*/ isFocused){
|
|
|
244 |
if(dijit.form.RangeBoundTextBox.superclass.isValid.call(this, false) && !this.isInRange(isFocused)){ return this.rangeMessage; }
|
|
|
245 |
else{ return this.inherited('getErrorMessage', arguments); }
|
|
|
246 |
},
|
|
|
247 |
|
|
|
248 |
postMixInProperties: function(){
|
|
|
249 |
this.inherited('postMixInProperties', arguments);
|
|
|
250 |
if(!this.rangeMessage){
|
|
|
251 |
this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
|
|
|
252 |
this.rangeMessage = this.messages.rangeMessage;
|
|
|
253 |
}
|
|
|
254 |
},
|
|
|
255 |
|
|
|
256 |
postCreate: function(){
|
|
|
257 |
this.inherited('postCreate', arguments);
|
|
|
258 |
if(typeof this.constraints.min != "undefined"){
|
|
|
259 |
dijit.setWaiState(this.focusNode, "valuemin", this.constraints.min);
|
|
|
260 |
}
|
|
|
261 |
if(typeof this.constraints.max != "undefined"){
|
|
|
262 |
dijit.setWaiState(this.focusNode, "valuemax", this.constraints.max);
|
|
|
263 |
}
|
|
|
264 |
}
|
|
|
265 |
}
|
|
|
266 |
);
|
|
|
267 |
|
|
|
268 |
}
|