Roo/form/ComboBoxArray.js
[roojs1] / Roo / bootstrap / Input.js
1 /*
2  * - LGPL
3  *
4  * Input
5  * 
6  */
7
8 /**
9  * @class Roo.bootstrap.Input
10  * @extends Roo.bootstrap.Component
11  * Bootstrap Input class
12  * @cfg {Boolean} disabled is it disabled
13  * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
14  * @cfg {String} name name of the input
15  * @cfg {string} fieldLabel - the label associated
16  * @cfg {string} placeholder - placeholder to put in text.
17  * @cfg {string}  before - input group add on before
18  * @cfg {string} after - input group add on after
19  * @cfg {string} size - (lg|sm) or leave empty..
20  * @cfg {Number} xs colspan out of 12 for mobile-sized screens
21  * @cfg {Number} sm colspan out of 12 for tablet-sized screens
22  * @cfg {Number} md colspan out of 12 for computer-sized screens
23  * @cfg {Number} lg colspan out of 12 for large computer-sized screens
24  * @cfg {string} value default value of the input
25  * @cfg {Number} labelWidth set the width of label (0-12)
26  * @cfg {String} labelAlign (top|left)
27  * @cfg {Boolean} readOnly Specifies that the field should be read-only
28  * @cfg {String} autocomplete - default is new-password see: https://developers.google.com/web/fundamentals/input/form/label-and-name-inputs?hl=en
29
30  * @cfg {String} align (left|center|right) Default left
31  * @cfg {Boolean} forceFeedback (true|false) Default false
32  * 
33  * 
34  * 
35  * 
36  * @constructor
37  * Create a new Input
38  * @param {Object} config The config object
39  */
40
41 Roo.bootstrap.Input = function(config){
42     Roo.bootstrap.Input.superclass.constructor.call(this, config);
43    
44         this.addEvents({
45             /**
46              * @event focus
47              * Fires when this field receives input focus.
48              * @param {Roo.form.Field} this
49              */
50             focus : true,
51             /**
52              * @event blur
53              * Fires when this field loses input focus.
54              * @param {Roo.form.Field} this
55              */
56             blur : true,
57             /**
58              * @event specialkey
59              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
60              * {@link Roo.EventObject#getKey} to determine which key was pressed.
61              * @param {Roo.form.Field} this
62              * @param {Roo.EventObject} e The event object
63              */
64             specialkey : true,
65             /**
66              * @event change
67              * Fires just before the field blurs if the field value has changed.
68              * @param {Roo.form.Field} this
69              * @param {Mixed} newValue The new value
70              * @param {Mixed} oldValue The original value
71              */
72             change : true,
73             /**
74              * @event invalid
75              * Fires after the field has been marked as invalid.
76              * @param {Roo.form.Field} this
77              * @param {String} msg The validation message
78              */
79             invalid : true,
80             /**
81              * @event valid
82              * Fires after the field has been validated with no errors.
83              * @param {Roo.form.Field} this
84              */
85             valid : true,
86              /**
87              * @event keyup
88              * Fires after the key up
89              * @param {Roo.form.Field} this
90              * @param {Roo.EventObject}  e The event Object
91              */
92             keyup : true
93         });
94 };
95
96 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
97      /**
98      * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
99       automatic validation (defaults to "keyup").
100      */
101     validationEvent : "keyup",
102      /**
103      * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
104      */
105     validateOnBlur : true,
106     /**
107      * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
108      */
109     validationDelay : 250,
110      /**
111      * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
112      */
113     focusClass : "x-form-focus",  // not needed???
114     
115        
116     /**
117      * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
118      */
119     invalidClass : "has-warning",
120     
121     /**
122      * @cfg {String} validClass The CSS class to use when marking a field valid (defaults to "x-form-invalid")
123      */
124     validClass : "has-success",
125     
126     /**
127      * @cfg {Boolean} hasFeedback (true|false) default true
128      */
129     hasFeedback : true,
130     
131     /**
132      * @cfg {String} invalidFeedbackIcon The CSS class to use when create feedback icon (defaults to "x-form-invalid")
133      */
134     invalidFeedbackClass : "glyphicon-warning-sign",
135     
136     /**
137      * @cfg {String} validFeedbackIcon The CSS class to use when create feedback icon (defaults to "x-form-invalid")
138      */
139     validFeedbackClass : "glyphicon-ok",
140     
141     /**
142      * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
143      */
144     selectOnFocus : false,
145     
146      /**
147      * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
148      */
149     maskRe : null,
150        /**
151      * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
152      */
153     vtype : null,
154     
155       /**
156      * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
157      */
158     disableKeyFilter : false,
159     
160        /**
161      * @cfg {Boolean} disabled True to disable the field (defaults to false).
162      */
163     disabled : false,
164      /**
165      * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
166      */
167     allowBlank : true,
168     /**
169      * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
170      */
171     blankText : "This field is required",
172     
173      /**
174      * @cfg {Number} minLength Minimum input field length required (defaults to 0)
175      */
176     minLength : 0,
177     /**
178      * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
179      */
180     maxLength : Number.MAX_VALUE,
181     /**
182      * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
183      */
184     minLengthText : "The minimum length for this field is {0}",
185     /**
186      * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
187      */
188     maxLengthText : "The maximum length for this field is {0}",
189   
190     
191     /**
192      * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
193      * If available, this function will be called only after the basic validators all return true, and will be passed the
194      * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
195      */
196     validator : null,
197     /**
198      * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
199      * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
200      * current field value.  If the test fails, the field will be marked invalid using {@link #regexText}.
201      */
202     regex : null,
203     /**
204      * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
205      */
206     regexText : "",
207     
208     autocomplete: false,
209     
210     
211     fieldLabel : '',
212     inputType : 'text',
213     
214     name : false,
215     placeholder: false,
216     before : false,
217     after : false,
218     size : false,
219     hasFocus : false,
220     preventMark: false,
221     isFormField : true,
222     value : '',
223     labelWidth : 2,
224     labelAlign : false,
225     readOnly : false,
226     align : false,
227     formatedValue : false,
228     forceFeedback : false,
229     
230     parentLabelAlign : function()
231     {
232         var parent = this;
233         while (parent.parent()) {
234             parent = parent.parent();
235             if (typeof(parent.labelAlign) !='undefined') {
236                 return parent.labelAlign;
237             }
238         }
239         return 'left';
240         
241     },
242     
243     getAutoCreate : function(){
244         
245         var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
246         
247         var id = Roo.id();
248         
249         var cfg = {};
250         
251         if(this.inputType != 'hidden'){
252             cfg.cls = 'form-group' //input-group
253         }
254         
255         var input =  {
256             tag: 'input',
257             id : id,
258             type : this.inputType,
259             value : this.value,
260             cls : 'form-control',
261             placeholder : this.placeholder || '',
262             autocomplete : this.autocomplete || 'new-password'
263         };
264         
265         
266         if(this.align){
267             input.style = (typeof(input.style) == 'undefined') ? ('text-align:' + this.align) : (input.style + 'text-align:' + this.align);
268         }
269         
270         if(this.maxLength && this.maxLength != Number.MAX_VALUE){
271             input.maxLength = this.maxLength;
272         }
273         
274         if (this.disabled) {
275             input.disabled=true;
276         }
277         
278         if (this.readOnly) {
279             input.readonly=true;
280         }
281         
282         if (this.name) {
283             input.name = this.name;
284         }
285         if (this.size) {
286             input.cls += ' input-' + this.size;
287         }
288         var settings=this;
289         ['xs','sm','md','lg'].map(function(size){
290             if (settings[size]) {
291                 cfg.cls += ' col-' + size + '-' + settings[size];
292             }
293         });
294         
295         var inputblock = input;
296         
297         var feedback = {
298             tag: 'span',
299             cls: 'glyphicon form-control-feedback'
300         };
301             
302         if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
303             
304             inputblock = {
305                 cls : 'has-feedback',
306                 cn :  [
307                     input,
308                     feedback
309                 ] 
310             };  
311         }
312         
313         if (this.before || this.after) {
314             
315             inputblock = {
316                 cls : 'input-group',
317                 cn :  [] 
318             };
319             
320             if (this.before && typeof(this.before) == 'string') {
321                 
322                 inputblock.cn.push({
323                     tag :'span',
324                     cls : 'roo-input-before input-group-addon',
325                     html : this.before
326                 });
327             }
328             if (this.before && typeof(this.before) == 'object') {
329                 this.before = Roo.factory(this.before);
330                 
331                 inputblock.cn.push({
332                     tag :'span',
333                     cls : 'roo-input-before input-group-' +
334                         (this.before.xtype == 'Button' ? 'btn' : 'addon')  //?? what about checkboxes - that looks like a bit of a hack thought? 
335                 });
336             }
337             
338             inputblock.cn.push(input);
339             
340             if (this.after && typeof(this.after) == 'string') {
341                 inputblock.cn.push({
342                     tag :'span',
343                     cls : 'roo-input-after input-group-addon',
344                     html : this.after
345                 });
346             }
347             if (this.after && typeof(this.after) == 'object') {
348                 this.after = Roo.factory(this.after);
349                 
350                 inputblock.cn.push({
351                     tag :'span',
352                     cls : 'roo-input-after input-group-' +
353                         (this.after.xtype == 'Button' ? 'btn' : 'addon')  //?? what about checkboxes - that looks like a bit of a hack thought? 
354                 });
355             }
356             
357             if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
358                 inputblock.cls += ' has-feedback';
359                 inputblock.cn.push(feedback);
360             }
361         };
362         
363         if (align ==='left' && this.fieldLabel.length) {
364                 
365                 cfg.cn = [
366                     
367                     {
368                         tag: 'label',
369                         'for' :  id,
370                         cls : 'control-label col-sm-' + this.labelWidth,
371                         html : this.fieldLabel
372                         
373                     },
374                     {
375                         cls : "col-sm-" + (12 - this.labelWidth), 
376                         cn: [
377                             inputblock
378                         ]
379                     }
380                     
381                 ];
382         } else if ( this.fieldLabel.length) {
383                 
384                  cfg.cn = [
385                    
386                     {
387                         tag: 'label',
388                         //cls : 'input-group-addon',
389                         html : this.fieldLabel
390                         
391                     },
392                     
393                     inputblock
394                     
395                 ];
396
397         } else {
398             
399                 cfg.cn = [
400                     
401                         inputblock
402                     
403                 ];
404                 
405                 
406         };
407         
408         if (this.parentType === 'Navbar' &&  this.parent().bar) {
409            cfg.cls += ' navbar-form';
410         }
411         
412         return cfg;
413         
414     },
415     /**
416      * return the real input element.
417      */
418     inputEl: function ()
419     {
420         return this.el.select('input.form-control',true).first();
421     },
422     
423     tooltipEl : function()
424     {
425         return this.inputEl();
426     },
427     
428     setDisabled : function(v)
429     {
430         var i  = this.inputEl().dom;
431         if (!v) {
432             i.removeAttribute('disabled');
433             return;
434             
435         }
436         i.setAttribute('disabled','true');
437     },
438     initEvents : function()
439     {
440           
441         this.inputEl().on("keydown" , this.fireKey,  this);
442         this.inputEl().on("focus", this.onFocus,  this);
443         this.inputEl().on("blur", this.onBlur,  this);
444         
445         this.inputEl().relayEvent('keyup', this);
446  
447         // reference to original value for reset
448         this.originalValue = this.getValue();
449         //Roo.form.TextField.superclass.initEvents.call(this);
450         if(this.validationEvent == 'keyup'){
451             this.validationTask = new Roo.util.DelayedTask(this.validate, this);
452             this.inputEl().on('keyup', this.filterValidation, this);
453         }
454         else if(this.validationEvent !== false){
455             this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
456         }
457         
458         if(this.selectOnFocus){
459             this.on("focus", this.preFocus, this);
460             
461         }
462         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
463             this.inputEl().on("keypress", this.filterKeys, this);
464         }
465        /* if(this.grow){
466             this.el.on("keyup", this.onKeyUp,  this, {buffer:50});
467             this.el.on("click", this.autoSize,  this);
468         }
469         */
470         if(this.inputEl().is('input[type=password]') && Roo.isSafari){
471             this.inputEl().on('keydown', this.SafariOnKeyDown, this);
472         }
473         
474         if (typeof(this.before) == 'object') {
475             this.before.render(this.el.select('.roo-input-before',true).first());
476         }
477         if (typeof(this.after) == 'object') {
478             this.after.render(this.el.select('.roo-input-after',true).first());
479         }
480         
481         
482     },
483     filterValidation : function(e){
484         if(!e.isNavKeyPress()){
485             this.validationTask.delay(this.validationDelay);
486         }
487     },
488      /**
489      * Validates the field value
490      * @return {Boolean} True if the value is valid, else false
491      */
492     validate : function(){
493         //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
494         if(this.disabled || this.validateValue(this.getRawValue())){
495             this.markValid();
496             return true;
497         }
498         
499         this.markInvalid();
500         return false;
501     },
502     
503     
504     /**
505      * Validates a value according to the field's validation rules and marks the field as invalid
506      * if the validation fails
507      * @param {Mixed} value The value to validate
508      * @return {Boolean} True if the value is valid, else false
509      */
510     validateValue : function(value){
511         if(value.length < 1)  { // if it's blank
512             if(this.allowBlank){
513                 return true;
514             }
515             return false;
516         }
517         
518         if(value.length < this.minLength){
519             return false;
520         }
521         if(value.length > this.maxLength){
522             return false;
523         }
524         if(this.vtype){
525             var vt = Roo.form.VTypes;
526             if(!vt[this.vtype](value, this)){
527                 return false;
528             }
529         }
530         if(typeof this.validator == "function"){
531             var msg = this.validator(value);
532             if(msg !== true){
533                 return false;
534             }
535         }
536         
537         if(this.regex && !this.regex.test(value)){
538             return false;
539         }
540         
541         return true;
542     },
543
544     
545     
546      // private
547     fireKey : function(e){
548         //Roo.log('field ' + e.getKey());
549         if(e.isNavKeyPress()){
550             this.fireEvent("specialkey", this, e);
551         }
552     },
553     focus : function (selectText){
554         if(this.rendered){
555             this.inputEl().focus();
556             if(selectText === true){
557                 this.inputEl().dom.select();
558             }
559         }
560         return this;
561     } ,
562     
563     onFocus : function(){
564         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
565            // this.el.addClass(this.focusClass);
566         }
567         if(!this.hasFocus){
568             this.hasFocus = true;
569             this.startValue = this.getValue();
570             this.fireEvent("focus", this);
571         }
572     },
573     
574     beforeBlur : Roo.emptyFn,
575
576     
577     // private
578     onBlur : function(){
579         this.beforeBlur();
580         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
581             //this.el.removeClass(this.focusClass);
582         }
583         this.hasFocus = false;
584         if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
585             this.validate();
586         }
587         var v = this.getValue();
588         if(String(v) !== String(this.startValue)){
589             this.fireEvent('change', this, v, this.startValue);
590         }
591         this.fireEvent("blur", this);
592     },
593     
594     /**
595      * Resets the current field value to the originally loaded value and clears any validation messages
596      */
597     reset : function(){
598         this.setValue(this.originalValue);
599         this.validate();
600     },
601      /**
602      * Returns the name of the field
603      * @return {Mixed} name The name field
604      */
605     getName: function(){
606         return this.name;
607     },
608      /**
609      * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
610      * @return {Mixed} value The field value
611      */
612     getValue : function(){
613         
614         var v = this.inputEl().getValue();
615         
616         return v;
617     },
618     /**
619      * Returns the raw data value which may or may not be a valid, defined value.  To return a normalized value see {@link #getValue}.
620      * @return {Mixed} value The field value
621      */
622     getRawValue : function(){
623         var v = this.inputEl().getValue();
624         
625         return v;
626     },
627     
628     /**
629      * Sets the underlying DOM field's value directly, bypassing validation.  To set the value with validation see {@link #setValue}.
630      * @param {Mixed} value The value to set
631      */
632     setRawValue : function(v){
633         return this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
634     },
635     
636     selectText : function(start, end){
637         var v = this.getRawValue();
638         if(v.length > 0){
639             start = start === undefined ? 0 : start;
640             end = end === undefined ? v.length : end;
641             var d = this.inputEl().dom;
642             if(d.setSelectionRange){
643                 d.setSelectionRange(start, end);
644             }else if(d.createTextRange){
645                 var range = d.createTextRange();
646                 range.moveStart("character", start);
647                 range.moveEnd("character", v.length-end);
648                 range.select();
649             }
650         }
651     },
652     
653     /**
654      * Sets a data value into the field and validates it.  To set the value directly without validation see {@link #setRawValue}.
655      * @param {Mixed} value The value to set
656      */
657     setValue : function(v){
658         this.value = v;
659         if(this.rendered){
660             this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
661             this.validate();
662         }
663     },
664     
665     /*
666     processValue : function(value){
667         if(this.stripCharsRe){
668             var newValue = value.replace(this.stripCharsRe, '');
669             if(newValue !== value){
670                 this.setRawValue(newValue);
671                 return newValue;
672             }
673         }
674         return value;
675     },
676   */
677     preFocus : function(){
678         
679         if(this.selectOnFocus){
680             this.inputEl().dom.select();
681         }
682     },
683     filterKeys : function(e){
684         var k = e.getKey();
685         if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
686             return;
687         }
688         var c = e.getCharCode(), cc = String.fromCharCode(c);
689         if(Roo.isIE && (e.isSpecialKey() || !cc)){
690             return;
691         }
692         if(!this.maskRe.test(cc)){
693             e.stopEvent();
694         }
695     },
696      /**
697      * Clear any invalid styles/messages for this field
698      */
699     clearInvalid : function(){
700         
701         if(!this.el || this.preventMark){ // not rendered
702             return;
703         }
704         this.el.removeClass(this.invalidClass);
705         
706         if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
707             
708             var feedback = this.el.select('.form-control-feedback', true).first();
709             
710             if(feedback){
711                 this.el.select('.form-control-feedback', true).first().removeClass(this.invalidFeedbackClass);
712             }
713             
714         }
715         
716         this.fireEvent('valid', this);
717     },
718     
719      /**
720      * Mark this field as valid
721      */
722     markValid : function()
723     {
724         if(!this.el  || this.preventMark){ // not rendered
725             return;
726         }
727         
728         this.el.removeClass([this.invalidClass, this.validClass]);
729         
730         var feedback = this.el.select('.form-control-feedback', true).first();
731             
732         if(feedback){
733             this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
734         }
735
736         if(this.disabled || this.allowBlank){
737             return;
738         }
739         
740         var formGroup = this.el.findParent('.form-group', false, true);
741         
742         if(formGroup){
743             
744             var label = formGroup.select('label', true).first();
745             var icon = formGroup.select('i.fa-star', true).first();
746             
747             if(label && icon){
748                 icon.remove();
749             }
750         }
751         
752         this.el.addClass(this.validClass);
753         
754         if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && (this.getValue().length || this.forceFeedback)){
755             
756             var feedback = this.el.select('.form-control-feedback', true).first();
757             
758             if(feedback){
759                 this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
760                 this.el.select('.form-control-feedback', true).first().addClass([this.validFeedbackClass]);
761             }
762             
763         }
764         
765         this.fireEvent('valid', this);
766     },
767     
768      /**
769      * Mark this field as invalid
770      * @param {String} msg The validation message
771      */
772     markInvalid : function(msg)
773     {
774         if(!this.el  || this.preventMark){ // not rendered
775             return;
776         }
777         
778         this.el.removeClass([this.invalidClass, this.validClass]);
779         
780         var feedback = this.el.select('.form-control-feedback', true).first();
781             
782         if(feedback){
783             this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
784         }
785
786         if(this.disabled || this.allowBlank){
787             return;
788         }
789         
790         var formGroup = this.el.findParent('.form-group', false, true);
791         
792         if(formGroup){
793             var label = formGroup.select('label', true).first();
794             var icon = formGroup.select('i.fa-star', true).first();
795
796             if(!this.getValue().length && label && !icon){
797                 this.el.findParent('.form-group', false, true).createChild({
798                     tag : 'i',
799                     cls : 'text-danger fa fa-lg fa-star',
800                     tooltip : 'This field is required',
801                     style : 'margin-right:5px;'
802                 }, label, true);
803             }
804         }
805         
806         
807         this.el.addClass(this.invalidClass);
808         
809         if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank){
810             
811             var feedback = this.el.select('.form-control-feedback', true).first();
812             
813             if(feedback){
814                 this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
815                 
816                 if(this.getValue().length || this.forceFeedback){
817                     this.el.select('.form-control-feedback', true).first().addClass([this.invalidFeedbackClass]);
818                 }
819                 
820             }
821             
822         }
823         
824         this.fireEvent('invalid', this, msg);
825     },
826     // private
827     SafariOnKeyDown : function(event)
828     {
829         // this is a workaround for a password hang bug on chrome/ webkit.
830         
831         var isSelectAll = false;
832         
833         if(this.inputEl().dom.selectionEnd > 0){
834             isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
835         }
836         if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
837             event.preventDefault();
838             this.setValue('');
839             return;
840         }
841         
842         if(isSelectAll  && event.getCharCode() > 31){ // not backspace and delete key
843             
844             event.preventDefault();
845             // this is very hacky as keydown always get's upper case.
846             //
847             var cc = String.fromCharCode(event.getCharCode());
848             this.setValue( event.shiftKey ?  cc : cc.toLowerCase());
849             
850         }
851     },
852     adjustWidth : function(tag, w){
853         tag = tag.toLowerCase();
854         if(typeof w == 'number' && Roo.isStrict && !Roo.isSafari){
855             if(Roo.isIE && (tag == 'input' || tag == 'textarea')){
856                 if(tag == 'input'){
857                     return w + 2;
858                 }
859                 if(tag == 'textarea'){
860                     return w-2;
861                 }
862             }else if(Roo.isOpera){
863                 if(tag == 'input'){
864                     return w + 2;
865                 }
866                 if(tag == 'textarea'){
867                     return w-2;
868                 }
869             }
870         }
871         return w;
872     }
873     
874 });
875
876