TextField.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:20k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!
  2.  * Ext JS Library 3.1.0
  3.  * Copyright(c) 2006-2009 Ext JS, LLC
  4.  * licensing@extjs.com
  5.  * http://www.extjs.com/license
  6.  */
  7. /**
  8.  * @class Ext.form.TextField
  9.  * @extends Ext.form.Field
  10.  * <p>Basic text field.  Can be used as a direct replacement for traditional text inputs,
  11.  * or as the base class for more sophisticated input controls (like {@link Ext.form.TextArea}
  12.  * and {@link Ext.form.ComboBox}).</p>
  13.  * <p><b><u>Validation</u></b></p>
  14.  * <p>The validation procedure is described in the documentation for {@link #validateValue}.</p>
  15.  * <p><b><u>Alter Validation Behavior</u></b></p>
  16.  * <p>Validation behavior for each field can be configured:</p>
  17.  * <div class="mdetail-params"><ul>
  18.  * <li><code>{@link Ext.form.TextField#invalidText invalidText}</code> : the default validation message to
  19.  * show if any validation step above does not provide a message when invalid</li>
  20.  * <li><code>{@link Ext.form.TextField#maskRe maskRe}</code> : filter out keystrokes before any validation occurs</li>
  21.  * <li><code>{@link Ext.form.TextField#stripCharsRe stripCharsRe}</code> : filter characters after being typed in,
  22.  * but before being validated</li>
  23.  * <li><code>{@link Ext.form.Field#invalidClass invalidClass}</code> : alternate style when invalid</li>
  24.  * <li><code>{@link Ext.form.Field#validateOnBlur validateOnBlur}</code>,
  25.  * <code>{@link Ext.form.Field#validationDelay validationDelay}</code>, and
  26.  * <code>{@link Ext.form.Field#validationEvent validationEvent}</code> : modify how/when validation is triggered</li>
  27.  * </ul></div>
  28.  * 
  29.  * @constructor Creates a new TextField
  30.  * @param {Object} config Configuration options
  31.  * 
  32.  * @xtype textfield
  33.  */
  34. Ext.form.TextField = Ext.extend(Ext.form.Field,  {
  35.     /**
  36.      * @cfg {String} vtypeText A custom error message to display in place of the default message provided
  37.      * for the <b><code>{@link #vtype}</code></b> currently set for this field (defaults to <tt>''</tt>).  <b>Note</b>:
  38.      * only applies if <b><code>{@link #vtype}</code></b> is set, else ignored.
  39.      */
  40.     /**
  41.      * @cfg {RegExp} stripCharsRe A JavaScript RegExp object used to strip unwanted content from the value
  42.      * before validation (defaults to <tt>null</tt>).
  43.      */
  44.     /**
  45.      * @cfg {Boolean} grow <tt>true</tt> if this field should automatically grow and shrink to its content
  46.      * (defaults to <tt>false</tt>)
  47.      */
  48.     grow : false,
  49.     /**
  50.      * @cfg {Number} growMin The minimum width to allow when <code><b>{@link #grow}</b> = true</code> (defaults
  51.      * to <tt>30</tt>)
  52.      */
  53.     growMin : 30,
  54.     /**
  55.      * @cfg {Number} growMax The maximum width to allow when <code><b>{@link #grow}</b> = true</code> (defaults
  56.      * to <tt>800</tt>)
  57.      */
  58.     growMax : 800,
  59.     /**
  60.      * @cfg {String} vtype A validation type name as defined in {@link Ext.form.VTypes} (defaults to <tt>null</tt>)
  61.      */
  62.     vtype : null,
  63.     /**
  64.      * @cfg {RegExp} maskRe An input mask regular expression that will be used to filter keystrokes that do
  65.      * not match (defaults to <tt>null</tt>)
  66.      */
  67.     maskRe : null,
  68.     /**
  69.      * @cfg {Boolean} disableKeyFilter Specify <tt>true</tt> to disable input keystroke filtering (defaults
  70.      * to <tt>false</tt>)
  71.      */
  72.     disableKeyFilter : false,
  73.     /**
  74.      * @cfg {Boolean} allowBlank Specify <tt>false</tt> to validate that the value's length is > 0 (defaults to
  75.      * <tt>true</tt>)
  76.      */
  77.     allowBlank : true,
  78.     /**
  79.      * @cfg {Number} minLength Minimum input field length required (defaults to <tt>0</tt>)
  80.      */
  81.     minLength : 0,
  82.     /**
  83.      * @cfg {Number} maxLength Maximum input field length allowed by validation (defaults to Number.MAX_VALUE).
  84.      * This behavior is intended to provide instant feedback to the user by improving usability to allow pasting
  85.      * and editing or overtyping and back tracking. To restrict the maximum number of characters that can be
  86.      * entered into the field use <tt><b>{@link Ext.form.Field#autoCreate autoCreate}</b></tt> to add
  87.      * any attributes you want to a field, for example:<pre><code>
  88. var myField = new Ext.form.NumberField({
  89.     id: 'mobile',
  90.     anchor:'90%',
  91.     fieldLabel: 'Mobile',
  92.     maxLength: 16, // for validation
  93.     autoCreate: {tag: 'input', type: 'text', size: '20', autocomplete: 'off', maxlength: '10'}
  94. });
  95. </code></pre>
  96.      */
  97.     maxLength : Number.MAX_VALUE,
  98.     /**
  99.      * @cfg {String} minLengthText Error text to display if the <b><tt>{@link #minLength minimum length}</tt></b>
  100.      * validation fails (defaults to <tt>'The minimum length for this field is {minLength}'</tt>)
  101.      */
  102.     minLengthText : 'The minimum length for this field is {0}',
  103.     /**
  104.      * @cfg {String} maxLengthText Error text to display if the <b><tt>{@link #maxLength maximum length}</tt></b>
  105.      * validation fails (defaults to <tt>'The maximum length for this field is {maxLength}'</tt>)
  106.      */
  107.     maxLengthText : 'The maximum length for this field is {0}',
  108.     /**
  109.      * @cfg {Boolean} selectOnFocus <tt>true</tt> to automatically select any existing field text when the field
  110.      * receives input focus (defaults to <tt>false</tt>)
  111.      */
  112.     selectOnFocus : false,
  113.     /**
  114.      * @cfg {String} blankText The error text to display if the <b><tt>{@link #allowBlank}</tt></b> validation
  115.      * fails (defaults to <tt>'This field is required'</tt>)
  116.      */
  117.     blankText : 'This field is required',
  118.     /**
  119.      * @cfg {Function} validator
  120.      * <p>A custom validation function to be called during field validation ({@link #validateValue})
  121.      * (defaults to <tt>null</tt>). If specified, this function will be called first, allowing the
  122.      * developer to override the default validation process.</p>
  123.      * <br><p>This function will be passed the following Parameters:</p>
  124.      * <div class="mdetail-params"><ul>
  125.      * <li><code>value</code>: <i>Mixed</i>
  126.      * <div class="sub-desc">The current field value</div></li>
  127.      * </ul></div>
  128.      * <br><p>This function is to Return:</p>
  129.      * <div class="mdetail-params"><ul>
  130.      * <li><code>true</code>: <i>Boolean</i>
  131.      * <div class="sub-desc"><code>true</code> if the value is valid</div></li>
  132.      * <li><code>msg</code>: <i>String</i>
  133.      * <div class="sub-desc">An error message if the value is invalid</div></li>
  134.      * </ul></div>
  135.      */
  136.     validator : null,
  137.     /**
  138.      * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation
  139.      * (defaults to <tt>null</tt>). If the test fails, the field will be marked invalid using
  140.      * <b><tt>{@link #regexText}</tt></b>.
  141.      */
  142.     regex : null,
  143.     /**
  144.      * @cfg {String} regexText The error text to display if <b><tt>{@link #regex}</tt></b> is used and the
  145.      * test fails during validation (defaults to <tt>''</tt>)
  146.      */
  147.     regexText : '',
  148.     /**
  149.      * @cfg {String} emptyText The default text to place into an empty field (defaults to <tt>null</tt>).
  150.      * <b>Note</b>: that this value will be submitted to the server if this field is enabled and configured
  151.      * with a {@link #name}.
  152.      */
  153.     emptyText : null,
  154.     /**
  155.      * @cfg {String} emptyClass The CSS class to apply to an empty field to style the <b><tt>{@link #emptyText}</tt></b>
  156.      * (defaults to <tt>'x-form-empty-field'</tt>).  This class is automatically added and removed as needed
  157.      * depending on the current field value.
  158.      */
  159.     emptyClass : 'x-form-empty-field',
  160.     /**
  161.      * @cfg {Boolean} enableKeyEvents <tt>true</tt> to enable the proxying of key events for the HTML input
  162.      * field (defaults to <tt>false</tt>)
  163.      */
  164.     initComponent : function(){
  165.         Ext.form.TextField.superclass.initComponent.call(this);
  166.         this.addEvents(
  167.             /**
  168.              * @event autosize
  169.              * Fires when the <tt><b>{@link #autoSize}</b></tt> function is triggered. The field may or
  170.              * may not have actually changed size according to the default logic, but this event provides
  171.              * a hook for the developer to apply additional logic at runtime to resize the field if needed.
  172.              * @param {Ext.form.Field} this This text field
  173.              * @param {Number} width The new field width
  174.              */
  175.             'autosize',
  176.             /**
  177.              * @event keydown
  178.              * Keydown input field event. This event only fires if <tt><b>{@link #enableKeyEvents}</b></tt>
  179.              * is set to true.
  180.              * @param {Ext.form.TextField} this This text field
  181.              * @param {Ext.EventObject} e
  182.              */
  183.             'keydown',
  184.             /**
  185.              * @event keyup
  186.              * Keyup input field event. This event only fires if <tt><b>{@link #enableKeyEvents}</b></tt>
  187.              * is set to true.
  188.              * @param {Ext.form.TextField} this This text field
  189.              * @param {Ext.EventObject} e
  190.              */
  191.             'keyup',
  192.             /**
  193.              * @event keypress
  194.              * Keypress input field event. This event only fires if <tt><b>{@link #enableKeyEvents}</b></tt>
  195.              * is set to true.
  196.              * @param {Ext.form.TextField} this This text field
  197.              * @param {Ext.EventObject} e
  198.              */
  199.             'keypress'
  200.         );
  201.     },
  202.     // private
  203.     initEvents : function(){
  204.         Ext.form.TextField.superclass.initEvents.call(this);
  205.         if(this.validationEvent == 'keyup'){
  206.             this.validationTask = new Ext.util.DelayedTask(this.validate, this);
  207.             this.mon(this.el, 'keyup', this.filterValidation, this);
  208.         }
  209.         else if(this.validationEvent !== false && this.validationEvent != 'blur'){
  210.          this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});
  211.         }
  212.         if(this.selectOnFocus || this.emptyText){            
  213.             this.mon(this.el, 'mousedown', this.onMouseDown, this);
  214.             
  215.             if(this.emptyText){
  216.                 this.applyEmptyText();
  217.             }
  218.         }
  219.         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
  220.          this.mon(this.el, 'keypress', this.filterKeys, this);
  221.         }
  222.         if(this.grow){
  223.          this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50});
  224. this.mon(this.el, 'click', this.autoSize, this);
  225.         }
  226.         if(this.enableKeyEvents){
  227.             this.mon(this.el, {
  228.                 scope: this,
  229.                 keyup: this.onKeyUp,
  230.                 keydown: this.onKeyDown,
  231.                 keypress: this.onKeyPress
  232.             });
  233.         }
  234.     },
  235.     
  236.     onMouseDown: function(e){
  237.         if(!this.hasFocus){
  238.             this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
  239.         }
  240.     },
  241.     processValue : function(value){
  242.         if(this.stripCharsRe){
  243.             var newValue = value.replace(this.stripCharsRe, '');
  244.             if(newValue !== value){
  245.                 this.setRawValue(newValue);
  246.                 return newValue;
  247.             }
  248.         }
  249.         return value;
  250.     },
  251.     filterValidation : function(e){
  252.         if(!e.isNavKeyPress()){
  253.             this.validationTask.delay(this.validationDelay);
  254.         }
  255.     },
  256.     
  257.     //private
  258.     onDisable: function(){
  259.         Ext.form.TextField.superclass.onDisable.call(this);
  260.         if(Ext.isIE){
  261.             this.el.dom.unselectable = 'on';
  262.         }
  263.     },
  264.     
  265.     //private
  266.     onEnable: function(){
  267.         Ext.form.TextField.superclass.onEnable.call(this);
  268.         if(Ext.isIE){
  269.             this.el.dom.unselectable = '';
  270.         }
  271.     },
  272.     // private
  273.     onKeyUpBuffered : function(e){
  274.         if(this.doAutoSize(e)){
  275.             this.autoSize();
  276.         }
  277.     },
  278.     
  279.     // private
  280.     doAutoSize : function(e){
  281.         return !e.isNavKeyPress();
  282.     },
  283.     // private
  284.     onKeyUp : function(e){
  285.         this.fireEvent('keyup', this, e);
  286.     },
  287.     // private
  288.     onKeyDown : function(e){
  289.         this.fireEvent('keydown', this, e);
  290.     },
  291.     // private
  292.     onKeyPress : function(e){
  293.         this.fireEvent('keypress', this, e);
  294.     },
  295.     /**
  296.      * Resets the current field value to the originally-loaded value and clears any validation messages.
  297.      * Also adds <tt><b>{@link #emptyText}</b></tt> and <tt><b>{@link #emptyClass}</b></tt> if the
  298.      * original value was blank.
  299.      */
  300.     reset : function(){
  301.         Ext.form.TextField.superclass.reset.call(this);
  302.         this.applyEmptyText();
  303.     },
  304.     applyEmptyText : function(){
  305.         if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
  306.             this.setRawValue(this.emptyText);
  307.             this.el.addClass(this.emptyClass);
  308.         }
  309.     },
  310.     // private
  311.     preFocus : function(){
  312.         var el = this.el;
  313.         if(this.emptyText){
  314.             if(el.dom.value == this.emptyText){
  315.                 this.setRawValue('');
  316.             }
  317.             el.removeClass(this.emptyClass);
  318.         }
  319.         if(this.selectOnFocus){
  320.             el.dom.select();
  321.         }
  322.     },
  323.     // private
  324.     postBlur : function(){
  325.         this.applyEmptyText();
  326.     },
  327.     // private
  328.     filterKeys : function(e){
  329.         if(e.ctrlKey){
  330.             return;
  331.         }
  332.         var k = e.getKey();
  333.         if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
  334.             return;
  335.         }
  336.         var cc = String.fromCharCode(e.getCharCode());
  337.         if(!Ext.isGecko && e.isSpecialKey() && !cc){
  338.             return;
  339.         }
  340.         if(!this.maskRe.test(cc)){
  341.             e.stopEvent();
  342.         }
  343.     },
  344.     setValue : function(v){
  345.         if(this.emptyText && this.el && !Ext.isEmpty(v)){
  346.             this.el.removeClass(this.emptyClass);
  347.         }
  348.         Ext.form.TextField.superclass.setValue.apply(this, arguments);
  349.         this.applyEmptyText();
  350.         this.autoSize();
  351.         return this;
  352.     },
  353.     /**
  354.      * <p>Validates a value according to the field's validation rules and marks the field as invalid
  355.      * if the validation fails. Validation rules are processed in the following order:</p>
  356.      * <div class="mdetail-params"><ul>
  357.      * 
  358.      * <li><b>1. Field specific validator</b>
  359.      * <div class="sub-desc">
  360.      * <p>A validator offers a way to customize and reuse a validation specification.
  361.      * If a field is configured with a <code>{@link #validator}</code>
  362.      * function, it will be passed the current field value.  The <code>{@link #validator}</code>
  363.      * function is expected to return either:
  364.      * <div class="mdetail-params"><ul>
  365.      * <li>Boolean <tt>true</tt> if the value is valid (validation continues).</li>
  366.      * <li>a String to represent the invalid message if invalid (validation halts).</li>
  367.      * </ul></div>
  368.      * </div></li>
  369.      * 
  370.      * <li><b>2. Basic Validation</b>
  371.      * <div class="sub-desc">
  372.      * <p>If the <code>{@link #validator}</code> has not halted validation,
  373.      * basic validation proceeds as follows:</p>
  374.      * 
  375.      * <div class="mdetail-params"><ul>
  376.      * 
  377.      * <li><code>{@link #allowBlank}</code> : (Invalid message =
  378.      * <code>{@link #emptyText}</code>)<div class="sub-desc">
  379.      * Depending on the configuration of <code>{@link #allowBlank}</code>, a
  380.      * blank field will cause validation to halt at this step and return
  381.      * Boolean true or false accordingly.  
  382.      * </div></li>
  383.      * 
  384.      * <li><code>{@link #minLength}</code> : (Invalid message =
  385.      * <code>{@link #minLengthText}</code>)<div class="sub-desc">
  386.      * If the passed value does not satisfy the <code>{@link #minLength}</code>
  387.      * specified, validation halts.
  388.      * </div></li>
  389.      * 
  390.      * <li><code>{@link #maxLength}</code> : (Invalid message =
  391.      * <code>{@link #maxLengthText}</code>)<div class="sub-desc">
  392.      * If the passed value does not satisfy the <code>{@link #maxLength}</code>
  393.      * specified, validation halts.
  394.      * </div></li>
  395.      * 
  396.      * </ul></div>
  397.      * </div></li>
  398.      * 
  399.      * <li><b>3. Preconfigured Validation Types (VTypes)</b>
  400.      * <div class="sub-desc">
  401.      * <p>If none of the prior validation steps halts validation, a field
  402.      * configured with a <code>{@link #vtype}</code> will utilize the
  403.      * corresponding {@link Ext.form.VTypes VTypes} validation function.
  404.      * If invalid, either the field's <code>{@link #vtypeText}</code> or
  405.      * the VTypes vtype Text property will be used for the invalid message.
  406.      * Keystrokes on the field will be filtered according to the VTypes
  407.      * vtype Mask property.</p>
  408.      * </div></li>
  409.      * 
  410.      * <li><b>4. Field specific regex test</b>
  411.      * <div class="sub-desc">
  412.      * <p>If none of the prior validation steps halts validation, a field's
  413.      * configured <code>{@link #regex}</code> test will be processed.
  414.      * The invalid message for this test is configured with
  415.      * <code>{@link #regexText}</code>.</p>
  416.      * </div></li>
  417.      * 
  418.      * @param {Mixed} value The value to validate
  419.      * @return {Boolean} True if the value is valid, else false
  420.      */
  421.     validateValue : function(value){
  422.         if(Ext.isFunction(this.validator)){
  423.             var msg = this.validator(value);
  424.             if(msg !== true){
  425.                 this.markInvalid(msg);
  426.                 return false;
  427.             }
  428.         }
  429.         if(value.length < 1 || value === this.emptyText){ // if it's blank
  430.              if(this.allowBlank){
  431.                  this.clearInvalid();
  432.                  return true;
  433.              }else{
  434.                  this.markInvalid(this.blankText);
  435.                  return false;
  436.              }
  437.         }
  438.         if(value.length < this.minLength){
  439.             this.markInvalid(String.format(this.minLengthText, this.minLength));
  440.             return false;
  441.         }
  442.         if(value.length > this.maxLength){
  443.             this.markInvalid(String.format(this.maxLengthText, this.maxLength));
  444.             return false;
  445.         }
  446.         if(this.vtype){
  447.             var vt = Ext.form.VTypes;
  448.             if(!vt[this.vtype](value, this)){
  449.                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
  450.                 return false;
  451.             }
  452.         }
  453.         if(this.regex && !this.regex.test(value)){
  454.             this.markInvalid(this.regexText);
  455.             return false;
  456.         }
  457.         return true;
  458.     },
  459.     /**
  460.      * Selects text in this field
  461.      * @param {Number} start (optional) The index where the selection should start (defaults to 0)
  462.      * @param {Number} end (optional) The index where the selection should end (defaults to the text length)
  463.      */
  464.     selectText : function(start, end){
  465.         var v = this.getRawValue();
  466.         var doFocus = false;
  467.         if(v.length > 0){
  468.             start = start === undefined ? 0 : start;
  469.             end = end === undefined ? v.length : end;
  470.             var d = this.el.dom;
  471.             if(d.setSelectionRange){
  472.                 d.setSelectionRange(start, end);
  473.             }else if(d.createTextRange){
  474.                 var range = d.createTextRange();
  475.                 range.moveStart('character', start);
  476.                 range.moveEnd('character', end-v.length);
  477.                 range.select();
  478.             }
  479.             doFocus = Ext.isGecko || Ext.isOpera;
  480.         }else{
  481.             doFocus = true;
  482.         }
  483.         if(doFocus){
  484.             this.focus();
  485.         }
  486.     },
  487.     /**
  488.      * Automatically grows the field to accomodate the width of the text up to the maximum field width allowed.
  489.      * This only takes effect if <tt><b>{@link #grow}</b> = true</tt>, and fires the {@link #autosize} event.
  490.      */
  491.     autoSize : function(){
  492.         if(!this.grow || !this.rendered){
  493.             return;
  494.         }
  495.         if(!this.metrics){
  496.             this.metrics = Ext.util.TextMetrics.createInstance(this.el);
  497.         }
  498.         var el = this.el;
  499.         var v = el.dom.value;
  500.         var d = document.createElement('div');
  501.         d.appendChild(document.createTextNode(v));
  502.         v = d.innerHTML;
  503.         Ext.removeNode(d);
  504.         d = null;
  505.         v += '&#160;';
  506.         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) + /* add extra padding */ 10, this.growMin));
  507.         this.el.setWidth(w);
  508.         this.fireEvent('autosize', this, w);
  509.     },
  510. onDestroy: function(){
  511. if(this.validationTask){
  512. this.validationTask.cancel();
  513. this.validationTask = null;
  514. }
  515. Ext.form.TextField.superclass.onDestroy.call(this);
  516. }
  517. });
  518. Ext.reg('textfield', Ext.form.TextField);