6cb08187794b8d752cd868c7e76080040de7bb6e.svn-base 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. * Ext JS Library 2.0 Copyright(c) 2006-2007, Ext JS, LLC. licensing@extjs.com
  3. *
  4. * http://extjs.com/license
  5. */
  6. /**
  7. * @class Ext.form.TextField
  8. * @extends Ext.form.Field Basic text field. Can be used as a direct replacement
  9. * for traditional text inputs, or as the base class for more
  10. * sophisticated input controls (like {@link Ext.form.TextArea} and
  11. * {@link Ext.form.ComboBox}).
  12. * @constructor Creates a new TextField
  13. * @param {Object}
  14. * config Configuration options
  15. */
  16. Ext.form.TextField = Ext.extend(Ext.form.Field, {
  17. /**
  18. * @cfg {String} vtypeText A custom error message to display in place of the
  19. * default message provided for the {@link #vtype} currently set for
  20. * this field (defaults to ''). Only applies if vtype is set, else
  21. * ignored.
  22. */
  23. /**
  24. * @cfg {Boolean} grow True if this field should automatically grow and
  25. * shrink to its content
  26. */
  27. grow : false,
  28. /**
  29. * @cfg {Number} growMin The minimum width to allow when grow = true
  30. * (defaults to 30)
  31. */
  32. growMin : 30,
  33. /**
  34. * @cfg {Number} growMax The maximum width to allow when grow = true
  35. * (defaults to 800)
  36. */
  37. growMax : 800,
  38. /**
  39. * @cfg {String} vtype A validation type name as defined in
  40. * {@link Ext.form.VTypes} (defaults to null)
  41. */
  42. vtype : null,
  43. /**
  44. * @cfg {RegExp} maskRe An input mask regular expression that will be used
  45. * to filter keystrokes that don't match (defaults to null)
  46. */
  47. maskRe : null,
  48. /**
  49. * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering
  50. * (defaults to false)
  51. */
  52. disableKeyFilter : false,
  53. /**
  54. * @cfg {Boolean} allowBlank False to validate that the value length > 0
  55. * (defaults to true)
  56. */
  57. allowBlank : true,
  58. /**
  59. * @cfg {Number} minLength Minimum input field length required (defaults to
  60. * 0)
  61. */
  62. minLength : 0,
  63. /**
  64. * @cfg {Number} maxLength Maximum input field length allowed (defaults to
  65. * Number.MAX_VALUE)
  66. */
  67. maxLength : Number.MAX_VALUE,
  68. /**
  69. * @cfg {String} minLengthText Error text to display if the minimum length
  70. * validation fails (defaults to "The minimum length for this field is
  71. * {minLength}")
  72. */
  73. minLengthText : "The minimum length for this field is {0}",
  74. /**
  75. * @cfg {String} maxLengthText Error text to display if the maximum length
  76. * validation fails (defaults to "The maximum length for this field is
  77. * {maxLength}")
  78. */
  79. maxLengthText : "The maximum length for this field is {0}",
  80. /**
  81. * @cfg {Boolean} selectOnFocus True to automatically select any existing
  82. * field text when the field receives input focus (defaults to false)
  83. */
  84. selectOnFocus : false,
  85. /**
  86. * @cfg {String} blankText Error text to display if the allow blank
  87. * validation fails (defaults to "This field is required")
  88. */
  89. blankText : "This field is required",
  90. /**
  91. * @cfg {Function} validator A custom validation function to be called
  92. * during field validation (defaults to null). If available, this
  93. * function will be called only after the basic validators all return
  94. * true, and will be passed the current field value and expected to
  95. * return boolean true if the value is valid or a string error message
  96. * if invalid.
  97. */
  98. validator : null,
  99. /**
  100. * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the
  101. * field value during validation (defaults to null). If available, this
  102. * regex will be evaluated only after the basic validators all return
  103. * true, and will be passed the current field value. If the test fails,
  104. * the field will be marked invalid using {@link #regexText}.
  105. */
  106. regex : null,
  107. /**
  108. * @cfg {String} regexText The error text to display if {@link #regex} is
  109. * used and the test fails during validation (defaults to "")
  110. */
  111. regexText : "",
  112. /**
  113. * @cfg {String} emptyText The default text to display in an empty field
  114. * (defaults to null).
  115. */
  116. emptyText : null,
  117. /**
  118. * @cfg {String} emptyClass The CSS class to apply to an empty field to
  119. * style the {@link #emptyText} (defaults to 'x-form-empty-field').
  120. * This class is automatically added and removed as needed depending on
  121. * the current field value.
  122. */
  123. emptyClass : 'x-form-empty-field',
  124. initComponent : function() {
  125. Ext.form.TextField.superclass.initComponent.call(this);
  126. this.addEvents(
  127. /**
  128. * @event autosize Fires when the autosize function is
  129. * triggered. The field may or may not have actually
  130. * changed size according to the default logic, but this
  131. * event provides a hook for the developer to apply
  132. * additional logic at runtime to resize the field if
  133. * needed.
  134. * @param {Ext.form.Field}
  135. * this This text field
  136. * @param {Number}
  137. * width The new field width
  138. */
  139. 'autosize');
  140. },
  141. // private
  142. initEvents : function() {
  143. Ext.form.TextField.superclass.initEvents.call(this);
  144. if (this.validationEvent == 'keyup') {
  145. this.validationTask = new Ext.util.DelayedTask(this.validate, this);
  146. this.el.on('keyup', this.filterValidation, this);
  147. } else if (this.validationEvent !== false) {
  148. this.el.on(this.validationEvent, this.validate, this, {
  149. buffer : this.validationDelay
  150. });
  151. }
  152. if (this.selectOnFocus || this.emptyText) {
  153. this.on("focus", this.preFocus, this);
  154. if (this.emptyText) {
  155. this.on('blur', this.postBlur, this);
  156. this.applyEmptyText();
  157. }
  158. }
  159. if (this.maskRe
  160. || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype
  161. + 'Mask']))) {
  162. this.el.on("keypress", this.filterKeys, this);
  163. }
  164. if (this.grow) {
  165. this.el.on("keyup", this.onKeyUp, this, {
  166. buffer : 50
  167. });
  168. this.el.on("click", this.autoSize, this);
  169. }
  170. },
  171. processValue : function(value) {
  172. if (this.stripCharsRe) {
  173. var newValue = value.replace(this.stripCharsRe, '');
  174. if (newValue !== value) {
  175. this.setRawValue(newValue);
  176. return newValue;
  177. }
  178. }
  179. return value;
  180. },
  181. filterValidation : function(e) {
  182. if (!e.isNavKeyPress()) {
  183. this.validationTask.delay(this.validationDelay);
  184. }
  185. },
  186. // private
  187. onKeyUp : function(e) {
  188. if (!e.isNavKeyPress()) {
  189. this.autoSize();
  190. }
  191. },
  192. /**
  193. * Resets the current field value to the originally-loaded value and clears
  194. * any validation messages. Also adds emptyText and emptyClass if the
  195. * original value was blank.
  196. */
  197. reset : function() {
  198. Ext.form.TextField.superclass.reset.call(this);
  199. this.applyEmptyText();
  200. },
  201. applyEmptyText : function() {
  202. if (this.rendered && this.emptyText && this.getRawValue().length < 1) {
  203. this.setRawValue(this.emptyText);
  204. this.el.addClass(this.emptyClass);
  205. }
  206. },
  207. // private
  208. preFocus : function() {
  209. if (this.emptyText) {
  210. if (this.el.dom.value == this.emptyText) {
  211. this.setRawValue('');
  212. }
  213. this.el.removeClass(this.emptyClass);
  214. }
  215. if (this.selectOnFocus) {
  216. this.el.dom.select();
  217. }
  218. },
  219. // private
  220. postBlur : function() {
  221. this.applyEmptyText();
  222. },
  223. // private
  224. filterKeys : function(e) {
  225. var k = e.getKey();
  226. if (!Ext.isIE
  227. && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))) {
  228. return;
  229. }
  230. var c = e.getCharCode(), cc = String.fromCharCode(c);
  231. if (Ext.isIE && (e.isSpecialKey() || !cc)) {
  232. return;
  233. }
  234. if (!this.maskRe.test(cc)) {
  235. e.stopEvent();
  236. }
  237. },
  238. setValue : function(v) {
  239. if (this.emptyText && this.el && v !== undefined && v !== null
  240. && v !== '') {
  241. this.el.removeClass(this.emptyClass);
  242. }
  243. Ext.form.TextField.superclass.setValue.apply(this, arguments);
  244. this.applyEmptyText();
  245. this.autoSize();
  246. },
  247. /**
  248. * Validates a value according to the field's validation rules and marks the
  249. * field as invalid if the validation fails
  250. *
  251. * @param {Mixed}
  252. * value The value to validate
  253. * @return {Boolean} True if the value is valid, else false
  254. */
  255. validateValue : function(value) {
  256. if (value.length < 1 || value === this.emptyText) { // if it's blank
  257. if (this.allowBlank) {
  258. this.clearInvalid();
  259. return true;
  260. } else {
  261. this.markInvalid(this.blankText);
  262. return false;
  263. }
  264. }
  265. if (value.length < this.minLength) {
  266. this.markInvalid(String.format(this.minLengthText, this.minLength));
  267. return false;
  268. }
  269. if (value.length > this.maxLength) {
  270. this.markInvalid(String.format(this.maxLengthText, this.maxLength));
  271. return false;
  272. }
  273. if (this.vtype) {
  274. var vt = Ext.form.VTypes;
  275. if (!vt[this.vtype](value, this)) {
  276. this.markInvalid(this.vtypeText || vt[this.vtype + 'Text']);
  277. return false;
  278. }
  279. }
  280. if (typeof this.validator == "function") {
  281. var msg = this.validator(value);
  282. if (msg !== true) {
  283. this.markInvalid(msg);
  284. return false;
  285. }
  286. }
  287. if (this.regex && !this.regex.test(value)) {
  288. this.markInvalid(this.regexText);
  289. return false;
  290. }
  291. return true;
  292. },
  293. /**
  294. * Selects text in this field
  295. *
  296. * @param {Number}
  297. * start (optional) The index where the selection should start
  298. * (defaults to 0)
  299. * @param {Number}
  300. * end (optional) The index where the selection should end
  301. * (defaults to the text length)
  302. */
  303. selectText : function(start, end) {
  304. var v = this.getRawValue();
  305. if (v.length > 0) {
  306. start = start === undefined ? 0 : start;
  307. end = end === undefined ? v.length : end;
  308. var d = this.el.dom;
  309. if (d.setSelectionRange) {
  310. d.setSelectionRange(start, end);
  311. } else if (d.createTextRange) {
  312. var range = d.createTextRange();
  313. range.moveStart("character", start);
  314. range.moveEnd("character", v.length - end);
  315. range.select();
  316. }
  317. }
  318. },
  319. /**
  320. * Automatically grows the field to accomodate the width of the text up to
  321. * the maximum field width allowed. This only takes effect if grow = true,
  322. * and fires the autosize event.
  323. */
  324. autoSize : function() {
  325. if (!this.grow || !this.rendered) {
  326. return;
  327. }
  328. if (!this.metrics) {
  329. this.metrics = Ext.util.TextMetrics.createInstance(this.el);
  330. }
  331. var el = this.el;
  332. var v = el.dom.value;
  333. var d = document.createElement('div');
  334. d.appendChild(document.createTextNode(v));
  335. v = d.innerHTML;
  336. d = null;
  337. v += "&#160;";
  338. var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v)
  339. + /* add extra padding */10, this.growMin));
  340. this.el.setWidth(w);
  341. this.fireEvent("autosize", this, w);
  342. }
  343. });
  344. Ext.reg('textfield', Ext.form.TextField);