]> git.wh0rd.org - tt-rss.git/blob - lib/dijit/form/ValidationTextBox.js.uncompressed.js
modify dojo rebuild script to remove uncompressed files
[tt-rss.git] / lib / dijit / form / ValidationTextBox.js.uncompressed.js
1 require({cache:{
2 'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\" role=\"presentation\"\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"&#935; \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"}});
3 define("dijit/form/ValidationTextBox", [
4 "dojo/_base/declare", // declare
5 "dojo/_base/kernel", // kernel.deprecated
6 "dojo/i18n", // i18n.getLocalization
7 "./TextBox",
8 "../Tooltip",
9 "dojo/text!./templates/ValidationTextBox.html",
10 "dojo/i18n!./nls/validate"
11 ], function(declare, kernel, i18n, TextBox, Tooltip, template){
12
13 // module:
14 // dijit/form/ValidationTextBox
15
16
17 /*=====
18 var __Constraints = {
19 // locale: String
20 // locale used for validation, picks up value from this widget's lang attribute
21 // _flags_: anything
22 // various flags passed to pattern function
23 };
24 =====*/
25
26 var ValidationTextBox;
27 return ValidationTextBox = declare("dijit.form.ValidationTextBox", TextBox, {
28 // summary:
29 // Base class for textbox widgets with the ability to validate content of various types and provide user feedback.
30
31 templateString: template,
32
33 // required: Boolean
34 // User is required to enter data into this field.
35 required: false,
36
37 // promptMessage: String
38 // If defined, display this hint string immediately on focus to the textbox, if empty.
39 // Also displays if the textbox value is Incomplete (not yet valid but will be with additional input).
40 // Think of this like a tooltip that tells the user what to do, not an error message
41 // that tells the user what they've done wrong.
42 //
43 // Message disappears when user starts typing.
44 promptMessage: "",
45
46 // invalidMessage: String
47 // The message to display if value is invalid.
48 // The translated string value is read from the message file by default.
49 // Set to "" to use the promptMessage instead.
50 invalidMessage: "$_unset_$",
51
52 // missingMessage: String
53 // The message to display if value is empty and the field is required.
54 // The translated string value is read from the message file by default.
55 // Set to "" to use the invalidMessage instead.
56 missingMessage: "$_unset_$",
57
58 // message: String
59 // Currently error/prompt message.
60 // When using the default tooltip implementation, this will only be
61 // displayed when the field is focused.
62 message: "",
63
64 // constraints: __Constraints
65 // user-defined object needed to pass parameters to the validator functions
66 constraints: {},
67
68 // pattern: [extension protected] String|Function(constraints) returning a string.
69 // This defines the regular expression used to validate the input.
70 // Do not add leading ^ or $ characters since the widget adds these.
71 // A function may be used to generate a valid pattern when dependent on constraints or other runtime factors.
72 // set('pattern', String|Function).
73 pattern: ".*",
74
75 // regExp: Deprecated [extension protected] String. Use "pattern" instead.
76 regExp: "",
77
78 regExpGen: function(/*__Constraints*/ /*===== constraints =====*/){
79 // summary:
80 // Deprecated. Use set('pattern', Function) instead.
81 },
82
83 // state: [readonly] String
84 // Shows current state (ie, validation result) of input (""=Normal, Incomplete, or Error)
85 state: "",
86
87 // tooltipPosition: String[]
88 // See description of `dijit/Tooltip.defaultPosition` for details on this parameter.
89 tooltipPosition: [],
90
91 _deprecateRegExp: function(attr, value){
92 if(value != ValidationTextBox.prototype[attr]){
93 kernel.deprecated("ValidationTextBox id="+this.id+", set('" + attr + "', ...) is deprecated. Use set('pattern', ...) instead.", "", "2.0");
94 this.set('pattern', value);
95 }
96 },
97 _setRegExpGenAttr: function(/*Function*/ newFcn){
98 this._deprecateRegExp("regExpGen", newFcn);
99 this.regExpGen = this._getPatternAttr; // backward compat with this.regExpGen(this.constraints)
100 },
101 _setRegExpAttr: function(/*String*/ value){
102 this._deprecateRegExp("regExp", value);
103 },
104
105 _setValueAttr: function(){
106 // summary:
107 // Hook so set('value', ...) works.
108 this.inherited(arguments);
109 this.validate(this.focused);
110 },
111
112 validator: function(/*anything*/ value, /*__Constraints*/ constraints){
113 // summary:
114 // Overridable function used to validate the text input against the regular expression.
115 // tags:
116 // protected
117 return (new RegExp("^(?:" + this._getPatternAttr(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
118 (!this.required || !this._isEmpty(value)) &&
119 (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
120 },
121
122 _isValidSubset: function(){
123 // summary:
124 // Returns true if the value is either already valid or could be made valid by appending characters.
125 // This is used for validation while the user [may be] still typing.
126 return this.textbox.value.search(this._partialre) == 0;
127 },
128
129 isValid: function(/*Boolean*/ /*===== isFocused =====*/){
130 // summary:
131 // Tests if value is valid.
132 // Can override with your own routine in a subclass.
133 // tags:
134 // protected
135 return this.validator(this.textbox.value, this.constraints);
136 },
137
138 _isEmpty: function(value){
139 // summary:
140 // Checks for whitespace
141 return (this.trim ? /^\s*$/ : /^$/).test(value); // Boolean
142 },
143
144 getErrorMessage: function(/*Boolean*/ /*===== isFocused =====*/){
145 // summary:
146 // Return an error message to show if appropriate
147 // tags:
148 // protected
149 var invalid = this.invalidMessage == "$_unset_$" ? this.messages.invalidMessage :
150 !this.invalidMessage ? this.promptMessage : this.invalidMessage;
151 var missing = this.missingMessage == "$_unset_$" ? this.messages.missingMessage :
152 !this.missingMessage ? invalid : this.missingMessage;
153 return (this.required && this._isEmpty(this.textbox.value)) ? missing : invalid; // String
154 },
155
156 getPromptMessage: function(/*Boolean*/ /*===== isFocused =====*/){
157 // summary:
158 // Return a hint message to show when widget is first focused
159 // tags:
160 // protected
161 return this.promptMessage; // String
162 },
163
164 _maskValidSubsetError: true,
165 validate: function(/*Boolean*/ isFocused){
166 // summary:
167 // Called by oninit, onblur, and onkeypress.
168 // description:
169 // Show missing or invalid messages if appropriate, and highlight textbox field.
170 // tags:
171 // protected
172 var message = "";
173 var isValid = this.disabled || this.isValid(isFocused);
174 if(isValid){ this._maskValidSubsetError = true; }
175 var isEmpty = this._isEmpty(this.textbox.value);
176 var isValidSubset = !isValid && isFocused && this._isValidSubset();
177 this._set("state", isValid ? "" : (((((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && (this._maskValidSubsetError || (isValidSubset && !this._hasBeenBlurred && isFocused))) ? "Incomplete" : "Error"));
178 this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true");
179
180 if(this.state == "Error"){
181 this._maskValidSubsetError = isFocused && isValidSubset; // we want the error to show up after a blur and refocus
182 message = this.getErrorMessage(isFocused);
183 }else if(this.state == "Incomplete"){
184 message = this.getPromptMessage(isFocused); // show the prompt whenever the value is not yet complete
185 this._maskValidSubsetError = !this._hasBeenBlurred || isFocused; // no Incomplete warnings while focused
186 }else if(isEmpty){
187 message = this.getPromptMessage(isFocused); // show the prompt whenever there's no error and no text
188 }
189 this.set("message", message);
190
191 return isValid;
192 },
193
194 displayMessage: function(/*String*/ message){
195 // summary:
196 // Overridable method to display validation errors/hints.
197 // By default uses a tooltip.
198 // tags:
199 // extension
200 if(message && this.focused){
201 Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
202 }else{
203 Tooltip.hide(this.domNode);
204 }
205 },
206
207 _refreshState: function(){
208 // Overrides TextBox._refreshState()
209 if(this._created){
210 this.validate(this.focused);
211 }
212 this.inherited(arguments);
213 },
214
215 //////////// INITIALIZATION METHODS ///////////////////////////////////////
216
217 constructor: function(params /*===== , srcNodeRef =====*/){
218 // summary:
219 // Create the widget.
220 // params: Object|null
221 // Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
222 // and functions, typically callbacks like onClick.
223 // The hash can contain any of the widget's properties, excluding read-only properties.
224 // srcNodeRef: DOMNode|String?
225 // If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree.
226
227 this.constraints = {};
228 this.baseClass += ' dijitValidationTextBox';
229 },
230
231 startup: function(){
232 this.inherited(arguments);
233 this._refreshState(); // after all _set* methods have run
234 },
235
236 _setConstraintsAttr: function(/*__Constraints*/ constraints){
237 if(!constraints.locale && this.lang){
238 constraints.locale = this.lang;
239 }
240 this._set("constraints", constraints);
241 this._refreshState();
242 },
243
244 _setPatternAttr: function(/*String|Function*/ pattern){
245 this._set("pattern", pattern); // don't set on INPUT to avoid native HTML5 validation
246 },
247
248 _getPatternAttr: function(/*__Constraints*/ constraints){
249 // summary:
250 // Hook to get the current regExp and to compute the partial validation RE.
251 var p = this.pattern;
252 var type = (typeof p).toLowerCase();
253 if(type == "function"){
254 p = this.pattern(constraints || this.constraints);
255 }
256 if(p != this._lastRegExp){
257 var partialre = "";
258 this._lastRegExp = p;
259 // parse the regexp and produce a new regexp that matches valid subsets
260 // if the regexp is .* then there's no use in matching subsets since everything is valid
261 if(p != ".*"){
262 p.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g,
263 function(re){
264 switch(re.charAt(0)){
265 case '{':
266 case '+':
267 case '?':
268 case '*':
269 case '^':
270 case '$':
271 case '|':
272 case '(':
273 partialre += re;
274 break;
275 case ")":
276 partialre += "|$)";
277 break;
278 default:
279 partialre += "(?:"+re+"|$)";
280 break;
281 }
282 });
283 }
284 try{ // this is needed for now since the above regexp parsing needs more test verification
285 "".search(partialre);
286 }catch(e){ // should never be here unless the original RE is bad or the parsing is bad
287 partialre = this.pattern;
288 console.warn('RegExp error in ' + this.declaredClass + ': ' + this.pattern);
289 } // should never be here unless the original RE is bad or the parsing is bad
290 this._partialre = "^(?:" + partialre + ")$";
291 }
292 return p;
293 },
294
295 postMixInProperties: function(){
296 this.inherited(arguments);
297 this.messages = i18n.getLocalization("dijit.form", "validate", this.lang);
298 this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls attachPoints
299 },
300
301 _setDisabledAttr: function(/*Boolean*/ value){
302 this.inherited(arguments); // call FormValueWidget._setDisabledAttr()
303 this._refreshState();
304 },
305
306 _setRequiredAttr: function(/*Boolean*/ value){
307 this._set("required", value);
308 this.focusNode.setAttribute("aria-required", value);
309 this._refreshState();
310 },
311
312 _setMessageAttr: function(/*String*/ message){
313 this._set("message", message);
314 this.displayMessage(message);
315 },
316
317 reset:function(){
318 // Overrides dijit/form/TextBox.reset() by also
319 // hiding errors about partial matches
320 this._maskValidSubsetError = true;
321 this.inherited(arguments);
322 },
323
324 _onBlur: function(){
325 // the message still exists but for back-compat, and to erase the tooltip
326 // (if the message is being displayed as a tooltip), call displayMessage('')
327 this.displayMessage('');
328
329 this.inherited(arguments);
330 }
331 });
332 });