Fix #7418 - radio button set value
[roojs1] / Roo / form / BasicForm.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11  
12 /**
13  * @class Roo.form.BasicForm
14  * @extends Roo.util.Observable
15  * Supplies the functionality to do "actions" on forms and initialize Roo.form.Field types on existing markup.
16  * @constructor
17  * @param {String/HTMLElement/Roo.Element} el The form element or its id
18  * @param {Object} config Configuration options
19  */
20 Roo.form.BasicForm = function(el, config){
21     this.allItems = [];
22     this.childForms = [];
23     Roo.apply(this, config);
24     /*
25      * The Roo.form.Field items in this form.
26      * @type MixedCollection
27      */
28      
29      
30     this.items = new Roo.util.MixedCollection(false, function(o){
31         return o.id || (o.id = Roo.id());
32     });
33     this.addEvents({
34         /**
35          * @event beforeaction
36          * Fires before any action is performed. Return false to cancel the action.
37          * @param {Form} this
38          * @param {Action} action The action to be performed
39          */
40         beforeaction: true,
41         /**
42          * @event actionfailed
43          * Fires when an action fails.
44          * @param {Form} this
45          * @param {Action} action The action that failed
46          */
47         actionfailed : true,
48         /**
49          * @event actioncomplete
50          * Fires when an action is completed.
51          * @param {Form} this
52          * @param {Action} action The action that completed
53          */
54         actioncomplete : true
55     });
56     if(el){
57         this.initEl(el);
58     }
59     Roo.form.BasicForm.superclass.constructor.call(this);
60     
61     Roo.form.BasicForm.popover.apply();
62 };
63
64 Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
65     /**
66      * @cfg {String} method
67      * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
68      */
69     /**
70      * @cfg {DataReader} reader
71      * An Roo.data.DataReader (e.g. {@link Roo.data.XmlReader}) to be used to read data when executing "load" actions.
72      * This is optional as there is built-in support for processing JSON.
73      */
74     /**
75      * @cfg {DataReader} errorReader
76      * An Roo.data.DataReader (e.g. {@link Roo.data.XmlReader}) to be used to read data when reading validation errors on "submit" actions.
77      * This is completely optional as there is built-in support for processing JSON.
78      */
79     /**
80      * @cfg {String} url
81      * The URL to use for form actions if one isn't supplied in the action options.
82      */
83     /**
84      * @cfg {Boolean} fileUpload
85      * Set to true if this form is a file upload.
86      */
87      
88     /**
89      * @cfg {Object} baseParams
90      * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
91      */
92      /**
93      
94     /**
95      * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
96      */
97     timeout: 30,
98
99     // private
100     activeAction : null,
101
102     /**
103      * @cfg {Boolean} trackResetOnLoad If set to true, form.reset() resets to the last loaded
104      * or setValues() data instead of when the form was first created.
105      */
106     trackResetOnLoad : false,
107     
108     
109     /**
110      * childForms - used for multi-tab forms
111      * @type {Array}
112      */
113     childForms : false,
114     
115     /**
116      * allItems - full list of fields.
117      * @type {Array}
118      */
119     allItems : false,
120     
121     /**
122      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
123      * element by passing it or its id or mask the form itself by passing in true.
124      * @type Mixed
125      */
126     waitMsgTarget : false,
127     
128     /**
129      * @type Boolean
130      */
131     disableMask : false,
132     
133     /**
134      * @cfg {Boolean} errorMask (true|false) default false
135      */
136     errorMask : false,
137     
138     /**
139      * @cfg {Number} maskOffset Default 100
140      */
141     maskOffset : 100,
142
143     // private
144     initEl : function(el){
145         this.el = Roo.get(el);
146         this.id = this.el.id || Roo.id();
147         this.el.on('submit', this.onSubmit, this);
148         this.el.addClass('x-form');
149     },
150
151     // private
152     onSubmit : function(e){
153         e.stopEvent();
154     },
155
156     /**
157      * Returns true if client-side validation on the form is successful.
158      * @return Boolean
159      */
160     isValid : function(){
161         var valid = true;
162         var target = false;
163         this.items.each(function(f){
164             if(f.validate()){
165                 return;
166             }
167             
168             valid = false;
169                 
170             if(!target && f.el.isVisible(true)){
171                 target = f;
172             }
173         });
174         
175         if(this.errorMask && !valid){
176             Roo.form.BasicForm.popover.mask(this, target);
177         }
178         
179         return valid;
180     },
181     /**
182      * Returns array of invalid form fields.
183      * @return Array
184      */
185     
186     invalidFields : function()
187     {
188         var ret = [];
189         this.items.each(function(f){
190             if(f.validate()){
191                 return;
192             }
193             ret.push(f);
194             
195         });
196         
197         return ret;
198     },
199     
200     
201     /**
202      * DEPRICATED Returns true if any fields in this form have changed since their original load. 
203      * @return Boolean
204      */
205     isDirty : function(){
206         var dirty = false;
207         this.items.each(function(f){
208            if(f.isDirty()){
209                dirty = true;
210                return false;
211            }
212         });
213         return dirty;
214     },
215     
216     /**
217      * Returns true if any fields in this form have changed since their original load. (New version)
218      * @return Boolean
219      */
220     
221     hasChanged : function()
222     {
223         var dirty = false;
224         this.items.each(function(f){
225            if(f.hasChanged()){
226                dirty = true;
227                return false;
228            }
229         });
230         return dirty;
231         
232     },
233     /**
234      * Resets all hasChanged to 'false' -
235      * The old 'isDirty' used 'original value..' however this breaks reset() and a few other things.
236      * So hasChanged storage is only to be used for this purpose
237      * @return Boolean
238      */
239     resetHasChanged : function()
240     {
241         this.items.each(function(f){
242            f.resetHasChanged();
243         });
244         
245     },
246     
247     
248     /**
249      * Performs a predefined action (submit or load) or custom actions you define on this form.
250      * @param {String} actionName The name of the action type
251      * @param {Object} options (optional) The options to pass to the action.  All of the config options listed
252      * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
253      * accept other config options):
254      * <pre>
255 Property          Type             Description
256 ----------------  ---------------  ----------------------------------------------------------------------------------
257 url               String           The url for the action (defaults to the form's url)
258 method            String           The form method to use (defaults to the form's method, or POST if not defined)
259 params            String/Object    The params to pass (defaults to the form's baseParams, or none if not defined)
260 clientValidation  Boolean          Applies to submit only.  Pass true to call form.isValid() prior to posting to
261                                    validate the form on the client (defaults to false)
262      * </pre>
263      * @return {BasicForm} this
264      */
265     doAction : function(action, options){
266         if(typeof action == 'string'){
267             action = new Roo.form.Action.ACTION_TYPES[action](this, options);
268         }
269         if(this.fireEvent('beforeaction', this, action) !== false){
270             this.beforeAction(action);
271             action.run.defer(100, action);
272         }
273         return this;
274     },
275
276     /**
277      * Shortcut to do a submit action.
278      * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
279      * @return {BasicForm} this
280      */
281     submit : function(options){
282         this.doAction('submit', options);
283         return this;
284     },
285
286     /**
287      * Shortcut to do a load action.
288      * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
289      * @return {BasicForm} this
290      */
291     load : function(options){
292         this.doAction('load', options);
293         return this;
294     },
295
296     /**
297      * Persists the values in this form into the passed Roo.data.Record object in a beginEdit/endEdit block.
298      * @param {Record} record The record to edit
299      * @return {BasicForm} this
300      */
301     updateRecord : function(record){
302         record.beginEdit();
303         var fs = record.fields;
304         fs.each(function(f){
305             var field = this.findField(f.name);
306             if(field){
307                 record.set(f.name, field.getValue());
308             }
309         }, this);
310         record.endEdit();
311         return this;
312     },
313
314     /**
315      * Loads an Roo.data.Record into this form.
316      * @param {Record} record The record to load
317      * @return {BasicForm} this
318      */
319     loadRecord : function(record){
320         this.setValues(record.data);
321         return this;
322     },
323
324     // private
325     beforeAction : function(action){
326         var o = action.options;
327         
328         if(!this.disableMask) {
329             if(this.waitMsgTarget === true){
330                 this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
331             }else if(this.waitMsgTarget){
332                 this.waitMsgTarget = Roo.get(this.waitMsgTarget);
333                 this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
334             }else {
335                 Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
336             }
337         }
338         
339          
340     },
341
342     // private
343     afterAction : function(action, success){
344         this.activeAction = null;
345         var o = action.options;
346         
347         if(!this.disableMask) {
348             if(this.waitMsgTarget === true){
349                 this.el.unmask();
350             }else if(this.waitMsgTarget){
351                 this.waitMsgTarget.unmask();
352             }else{
353                 Roo.MessageBox.updateProgress(1);
354                 Roo.MessageBox.hide();
355             }
356         }
357         
358         if(success){
359             if(o.reset){
360                 this.reset();
361             }
362             Roo.callback(o.success, o.scope, [this, action]);
363             this.fireEvent('actioncomplete', this, action);
364             
365         }else{
366             
367             // failure condition..
368             // we have a scenario where updates need confirming.
369             // eg. if a locking scenario exists..
370             // we look for { errors : { needs_confirm : true }} in the response.
371             if (
372                 (typeof(action.result) != 'undefined')  &&
373                 (typeof(action.result.errors) != 'undefined')  &&
374                 (typeof(action.result.errors.needs_confirm) != 'undefined')
375            ){
376                 var _t = this;
377                 Roo.MessageBox.confirm(
378                     "Change requires confirmation",
379                     action.result.errorMsg,
380                     function(r) {
381                         if (r != 'yes') {
382                             return;
383                         }
384                         _t.doAction('submit', { params :  { _submit_confirmed : 1 } }  );
385                     }
386                     
387                 );
388                 
389                 
390                 
391                 return;
392             }
393             
394             Roo.callback(o.failure, o.scope, [this, action]);
395             // show an error message if no failed handler is set..
396             if (!this.hasListener('actionfailed')) {
397                 Roo.MessageBox.alert("Error",
398                     (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
399                         action.result.errorMsg :
400                         "Saving Failed, please check your entries or try again"
401                 );
402             }
403             
404             this.fireEvent('actionfailed', this, action);
405         }
406         
407     },
408
409     /**
410      * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
411      * @param {String} id The value to search for
412      * @return Field
413      */
414     findField : function(id){
415         var field = this.items.get(id);
416         if(!field){
417             this.items.each(function(f){
418                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
419                     field = f;
420                     return false;
421                 }
422             });
423         }
424         return field || null;
425     },
426
427     /**
428      * Add a secondary form to this one, 
429      * Used to provide tabbed forms. One form is primary, with hidden values 
430      * which mirror the elements from the other forms.
431      * 
432      * @param {Roo.form.Form} form to add.
433      * 
434      */
435     addForm : function(form)
436     {
437        
438         if (this.childForms.indexOf(form) > -1) {
439             // already added..
440             return;
441         }
442         this.childForms.push(form);
443         var n = '';
444         Roo.each(form.allItems, function (fe) {
445             
446             n = typeof(fe.getName) == 'undefined' ? fe.name : fe.getName();
447             if (this.findField(n)) { // already added..
448                 return;
449             }
450             var add = new Roo.form.Hidden({
451                 name : n
452             });
453             add.render(this.el);
454             
455             this.add( add );
456         }, this);
457         
458     },
459     /**
460      * Mark fields in this form invalid in bulk.
461      * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
462      * @return {BasicForm} this
463      */
464     markInvalid : function(errors){
465         if(errors instanceof Array){
466             for(var i = 0, len = errors.length; i < len; i++){
467                 var fieldError = errors[i];
468                 var f = this.findField(fieldError.id);
469                 if(f){
470                     f.markInvalid(fieldError.msg);
471                 }
472             }
473         }else{
474             var field, id;
475             for(id in errors){
476                 if(typeof errors[id] != 'function' && (field = this.findField(id))){
477                     field.markInvalid(errors[id]);
478                 }
479             }
480         }
481         Roo.each(this.childForms || [], function (f) {
482             f.markInvalid(errors);
483         });
484         
485         return this;
486     },
487
488     /**
489      * Set values for fields in this form in bulk.
490      * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
491      * @return {BasicForm} this
492      */
493     setValues : function(values){
494         if(values instanceof Array){ // array of objects
495             for(var i = 0, len = values.length; i < len; i++){
496                 var v = values[i];
497                 var f = this.findField(v.id);
498                 if(f){
499                     f.setValue(v.value);
500                     if(this.trackResetOnLoad){
501                         f.originalValue = f.getValue();
502                     }
503                 }
504             }
505         }else{ // object hash
506             var field, id;
507             for(id in values){
508                 if(typeof values[id] != 'function' && (field = this.findField(id))){
509                     
510                     
511                     
512                     
513                     if (field.setFromData && 
514                         field.valueField && 
515                         field.displayField &&
516                         // combos' with local stores can 
517                         // be queried via setValue()
518                         // to set their value..
519                         (field.store && !field.store.isLocal)
520                         ) {
521                         // it's a combo
522                         var sd = { };
523                         sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
524                         sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
525                         field.setFromData(sd);
526                         
527                     } else if (field.inputType && field.inputType == 'radio') {
528                         
529                         field.setValue(values[id]);
530                     } else {
531                         field.setValue(values[id]);
532                     }
533                     
534                     
535                     if(this.trackResetOnLoad){
536                         field.originalValue = field.getValue();
537                     }
538                 }
539             }
540         }
541         this.resetHasChanged();
542         
543         
544         Roo.each(this.childForms || [], function (f) {
545             f.setValues(values);
546             f.resetHasChanged();
547         });
548                 
549         return this;
550     },
551  
552     /**
553      * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
554      * they are returned as an array.
555      * @param {Boolean} asString (def)
556      * @return {Object}
557      */
558     getValues : function(asString)
559     {
560         if (this.childForms) {
561             // copy values from the child forms
562             Roo.each(this.childForms, function (f) {
563                 this.setValues(f.getFieldValues()); // get the full set of data, as we might be copying comboboxes from external into this one.
564             }, this);
565         }
566         
567         // use formdata
568         if (typeof(FormData) != 'undefined' && asString !== true) {
569             // this relies on a 'recent' version of chrome apparently...
570             try {
571                 var fd = (new FormData(this.el.dom)).entries();
572                 var ret = {};
573                 var ent = fd.next();
574                 while (!ent.done) {
575                     ret[ent.value[0]] = ent.value[1]; // not sure how this will handle duplicates..
576                     ent = fd.next();
577                 };
578                 return ret;
579             } catch(e) {
580                 
581             }
582             
583         }
584         
585         
586         var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
587         if(asString === true){
588             return fs;
589         }
590         return Roo.urlDecode(fs);
591     },
592     
593     /**
594      * Returns the fields in this form as an object with key/value pairs. 
595      * This differs from getValues as it calls getValue on each child item, rather than using dom data.
596      * Normally this will not return readOnly data 
597      * @param {Boolean} with_readonly return readonly field data.
598      * @return {Object}
599      */
600     getFieldValues : function(with_readonly)
601     {
602         if (this.childForms) {
603             // copy values from the child forms
604             // should this call getFieldValues - probably not as we do not currently copy
605             // hidden fields when we generate..
606             Roo.each(this.childForms, function (f) {
607                 this.setValues(f.getFieldValues());
608             }, this);
609         }
610         
611         var ret = {};
612         this.items.each(function(f){
613             
614             if (f.readOnly && with_readonly !== true) {
615                 return; // skip read only values. - this is in theory to stop 'old' values being copied over new ones
616                         // if a subform contains a copy of them.
617                         // if you have subforms with the same editable data, you will need to copy the data back
618                         // and forth.
619             }
620             
621             if (!f.getName()) {
622                 return;
623             }
624             var v = f.getValue();
625             if (f.inputType =='radio') {
626                 if (typeof(ret[f.getName()]) == 'undefined') {
627                     ret[f.getName()] = ''; // empty..
628                 }
629                 
630                 if (!f.el.dom.checked) {
631                     return;
632                     
633                 }
634                 v = f.el.dom.value;
635                 
636             }
637             
638             // not sure if this supported any more..
639             if ((typeof(v) == 'object') && f.getRawValue) {
640                 v = f.getRawValue() ; // dates..
641             }
642             // combo boxes where name != hiddenName...
643             if (f.name != f.getName()) {
644                 ret[f.name] = f.getRawValue();
645             }
646             ret[f.getName()] = v;
647         });
648         
649         return ret;
650     },
651
652     /**
653      * Clears all invalid messages in this form.
654      * @return {BasicForm} this
655      */
656     clearInvalid : function(){
657         this.items.each(function(f){
658            f.clearInvalid();
659         });
660         
661         Roo.each(this.childForms || [], function (f) {
662             f.clearInvalid();
663         });
664         
665         
666         return this;
667     },
668
669     /**
670      * Resets this form.
671      * @return {BasicForm} this
672      */
673     reset : function(){
674         this.items.each(function(f){
675             f.reset();
676         });
677         
678         Roo.each(this.childForms || [], function (f) {
679             f.reset();
680         });
681         this.resetHasChanged();
682         
683         return this;
684     },
685
686     /**
687      * Add Roo.form components to this form.
688      * @param {Field} field1
689      * @param {Field} field2 (optional)
690      * @param {Field} etc (optional)
691      * @return {BasicForm} this
692      */
693     add : function(){
694         this.items.addAll(Array.prototype.slice.call(arguments, 0));
695         return this;
696     },
697
698
699     /**
700      * Removes a field from the items collection (does NOT remove its markup).
701      * @param {Field} field
702      * @return {BasicForm} this
703      */
704     remove : function(field){
705         this.items.remove(field);
706         return this;
707     },
708
709     /**
710      * Looks at the fields in this form, checks them for an id attribute,
711      * and calls applyTo on the existing dom element with that id.
712      * @return {BasicForm} this
713      */
714     render : function(){
715         this.items.each(function(f){
716             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
717                 f.applyTo(f.id);
718             }
719         });
720         return this;
721     },
722
723     /**
724      * Calls {@link Ext#apply} for all fields in this form with the passed object.
725      * @param {Object} values
726      * @return {BasicForm} this
727      */
728     applyToFields : function(o){
729         this.items.each(function(f){
730            Roo.apply(f, o);
731         });
732         return this;
733     },
734
735     /**
736      * Calls {@link Ext#applyIf} for all field in this form with the passed object.
737      * @param {Object} values
738      * @return {BasicForm} this
739      */
740     applyIfToFields : function(o){
741         this.items.each(function(f){
742            Roo.applyIf(f, o);
743         });
744         return this;
745     }
746 });
747
748 // back compat
749 Roo.BasicForm = Roo.form.BasicForm;
750
751 Roo.apply(Roo.form.BasicForm, {
752     
753     popover : {
754         
755         padding : 5,
756         
757         isApplied : false,
758         
759         isMasked : false,
760         
761         form : false,
762         
763         target : false,
764         
765         intervalID : false,
766         
767         maskEl : false,
768         
769         apply : function()
770         {
771             if(this.isApplied){
772                 return;
773             }
774             
775             this.maskEl = {
776                 top : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-top-mask" }, true),
777                 left : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-left-mask" }, true),
778                 bottom : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-bottom-mask" }, true),
779                 right : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-right-mask" }, true)
780             };
781             
782             this.maskEl.top.enableDisplayMode("block");
783             this.maskEl.left.enableDisplayMode("block");
784             this.maskEl.bottom.enableDisplayMode("block");
785             this.maskEl.right.enableDisplayMode("block");
786             
787             Roo.get(document.body).on('click', function(){
788                 this.unmask();
789             }, this);
790             
791             Roo.get(document.body).on('touchstart', function(){
792                 this.unmask();
793             }, this);
794             
795             this.isApplied = true
796         },
797         
798         mask : function(form, target)
799         {
800             this.form = form;
801             
802             this.target = target;
803             
804             if(!this.form.errorMask || !target.el){
805                 return;
806             }
807             
808             var scrollable = this.target.el.findScrollableParent() || this.target.el.findParent('div.x-layout-active-content', 100, true) || Roo.get(document.body);
809             
810             var ot = this.target.el.calcOffsetsTo(scrollable);
811             
812             var scrollTo = ot[1] - this.form.maskOffset;
813             
814             scrollTo = Math.min(scrollTo, scrollable.dom.scrollHeight);
815             
816             scrollable.scrollTo('top', scrollTo);
817             
818             var el = this.target.wrap || this.target.el;
819             
820             var box = el.getBox();
821             
822             this.maskEl.top.setStyle('position', 'absolute');
823             this.maskEl.top.setStyle('z-index', 10000);
824             this.maskEl.top.setSize(Roo.lib.Dom.getDocumentWidth(), box.y - this.padding);
825             this.maskEl.top.setLeft(0);
826             this.maskEl.top.setTop(0);
827             this.maskEl.top.show();
828             
829             this.maskEl.left.setStyle('position', 'absolute');
830             this.maskEl.left.setStyle('z-index', 10000);
831             this.maskEl.left.setSize(box.x - this.padding, box.height + this.padding * 2);
832             this.maskEl.left.setLeft(0);
833             this.maskEl.left.setTop(box.y - this.padding);
834             this.maskEl.left.show();
835
836             this.maskEl.bottom.setStyle('position', 'absolute');
837             this.maskEl.bottom.setStyle('z-index', 10000);
838             this.maskEl.bottom.setSize(Roo.lib.Dom.getDocumentWidth(), Roo.lib.Dom.getDocumentHeight() - box.bottom - this.padding);
839             this.maskEl.bottom.setLeft(0);
840             this.maskEl.bottom.setTop(box.bottom + this.padding);
841             this.maskEl.bottom.show();
842
843             this.maskEl.right.setStyle('position', 'absolute');
844             this.maskEl.right.setStyle('z-index', 10000);
845             this.maskEl.right.setSize(Roo.lib.Dom.getDocumentWidth() - box.right - this.padding, box.height + this.padding * 2);
846             this.maskEl.right.setLeft(box.right + this.padding);
847             this.maskEl.right.setTop(box.y - this.padding);
848             this.maskEl.right.show();
849
850             this.intervalID = window.setInterval(function() {
851                 Roo.form.BasicForm.popover.unmask();
852             }, 10000);
853
854             window.onwheel = function(){ return false;};
855             
856             (function(){ this.isMasked = true; }).defer(500, this);
857             
858         },
859         
860         unmask : function()
861         {
862             if(!this.isApplied || !this.isMasked || !this.form || !this.target || !this.form.errorMask){
863                 return;
864             }
865             
866             this.maskEl.top.setStyle('position', 'absolute');
867             this.maskEl.top.setSize(0, 0).setXY([0, 0]);
868             this.maskEl.top.hide();
869
870             this.maskEl.left.setStyle('position', 'absolute');
871             this.maskEl.left.setSize(0, 0).setXY([0, 0]);
872             this.maskEl.left.hide();
873
874             this.maskEl.bottom.setStyle('position', 'absolute');
875             this.maskEl.bottom.setSize(0, 0).setXY([0, 0]);
876             this.maskEl.bottom.hide();
877
878             this.maskEl.right.setStyle('position', 'absolute');
879             this.maskEl.right.setSize(0, 0).setXY([0, 0]);
880             this.maskEl.right.hide();
881             
882             window.onwheel = function(){ return true;};
883             
884             if(this.intervalID){
885                 window.clearInterval(this.intervalID);
886                 this.intervalID = false;
887             }
888             
889             this.isMasked = false;
890             
891         }
892         
893     }
894     
895 });