ValidationTextBox.js 9.6 KB

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