sync
[roojs1] / Roo / bootstrap / PhoneInput.js
1 /*
2  * - LGPL
3  *
4  * element
5  * 
6  */
7
8 /**
9  * @class Roo.bootstrap.PhoneInput
10  * @extends Roo.bootstrap.TriggerField
11  * Bootstrap PhoneInput class
12  * 
13  * @constructor
14  * Create a new PhoneInput
15  * @param {Object} config The config object
16 */
17
18 Roo.bootstrap.PhoneInput = function(config){
19     Roo.bootstrap.PhoneInput.superclass.constructor.call(this, config);
20     this.addEvents({
21         
22     });
23     
24     //setting global...
25     this.item = [];
26     this.tickItems = [];
27     
28     this.selectedIndex = -1;
29     if(this.mode == 'local'){
30         if(config.queryDelay === undefined){
31             this.queryDelay = 10;
32         }
33         if(config.minChars === undefined){
34             this.minChars = 0;
35         }
36     }
37 };
38
39 Roo.extend(Roo.bootstrap.PhoneInput, Roo.bootstrap.TriggerField, {
40      
41      //setting properties..
42     
43     getAutoCreate : function()
44     {   
45         var cfg = false;
46         //render
47         /*
48          * Render classic select for iso
49          */
50         
51         if(Roo.isIOS && this.useNativeIOS){
52             cfg = this.getAutoCreateNativeIOS();
53             return cfg;
54         }
55         
56         /*
57          * Touch Devices
58          */
59         
60         if(Roo.isTouch && this.mobileTouchView){
61             cfg = this.getAutoCreateTouchView();
62             return cfg;;
63         }
64         
65         /*
66          *  Normal PhoneInput
67          */
68         if(!this.tickable){
69             cfg = Roo.bootstrap.PhoneInput.superclass.getAutoCreate.call(this);
70             return cfg;
71         }
72         
73         /*
74          *  PhoneInput with tickable selections
75          */
76              
77         var align = this.labelAlign || this.parentLabelAlign();
78         
79         cfg = {
80             cls : 'form-group roo-PhoneInput-tickable' //input-group
81         };
82         
83         var btn_text_select = '';
84         var btn_text_done = '';
85         var btn_text_cancel = '';
86         
87         if (this.btn_text_show) {
88             btn_text_select = 'Select';
89             btn_text_done = 'Done';
90             btn_text_cancel = 'Cancel'; 
91         }
92         
93         var buttons = {
94             tag : 'div',
95             cls : 'tickable-buttons',
96             cn : [
97                 {
98                     tag : 'button',
99                     type : 'button',
100                     cls : 'btn btn-link btn-edit pull-' + this.btnPosition,
101                     //html : this.triggerText
102                     html: btn_text_select
103                 },
104                 {
105                     tag : 'button',
106                     type : 'button',
107                     name : 'ok',
108                     cls : 'btn btn-link btn-ok pull-' + this.btnPosition,
109                     //html : 'Done'
110                     html: btn_text_done
111                 },
112                 {
113                     tag : 'button',
114                     type : 'button',
115                     name : 'cancel',
116                     cls : 'btn btn-link btn-cancel pull-' + this.btnPosition,
117                     //html : 'Cancel'
118                     html: btn_text_cancel
119                 }
120             ]
121         };
122         
123         if(this.editable){
124             buttons.cn.unshift({
125                 tag: 'input',
126                 cls: 'roo-select2-search-field-input'
127             });
128         }
129         
130         var _this = this;
131         
132         Roo.each(buttons.cn, function(c){
133             if (_this.size) {
134                 c.cls += ' btn-' + _this.size;
135             }
136
137             if (_this.disabled) {
138                 c.disabled = true;
139             }
140         });
141         
142         var box = {
143             tag: 'div',
144             cn: [
145                 {
146                     tag: 'input',
147                     type : 'hidden',
148                     cls: 'form-hidden-field'
149                 },
150                 {
151                     tag: 'ul',
152                     cls: 'roo-select2-choices',
153                     cn:[
154                         {
155                             tag: 'li',
156                             cls: 'roo-select2-search-field',
157                             cn: [
158                                 buttons
159                             ]
160                         }
161                     ]
162                 }
163             ]
164         };
165         
166         var PhoneInput = {
167             cls: 'roo-select2-container input-group roo-select2-container-multi',
168             cn: [
169                 box
170 //                {
171 //                    tag: 'ul',
172 //                    cls: 'typeahead typeahead-long dropdown-menu',
173 //                    style: 'display:none; max-height:' + this.maxHeight + 'px;'
174 //                }
175             ]
176         };
177         
178         if(this.hasFeedback && !this.allowBlank){
179             
180             var feedback = {
181                 tag: 'span',
182                 cls: 'glyphicon form-control-feedback'
183             };
184
185             PhoneInput.cn.push(feedback);
186         }
187         
188         
189         if (align ==='left' && this.fieldLabel.length) {
190             
191             cfg.cls += ' roo-form-group-label-left';
192             
193             cfg.cn = [
194                 {
195                     tag : 'i',
196                     cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
197                     tooltip : 'This field is required'
198                 },
199                 {
200                     tag: 'label',
201                     'for' :  id,
202                     cls : 'control-label',
203                     html : this.fieldLabel
204
205                 },
206                 {
207                     cls : "", 
208                     cn: [
209                         PhoneInput
210                     ]
211                 }
212
213             ];
214             
215             var labelCfg = cfg.cn[1];
216             var contentCfg = cfg.cn[2];
217             
218
219             if(this.indicatorpos == 'right'){
220                 
221                 cfg.cn = [
222                     {
223                         tag: 'label',
224                         'for' :  id,
225                         cls : 'control-label',
226                         cn : [
227                             {
228                                 tag : 'span',
229                                 html : this.fieldLabel
230                             },
231                             {
232                                 tag : 'i',
233                                 cls : 'roo-required-indicator right-indicator text-danger fa fa-lg fa-star',
234                                 tooltip : 'This field is required'
235                             }
236                         ]
237                     },
238                     {
239                         cls : "",
240                         cn: [
241                             PhoneInput
242                         ]
243                     }
244
245                 ];
246                 
247                 
248                 
249                 labelCfg = cfg.cn[0];
250                 contentCfg = cfg.cn[1];
251             
252             }
253             
254             if(this.labelWidth > 12){
255                 labelCfg.style = "width: " + this.labelWidth + 'px';
256             }
257             
258             if(this.labelWidth < 13 && this.labelmd == 0){
259                 this.labelmd = this.labelWidth;
260             }
261             
262             if(this.labellg > 0){
263                 labelCfg.cls += ' col-lg-' + this.labellg;
264                 contentCfg.cls += ' col-lg-' + (12 - this.labellg);
265             }
266             
267             if(this.labelmd > 0){
268                 labelCfg.cls += ' col-md-' + this.labelmd;
269                 contentCfg.cls += ' col-md-' + (12 - this.labelmd);
270             }
271             
272             if(this.labelsm > 0){
273                 labelCfg.cls += ' col-sm-' + this.labelsm;
274                 contentCfg.cls += ' col-sm-' + (12 - this.labelsm);
275             }
276             
277             if(this.labelxs > 0){
278                 labelCfg.cls += ' col-xs-' + this.labelxs;
279                 contentCfg.cls += ' col-xs-' + (12 - this.labelxs);
280             }
281                 
282                 
283         } else if ( this.fieldLabel.length) {
284                  cfg.cn = [
285                     {
286                         tag : 'i',
287                         cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
288                         tooltip : 'This field is required'
289                     },
290                     {
291                         tag: 'label',
292                         //cls : 'input-group-addon',
293                         html : this.fieldLabel
294                     },
295                     PhoneInput
296                 ];
297                 
298                 if(this.indicatorpos == 'right'){
299                     cfg.cn = [
300                         {
301                             tag: 'label',
302                             //cls : 'input-group-addon',
303                             html : this.fieldLabel
304                         },
305                         {
306                             tag : 'i',
307                             cls : 'roo-required-indicator right-indicator text-danger fa fa-lg fa-star',
308                             tooltip : 'This field is required'
309                         },
310                         PhoneInput
311                     ];
312                     
313                 }
314
315         } else {
316             
317                 cfg = PhoneInput
318                      
319                 
320         }
321          
322         var settings=this;
323         ['xs','sm','md','lg'].map(function(size){
324             if (settings[size]) {
325                 cfg.cls += ' col-' + size + '-' + settings[size];
326             }
327         });
328         
329         return cfg;
330         
331     },
332     
333     _initEventsCalled : false,
334     
335     // private
336     initEvents: function()
337     {   
338         if (this._initEventsCalled) { // as we call render... prevent looping...
339             return;
340         }
341         this._initEventsCalled = true;
342         
343         if (!this.store) {
344             throw "can not find store for combo";
345         }
346         
347         this.store = Roo.factory(this.store, Roo.data);
348         this.store.parent = this;
349         
350         // if we are building from html. then this element is so complex, that we can not really
351         // use the rendered HTML.
352         // so we have to trash and replace the previous code.
353         if (Roo.XComponent.build_from_html) {
354             
355             // remove this element....
356             var e = this.el.dom, k=0;
357             while (e ) { e = e.previousSibling;  ++k;}
358
359             this.el.remove();
360             
361             this.el=false;
362             this.rendered = false;
363             
364             this.render(this.parent().getChildContainer(true), k);
365             
366             
367             
368         }
369         
370         if(Roo.isIOS && this.useNativeIOS){
371             this.initIOSView();
372             return;
373         }
374         
375         /*
376          * Touch Devices
377          */
378         
379         if(Roo.isTouch && this.mobileTouchView){
380             this.initTouchView();
381             return;
382         }
383         
384         if(this.tickable){
385             this.initTickableEvents();
386             return;
387         }
388         
389         Roo.bootstrap.PhoneInput.superclass.initEvents.call(this);
390         
391         if(this.hiddenName){
392             
393             this.hiddenField = this.el.select('input.form-hidden-field',true).first();
394             
395             this.hiddenField.dom.value =
396                 this.hiddenValue !== undefined ? this.hiddenValue :
397                 this.value !== undefined ? this.value : '';
398
399             // prevent input submission
400             this.el.dom.removeAttribute('name');
401             this.hiddenField.dom.setAttribute('name', this.hiddenName);
402              
403              
404         }
405         //if(Roo.isGecko){
406         //    this.el.dom.setAttribute('autocomplete', 'off');
407         //}
408         
409         var cls = 'x-combo-list';
410         
411         //this.list = new Roo.Layer({
412         //    shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
413         //});
414         
415         var _this = this;
416         
417         (function(){
418             var lw = _this.listWidth || Math.max(_this.inputEl().getWidth(), _this.minListWidth);
419             _this.list.setWidth(lw);
420         }).defer(100);
421         
422         this.list.on('mouseover', this.onViewOver, this);
423         this.list.on('mousemove', this.onViewMove, this);
424         
425         this.list.on('scroll', this.onViewScroll, this);
426         
427         /*
428         this.list.swallowEvent('mousewheel');
429         this.assetHeight = 0;
430
431         if(this.title){
432             this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
433             this.assetHeight += this.header.getHeight();
434         }
435
436         this.innerList = this.list.createChild({cls:cls+'-inner'});
437         this.innerList.on('mouseover', this.onViewOver, this);
438         this.innerList.on('mousemove', this.onViewMove, this);
439         this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
440         
441         if(this.allowBlank && !this.pageSize && !this.disableClear){
442             this.footer = this.list.createChild({cls:cls+'-ft'});
443             this.pageTb = new Roo.Toolbar(this.footer);
444            
445         }
446         if(this.pageSize){
447             this.footer = this.list.createChild({cls:cls+'-ft'});
448             this.pageTb = new Roo.PagingToolbar(this.footer, this.store,
449                     {pageSize: this.pageSize});
450             
451         }
452         
453         if (this.pageTb && this.allowBlank && !this.disableClear) {
454             var _this = this;
455             this.pageTb.add(new Roo.Toolbar.Fill(), {
456                 cls: 'x-btn-icon x-btn-clear',
457                 text: '&#160;',
458                 handler: function()
459                 {
460                     _this.collapse();
461                     _this.clearValue();
462                     _this.onSelect(false, -1);
463                 }
464             });
465         }
466         if (this.footer) {
467             this.assetHeight += this.footer.getHeight();
468         }
469         */
470             
471         if(!this.tpl){
472             this.tpl = '<li><a href="#">{' + this.displayField + '}</a></li>';
473         }
474
475         this.view = new Roo.View(this.list, this.tpl, {
476             singleSelect:true, store: this.store, selectedClass: this.selectedClass
477         });
478         //this.view.wrapEl.setDisplayed(false);
479         this.view.on('click', this.onViewClick, this);
480         
481         
482         this.store.on('beforeload', this.onBeforeLoad, this);
483         this.store.on('load', this.onLoad, this);
484         this.store.on('loadexception', this.onLoadException, this);
485         /*
486         if(this.resizable){
487             this.resizer = new Roo.Resizable(this.list,  {
488                pinned:true, handles:'se'
489             });
490             this.resizer.on('resize', function(r, w, h){
491                 this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
492                 this.listWidth = w;
493                 this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
494                 this.restrictHeight();
495             }, this);
496             this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
497         }
498         */
499         if(!this.editable){
500             this.editable = true;
501             this.setEditable(false);
502         }
503         
504         /*
505         
506         if (typeof(this.events.add.listeners) != 'undefined') {
507             
508             this.addicon = this.wrap.createChild(
509                 {tag: 'img', src: Roo.BLANK_IMAGE_URL, cls: 'x-form-combo-add' });  
510        
511             this.addicon.on('click', function(e) {
512                 this.fireEvent('add', this);
513             }, this);
514         }
515         if (typeof(this.events.edit.listeners) != 'undefined') {
516             
517             this.editicon = this.wrap.createChild(
518                 {tag: 'img', src: Roo.BLANK_IMAGE_URL, cls: 'x-form-combo-edit' });  
519             if (this.addicon) {
520                 this.editicon.setStyle('margin-left', '40px');
521             }
522             this.editicon.on('click', function(e) {
523                 
524                 // we fire even  if inothing is selected..
525                 this.fireEvent('edit', this, this.lastData );
526                 
527             }, this);
528         }
529         */
530         
531         this.keyNav = new Roo.KeyNav(this.inputEl(), {
532             "up" : function(e){
533                 this.inKeyMode = true;
534                 this.selectPrev();
535             },
536
537             "down" : function(e){
538                 if(!this.isExpanded()){
539                     this.onTriggerClick();
540                 }else{
541                     this.inKeyMode = true;
542                     this.selectNext();
543                 }
544             },
545
546             "enter" : function(e){
547 //                this.onViewClick();
548                 //return true;
549                 this.collapse();
550                 
551                 if(this.fireEvent("specialkey", this, e)){
552                     this.onViewClick(false);
553                 }
554                 
555                 return true;
556             },
557
558             "esc" : function(e){
559                 this.collapse();
560             },
561
562             "tab" : function(e){
563                 this.collapse();
564                 
565                 if(this.fireEvent("specialkey", this, e)){
566                     this.onViewClick(false);
567                 }
568                 
569                 return true;
570             },
571
572             scope : this,
573
574             doRelay : function(foo, bar, hname){
575                 if(hname == 'down' || this.scope.isExpanded()){
576                    return Roo.KeyNav.prototype.doRelay.apply(this, arguments);
577                 }
578                 return true;
579             },
580
581             forceKeyDown: true
582         });
583         
584         
585         this.queryDelay = Math.max(this.queryDelay || 10,
586                 this.mode == 'local' ? 10 : 250);
587         
588         
589         this.dqTask = new Roo.util.DelayedTask(this.initQuery, this);
590         
591         if(this.typeAhead){
592             this.taTask = new Roo.util.DelayedTask(this.onTypeAhead, this);
593         }
594         if(this.editable !== false){
595             this.inputEl().on("keyup", this.onKeyUp, this);
596         }
597         if(this.forceSelection){
598             this.inputEl().on('blur', this.doForce, this);
599         }
600         
601         if(this.multiple){
602             this.choices = this.el.select('ul.roo-select2-choices', true).first();
603             this.searchField = this.el.select('ul li.roo-select2-search-field', true).first();
604         }
605     },
606     
607     initTickableEvents: function()
608     {   
609         this.createList();
610         
611         if(this.hiddenName){
612             
613             this.hiddenField = this.el.select('input.form-hidden-field',true).first();
614             
615             this.hiddenField.dom.value =
616                 this.hiddenValue !== undefined ? this.hiddenValue :
617                 this.value !== undefined ? this.value : '';
618
619             // prevent input submission
620             this.el.dom.removeAttribute('name');
621             this.hiddenField.dom.setAttribute('name', this.hiddenName);
622              
623              
624         }
625         
626 //        this.list = this.el.select('ul.dropdown-menu',true).first();
627         
628         this.choices = this.el.select('ul.roo-select2-choices', true).first();
629         this.searchField = this.el.select('ul li.roo-select2-search-field', true).first();
630         if(this.triggerList){
631             this.searchField.on("click", this.onSearchFieldClick, this, {preventDefault:true});
632         }
633          
634         this.trigger = this.el.select('.tickable-buttons > .btn-edit', true).first();
635         this.trigger.on("click", this.onTickableTriggerClick, this, {preventDefault:true});
636         
637         this.okBtn = this.el.select('.tickable-buttons > .btn-ok', true).first();
638         this.cancelBtn = this.el.select('.tickable-buttons > .btn-cancel', true).first();
639         
640         this.okBtn.on('click', this.onTickableFooterButtonClick, this, this.okBtn);
641         this.cancelBtn.on('click', this.onTickableFooterButtonClick, this, this.cancelBtn);
642         
643         this.trigger.setVisibilityMode(Roo.Element.DISPLAY);
644         this.okBtn.setVisibilityMode(Roo.Element.DISPLAY);
645         this.cancelBtn.setVisibilityMode(Roo.Element.DISPLAY);
646         
647         this.okBtn.hide();
648         this.cancelBtn.hide();
649         
650         var _this = this;
651         
652         (function(){
653             var lw = _this.listWidth || Math.max(_this.inputEl().getWidth(), _this.minListWidth);
654             _this.list.setWidth(lw);
655         }).defer(100);
656         
657         this.list.on('mouseover', this.onViewOver, this);
658         this.list.on('mousemove', this.onViewMove, this);
659         
660         this.list.on('scroll', this.onViewScroll, this);
661         
662         if(!this.tpl){
663             this.tpl = '<li class="roo-select2-result"><div class="checkbox"><input id="{roo-id}" type="checkbox" {roo-data-checked}><label for="{roo-id}"><b>{' + this.displayField + '}</b></label></div></li>';
664         }
665
666         this.view = new Roo.View(this.list, this.tpl, {
667             singleSelect:true, tickable:true, parent:this, store: this.store, selectedClass: this.selectedClass
668         });
669         
670         //this.view.wrapEl.setDisplayed(false);
671         this.view.on('click', this.onViewClick, this);
672         
673         
674         
675         this.store.on('beforeload', this.onBeforeLoad, this);
676         this.store.on('load', this.onLoad, this);
677         this.store.on('loadexception', this.onLoadException, this);
678         
679         if(this.editable){
680             this.keyNav = new Roo.KeyNav(this.tickableInputEl(), {
681                 "up" : function(e){
682                     this.inKeyMode = true;
683                     this.selectPrev();
684                 },
685
686                 "down" : function(e){
687                     this.inKeyMode = true;
688                     this.selectNext();
689                 },
690
691                 "enter" : function(e){
692                     if(this.fireEvent("specialkey", this, e)){
693                         this.onViewClick(false);
694                     }
695                     
696                     return true;
697                 },
698
699                 "esc" : function(e){
700                     this.onTickableFooterButtonClick(e, false, false);
701                 },
702
703                 "tab" : function(e){
704                     this.fireEvent("specialkey", this, e);
705                     
706                     this.onTickableFooterButtonClick(e, false, false);
707                     
708                     return true;
709                 },
710
711                 scope : this,
712
713                 doRelay : function(e, fn, key){
714                     if(this.scope.isExpanded()){
715                        return Roo.KeyNav.prototype.doRelay.apply(this, arguments);
716                     }
717                     return true;
718                 },
719
720                 forceKeyDown: true
721             });
722         }
723         
724         this.queryDelay = Math.max(this.queryDelay || 10,
725                 this.mode == 'local' ? 10 : 250);
726         
727         
728         this.dqTask = new Roo.util.DelayedTask(this.initQuery, this);
729         
730         if(this.typeAhead){
731             this.taTask = new Roo.util.DelayedTask(this.onTypeAhead, this);
732         }
733         
734         if(this.editable !== false){
735             this.tickableInputEl().on("keyup", this.onKeyUp, this);
736         }
737         
738         this.indicator = this.indicatorEl();
739         
740         if(this.indicator){
741             this.indicator.setVisibilityMode(Roo.Element.DISPLAY);
742             this.indicator.hide();
743         }
744         
745     },
746
747     onDestroy : function(){
748         if(this.view){
749             this.view.setStore(null);
750             this.view.el.removeAllListeners();
751             this.view.el.remove();
752             this.view.purgeListeners();
753         }
754         if(this.list){
755             this.list.dom.innerHTML  = '';
756         }
757         
758         if(this.store){
759             this.store.un('beforeload', this.onBeforeLoad, this);
760             this.store.un('load', this.onLoad, this);
761             this.store.un('loadexception', this.onLoadException, this);
762         }
763         Roo.bootstrap.PhoneInput.superclass.onDestroy.call(this);
764     },
765
766     // private
767     fireKey : function(e){
768         if(e.isNavKeyPress() && !this.list.isVisible()){
769             this.fireEvent("specialkey", this, e);
770         }
771     },
772
773     // private
774     onResize: function(w, h){
775 //        Roo.bootstrap.PhoneInput.superclass.onResize.apply(this, arguments);
776 //        
777 //        if(typeof w != 'number'){
778 //            // we do not handle it!?!?
779 //            return;
780 //        }
781 //        var tw = this.trigger.getWidth();
782 //       // tw += this.addicon ? this.addicon.getWidth() : 0;
783 //       // tw += this.editicon ? this.editicon.getWidth() : 0;
784 //        var x = w - tw;
785 //        this.inputEl().setWidth( this.adjustWidth('input', x));
786 //            
787 //        //this.trigger.setStyle('left', x+'px');
788 //        
789 //        if(this.list && this.listWidth === undefined){
790 //            var lw = Math.max(x + this.trigger.getWidth(), this.minListWidth);
791 //            this.list.setWidth(lw);
792 //            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
793 //        }
794         
795     
796         
797     },
798
799     /**
800      * Allow or prevent the user from directly editing the field text.  If false is passed,
801      * the user will only be able to select from the items defined in the dropdown list.  This method
802      * is the runtime equivalent of setting the 'editable' config option at config time.
803      * @param {Boolean} value True to allow the user to directly edit the field text
804      */
805     setEditable : function(value){
806         if(value == this.editable){
807             return;
808         }
809         this.editable = value;
810         if(!value){
811             this.inputEl().dom.setAttribute('readOnly', true);
812             this.inputEl().on('mousedown', this.onTriggerClick,  this);
813             this.inputEl().addClass('x-combo-noedit');
814         }else{
815             this.inputEl().dom.setAttribute('readOnly', false);
816             this.inputEl().un('mousedown', this.onTriggerClick,  this);
817             this.inputEl().removeClass('x-combo-noedit');
818         }
819     },
820
821     // private
822     
823     onBeforeLoad : function(combo,opts){
824         if(!this.hasFocus){
825             return;
826         }
827          if (!opts.add) {
828             this.list.dom.innerHTML = '<li class="loading-indicator">'+(this.loadingText||'loading')+'</li>' ;
829          }
830         this.restrictHeight();
831         this.selectedIndex = -1;
832     },
833
834     // private
835     onLoad : function(){
836         
837         this.hasQuery = false;
838         
839         if(!this.hasFocus){
840             return;
841         }
842         
843         if(typeof(this.loading) !== 'undefined' && this.loading !== null){
844             this.loading.hide();
845         }
846         
847         if(this.store.getCount() > 0){
848             
849             this.expand();
850             this.restrictHeight();
851             if(this.lastQuery == this.allQuery){
852                 if(this.editable && !this.tickable){
853                     this.inputEl().dom.select();
854                 }
855                 
856                 if(
857                     !this.selectByValue(this.value, true) &&
858                     this.autoFocus && 
859                     (
860                         !this.store.lastOptions ||
861                         typeof(this.store.lastOptions.add) == 'undefined' || 
862                         this.store.lastOptions.add != true
863                     )
864                 ){
865                     this.select(0, true);
866                 }
867             }else{
868                 if(this.autoFocus){
869                     this.selectNext();
870                 }
871                 if(this.typeAhead && this.lastKey != Roo.EventObject.BACKSPACE && this.lastKey != Roo.EventObject.DELETE){
872                     this.taTask.delay(this.typeAheadDelay);
873                 }
874             }
875         }else{
876             this.onEmptyResults();
877         }
878         
879         //this.el.focus();
880     },
881     // private
882     onLoadException : function()
883     {
884         this.hasQuery = false;
885         
886         if(typeof(this.loading) !== 'undefined' && this.loading !== null){
887             this.loading.hide();
888         }
889         
890         if(this.tickable && this.editable){
891             return;
892         }
893         
894         this.collapse();
895         // only causes errors at present
896         //Roo.log(this.store.reader.jsonData);
897         //if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
898             // fixme
899             //Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
900         //}
901         
902         
903     },
904     // private
905     onTypeAhead : function(){
906         if(this.store.getCount() > 0){
907             var r = this.store.getAt(0);
908             var newValue = r.data[this.displayField];
909             var len = newValue.length;
910             var selStart = this.getRawValue().length;
911             
912             if(selStart != len){
913                 this.setRawValue(newValue);
914                 this.selectText(selStart, newValue.length);
915             }
916         }
917     },
918
919     // private
920     onSelect : function(record, index){
921         
922         if(this.fireEvent('beforeselect', this, record, index) !== false){
923         
924             this.setFromData(index > -1 ? record.data : false);
925             
926             this.collapse();
927             this.fireEvent('select', this, record, index);
928         }
929     },
930
931     /**
932      * Returns the currently selected field value or empty string if no value is set.
933      * @return {String} value The selected value
934      */
935     getValue : function()
936     {
937         if(Roo.isIOS && this.useNativeIOS){
938             return this.ios_options[this.inputEl().dom.selectedIndex].data[this.valueField];
939         }
940         
941         if(this.multiple){
942             return (this.hiddenField) ? this.hiddenField.dom.value : this.value;
943         }
944         
945         if(this.valueField){
946             return typeof this.value != 'undefined' ? this.value : '';
947         }else{
948             return Roo.bootstrap.PhoneInput.superclass.getValue.call(this);
949         }
950     },
951     
952     getRawValue : function()
953     {
954         if(Roo.isIOS && this.useNativeIOS){
955             return this.ios_options[this.inputEl().dom.selectedIndex].data[this.displayField];
956         }
957         
958         var v = this.inputEl().getValue();
959         
960         return v;
961     },
962
963     /**
964      * Clears any text/value currently set in the field
965      */
966     clearValue : function(){
967         
968         if(this.hiddenField){
969             this.hiddenField.dom.value = '';
970         }
971         this.value = '';
972         this.setRawValue('');
973         this.lastSelectionText = '';
974         this.lastData = false;
975         
976         var close = this.closeTriggerEl();
977         
978         if(close){
979             close.hide();
980         }
981         
982         this.validate();
983         
984     },
985
986     /**
987      * Sets the specified value into the field.  If the value finds a match, the corresponding record text
988      * will be displayed in the field.  If the value does not match the data value of an existing item,
989      * and the valueNotFoundText config option is defined, it will be displayed as the default field text.
990      * Otherwise the field will be blank (although the value will still be set).
991      * @param {String} value The value to match
992      */
993     setValue : function(v)
994     {
995         if(Roo.isIOS && this.useNativeIOS){
996             this.setIOSValue(v);
997             return;
998         }
999         
1000         if(this.multiple){
1001             this.syncValue();
1002             return;
1003         }
1004         
1005         var text = v;
1006         if(this.valueField){
1007             var r = this.findRecord(this.valueField, v);
1008             if(r){
1009                 text = r.data[this.displayField];
1010             }else if(this.valueNotFoundText !== undefined){
1011                 text = this.valueNotFoundText;
1012             }
1013         }
1014         this.lastSelectionText = text;
1015         if(this.hiddenField){
1016             this.hiddenField.dom.value = v;
1017         }
1018         Roo.bootstrap.PhoneInput.superclass.setValue.call(this, text);
1019         this.value = v;
1020         
1021         var close = this.closeTriggerEl();
1022         
1023         if(close){
1024             (v && (v.length || v * 1 > 0)) ? close.show() : close.hide();
1025         }
1026         
1027         this.validate();
1028     },
1029     /**
1030      * @property {Object} the last set data for the element
1031      */
1032     
1033     lastData : false,
1034     /**
1035      * Sets the value of the field based on a object which is related to the record format for the store.
1036      * @param {Object} value the value to set as. or false on reset?
1037      */
1038     setFromData : function(o){
1039         
1040         if(this.multiple){
1041             this.addItem(o);
1042             return;
1043         }
1044             
1045         var dv = ''; // display value
1046         var vv = ''; // value value..
1047         this.lastData = o;
1048         if (this.displayField) {
1049             dv = !o || typeof(o[this.displayField]) == 'undefined' ? '' : o[this.displayField];
1050         } else {
1051             // this is an error condition!!!
1052             Roo.log('no  displayField value set for '+ (this.name ? this.name : this.id));
1053         }
1054         
1055         if(this.valueField){
1056             vv = !o || typeof(o[this.valueField]) == 'undefined' ? dv : o[this.valueField];
1057         }
1058         
1059         var close = this.closeTriggerEl();
1060         
1061         if(close){
1062             (vv.length || vv * 1 > 0) ? close.show() : close.hide();
1063         }
1064         
1065         if(this.hiddenField){
1066             this.hiddenField.dom.value = vv;
1067             
1068             this.lastSelectionText = dv;
1069             Roo.bootstrap.PhoneInput.superclass.setValue.call(this, dv);
1070             this.value = vv;
1071             return;
1072         }
1073         // no hidden field.. - we store the value in 'value', but still display
1074         // display field!!!!
1075         this.lastSelectionText = dv;
1076         Roo.bootstrap.PhoneInput.superclass.setValue.call(this, dv);
1077         this.value = vv;
1078         
1079         
1080         
1081     },
1082     // private
1083     reset : function(){
1084         // overridden so that last data is reset..
1085         
1086         if(this.multiple){
1087             this.clearItem();
1088             return;
1089         }
1090         
1091         this.setValue(this.originalValue);
1092         //this.clearInvalid();
1093         this.lastData = false;
1094         if (this.view) {
1095             this.view.clearSelections();
1096         }
1097         
1098         this.validate();
1099     },
1100     // private
1101     findRecord : function(prop, value){
1102         var record;
1103         if(this.store.getCount() > 0){
1104             this.store.each(function(r){
1105                 if(r.data[prop] == value){
1106                     record = r;
1107                     return false;
1108                 }
1109                 return true;
1110             });
1111         }
1112         return record;
1113     },
1114     
1115     getName: function()
1116     {
1117         // returns hidden if it's set..
1118         if (!this.rendered) {return ''};
1119         return !this.hiddenName && this.inputEl().dom.name  ? this.inputEl().dom.name : (this.hiddenName || '');
1120         
1121     },
1122     // private
1123     onViewMove : function(e, t){
1124         this.inKeyMode = false;
1125     },
1126
1127     // private
1128     onViewOver : function(e, t){
1129         if(this.inKeyMode){ // prevent key nav and mouse over conflicts
1130             return;
1131         }
1132         var item = this.view.findItemFromChild(t);
1133         
1134         if(item){
1135             var index = this.view.indexOf(item);
1136             this.select(index, false);
1137         }
1138     },
1139
1140     // private
1141     onViewClick : function(view, doFocus, el, e)
1142     {
1143         var index = this.view.getSelectedIndexes()[0];
1144         
1145         var r = this.store.getAt(index);
1146         
1147         if(this.tickable){
1148             
1149             if(typeof(e) != 'undefined' && e.getTarget().nodeName.toLowerCase() != 'input'){
1150                 return;
1151             }
1152             
1153             var rm = false;
1154             var _this = this;
1155             
1156             Roo.each(this.tickItems, function(v,k){
1157                 
1158                 if(typeof(v) != 'undefined' && v[_this.valueField] == r.data[_this.valueField]){
1159                     _this.tickItems.splice(k, 1);
1160                     
1161                     if(typeof(e) == 'undefined' && view == false){
1162                         Roo.get(_this.view.getNodes(index, index)[0]).select('input', true).first().dom.checked = false;
1163                     }
1164                     
1165                     rm = true;
1166                     return;
1167                 }
1168             });
1169             
1170             if(rm){
1171                 return;
1172             }
1173             
1174             if(this.fireEvent('tick', this, r, index, Roo.get(_this.view.getNodes(index, index)[0]).select('input', true).first().dom.checked) !== false){
1175                 this.tickItems.push(r.data);
1176             }
1177             
1178             if(typeof(e) == 'undefined' && view == false){
1179                 Roo.get(_this.view.getNodes(index, index)[0]).select('input', true).first().dom.checked = true;
1180             }
1181                     
1182             return;
1183         }
1184         
1185         if(r){
1186             this.onSelect(r, index);
1187         }
1188         if(doFocus !== false && !this.blockFocus){
1189             this.inputEl().focus();
1190         }
1191     },
1192
1193     // private
1194     restrictHeight : function(){
1195         //this.innerList.dom.style.height = '';
1196         //var inner = this.innerList.dom;
1197         //var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
1198         //this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
1199         //this.list.beginUpdate();
1200         //this.list.setHeight(this.innerList.getHeight()+this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight);
1201         this.list.alignTo(this.inputEl(), this.listAlign);
1202         this.list.alignTo(this.inputEl(), this.listAlign);
1203         //this.list.endUpdate();
1204     },
1205
1206     // private
1207     onEmptyResults : function(){
1208         
1209         if(this.tickable && this.editable){
1210             this.restrictHeight();
1211             return;
1212         }
1213         
1214         this.collapse();
1215     },
1216
1217     /**
1218      * Returns true if the dropdown list is expanded, else false.
1219      */
1220     isExpanded : function(){
1221         return this.list.isVisible();
1222     },
1223
1224     /**
1225      * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.
1226      * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
1227      * @param {String} value The data value of the item to select
1228      * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
1229      * selected item if it is not currently in view (defaults to true)
1230      * @return {Boolean} True if the value matched an item in the list, else false
1231      */
1232     selectByValue : function(v, scrollIntoView){
1233         if(v !== undefined && v !== null){
1234             var r = this.findRecord(this.valueField || this.displayField, v);
1235             if(r){
1236                 this.select(this.store.indexOf(r), scrollIntoView);
1237                 return true;
1238             }
1239         }
1240         return false;
1241     },
1242
1243     /**
1244      * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire.
1245      * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
1246      * @param {Number} index The zero-based index of the list item to select
1247      * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
1248      * selected item if it is not currently in view (defaults to true)
1249      */
1250     select : function(index, scrollIntoView){
1251         this.selectedIndex = index;
1252         this.view.select(index);
1253         if(scrollIntoView !== false){
1254             var el = this.view.getNode(index);
1255             /*
1256              * el && !this.multiple && !this.tickable // not sure why we disable multiple before..
1257              */
1258             if(el){
1259                 this.list.scrollChildIntoView(el, false);
1260             }
1261         }
1262     },
1263
1264     // private
1265     selectNext : function(){
1266         var ct = this.store.getCount();
1267         if(ct > 0){
1268             if(this.selectedIndex == -1){
1269                 this.select(0);
1270             }else if(this.selectedIndex < ct-1){
1271                 this.select(this.selectedIndex+1);
1272             }
1273         }
1274     },
1275
1276     // private
1277     selectPrev : function(){
1278         var ct = this.store.getCount();
1279         if(ct > 0){
1280             if(this.selectedIndex == -1){
1281                 this.select(0);
1282             }else if(this.selectedIndex != 0){
1283                 this.select(this.selectedIndex-1);
1284             }
1285         }
1286     },
1287
1288     // private
1289     onKeyUp : function(e){
1290         if(this.editable !== false && !e.isSpecialKey()){
1291             this.lastKey = e.getKey();
1292             this.dqTask.delay(this.queryDelay);
1293         }
1294     },
1295
1296     // private
1297     validateBlur : function(){
1298         return !this.list || !this.list.isVisible();   
1299     },
1300
1301     // private
1302     initQuery : function(){
1303         
1304         var v = this.getRawValue();
1305         
1306         if(this.tickable && this.editable){
1307             v = this.tickableInputEl().getValue();
1308         }
1309         
1310         this.doQuery(v);
1311     },
1312
1313     // private
1314     doForce : function(){
1315         if(this.inputEl().dom.value.length > 0){
1316             this.inputEl().dom.value =
1317                 this.lastSelectionText === undefined ? '' : this.lastSelectionText;
1318              
1319         }
1320     },
1321
1322     /**
1323      * Execute a query to filter the dropdown list.  Fires the beforequery event prior to performing the
1324      * query allowing the query action to be canceled if needed.
1325      * @param {String} query The SQL query to execute
1326      * @param {Boolean} forceAll True to force the query to execute even if there are currently fewer characters
1327      * in the field than the minimum specified by the minChars config option.  It also clears any filter previously
1328      * saved in the current store (defaults to false)
1329      */
1330     doQuery : function(q, forceAll){
1331         
1332         if(q === undefined || q === null){
1333             q = '';
1334         }
1335         var qe = {
1336             query: q,
1337             forceAll: forceAll,
1338             combo: this,
1339             cancel:false
1340         };
1341         if(this.fireEvent('beforequery', qe)===false || qe.cancel){
1342             return false;
1343         }
1344         q = qe.query;
1345         
1346         forceAll = qe.forceAll;
1347         if(forceAll === true || (q.length >= this.minChars)){
1348             
1349             this.hasQuery = true;
1350             
1351             if(this.lastQuery != q || this.alwaysQuery){
1352                 this.lastQuery = q;
1353                 if(this.mode == 'local'){
1354                     this.selectedIndex = -1;
1355                     if(forceAll){
1356                         this.store.clearFilter();
1357                     }else{
1358                         
1359                         if(this.specialFilter){
1360                             this.fireEvent('specialfilter', this);
1361                             this.onLoad();
1362                             return;
1363                         }
1364                         
1365                         this.store.filter(this.displayField, q);
1366                     }
1367                     
1368                     this.store.fireEvent("datachanged", this.store);
1369                     
1370                     this.onLoad();
1371                     
1372                     
1373                 }else{
1374                     
1375                     this.store.baseParams[this.queryParam] = q;
1376                     
1377                     var options = {params : this.getParams(q)};
1378                     
1379                     if(this.loadNext){
1380                         options.add = true;
1381                         options.params.start = this.page * this.pageSize;
1382                     }
1383                     
1384                     this.store.load(options);
1385                     
1386                     /*
1387                      *  this code will make the page width larger, at the beginning, the list not align correctly, 
1388                      *  we should expand the list on onLoad
1389                      *  so command out it
1390                      */
1391 //                    this.expand();
1392                 }
1393             }else{
1394                 this.selectedIndex = -1;
1395                 this.onLoad();   
1396             }
1397         }
1398         
1399         this.loadNext = false;
1400     },
1401     
1402     // private
1403     getParams : function(q){
1404         var p = {};
1405         //p[this.queryParam] = q;
1406         
1407         if(this.pageSize){
1408             p.start = 0;
1409             p.limit = this.pageSize;
1410         }
1411         return p;
1412     },
1413
1414     /**
1415      * Hides the dropdown list if it is currently expanded. Fires the 'collapse' event on completion.
1416      */
1417     collapse : function(){
1418         if(!this.isExpanded()){
1419             return;
1420         }
1421         
1422         this.list.hide();
1423         
1424         this.hasFocus = false;
1425         
1426         if(this.tickable){
1427             this.okBtn.hide();
1428             this.cancelBtn.hide();
1429             this.trigger.show();
1430             
1431             if(this.editable){
1432                 this.tickableInputEl().dom.value = '';
1433                 this.tickableInputEl().blur();
1434             }
1435             
1436         }
1437         
1438         Roo.get(document).un('mousedown', this.collapseIf, this);
1439         Roo.get(document).un('mousewheel', this.collapseIf, this);
1440         if (!this.editable) {
1441             Roo.get(document).un('keydown', this.listKeyPress, this);
1442         }
1443         this.fireEvent('collapse', this);
1444         
1445         this.validate();
1446     },
1447
1448     // private
1449     collapseIf : function(e){
1450         var in_combo  = e.within(this.el);
1451         var in_list =  e.within(this.list);
1452         var is_list = (Roo.get(e.getTarget()).id == this.list.id) ? true : false;
1453         
1454         if (in_combo || in_list || is_list) {
1455             //e.stopPropagation();
1456             return;
1457         }
1458         
1459         if(this.tickable){
1460             this.onTickableFooterButtonClick(e, false, false);
1461         }
1462
1463         this.collapse();
1464         
1465     },
1466
1467     /**
1468      * Expands the dropdown list if it is currently hidden. Fires the 'expand' event on completion.
1469      */
1470     expand : function(){
1471        
1472         if(this.isExpanded() || !this.hasFocus){
1473             return;
1474         }
1475         
1476         var lw = this.listWidth || Math.max(this.inputEl().getWidth(), this.minListWidth);
1477         this.list.setWidth(lw);
1478         
1479         Roo.log('expand');
1480         
1481         this.list.show();
1482         
1483         this.restrictHeight();
1484         
1485         if(this.tickable){
1486             
1487             this.tickItems = Roo.apply([], this.item);
1488             
1489             this.okBtn.show();
1490             this.cancelBtn.show();
1491             this.trigger.hide();
1492             
1493             if(this.editable){
1494                 this.tickableInputEl().focus();
1495             }
1496             
1497         }
1498         
1499         Roo.get(document).on('mousedown', this.collapseIf, this);
1500         Roo.get(document).on('mousewheel', this.collapseIf, this);
1501         if (!this.editable) {
1502             Roo.get(document).on('keydown', this.listKeyPress, this);
1503         }
1504         
1505         this.fireEvent('expand', this);
1506     },
1507
1508     // private
1509     // Implements the default empty TriggerField.onTriggerClick function
1510     onTriggerClick : function(e)
1511     {
1512         Roo.log('trigger click');
1513         
1514         if(this.disabled || !this.triggerList){
1515             return;
1516         }
1517         
1518         this.page = 0;
1519         this.loadNext = false;
1520         
1521         if(this.isExpanded()){
1522             this.collapse();
1523             if (!this.blockFocus) {
1524                 this.inputEl().focus();
1525             }
1526             
1527         }else {
1528             this.hasFocus = true;
1529             if(this.triggerAction == 'all') {
1530                 this.doQuery(this.allQuery, true);
1531             } else {
1532                 this.doQuery(this.getRawValue());
1533             }
1534             if (!this.blockFocus) {
1535                 this.inputEl().focus();
1536             }
1537         }
1538     },
1539     
1540     onTickableTriggerClick : function(e)
1541     {
1542         if(this.disabled){
1543             return;
1544         }
1545         
1546         this.page = 0;
1547         this.loadNext = false;
1548         this.hasFocus = true;
1549         
1550         if(this.triggerAction == 'all') {
1551             this.doQuery(this.allQuery, true);
1552         } else {
1553             this.doQuery(this.getRawValue());
1554         }
1555     },
1556     
1557     onSearchFieldClick : function(e)
1558     {
1559         if(this.hasFocus && !this.disabled && e.getTarget().nodeName.toLowerCase() != 'button'){
1560             this.onTickableFooterButtonClick(e, false, false);
1561             return;
1562         }
1563         
1564         if(this.hasFocus || this.disabled || e.getTarget().nodeName.toLowerCase() == 'button'){
1565             return;
1566         }
1567         
1568         this.page = 0;
1569         this.loadNext = false;
1570         this.hasFocus = true;
1571         
1572         if(this.triggerAction == 'all') {
1573             this.doQuery(this.allQuery, true);
1574         } else {
1575             this.doQuery(this.getRawValue());
1576         }
1577     },
1578     
1579     listKeyPress : function(e)
1580     {
1581         //Roo.log('listkeypress');
1582         // scroll to first matching element based on key pres..
1583         if (e.isSpecialKey()) {
1584             return false;
1585         }
1586         var k = String.fromCharCode(e.getKey()).toUpperCase();
1587         //Roo.log(k);
1588         var match  = false;
1589         var csel = this.view.getSelectedNodes();
1590         var cselitem = false;
1591         if (csel.length) {
1592             var ix = this.view.indexOf(csel[0]);
1593             cselitem  = this.store.getAt(ix);
1594             if (!cselitem.get(this.displayField) || cselitem.get(this.displayField).substring(0,1).toUpperCase() != k) {
1595                 cselitem = false;
1596             }
1597             
1598         }
1599         
1600         this.store.each(function(v) { 
1601             if (cselitem) {
1602                 // start at existing selection.
1603                 if (cselitem.id == v.id) {
1604                     cselitem = false;
1605                 }
1606                 return true;
1607             }
1608                 
1609             if (v.get(this.displayField) && v.get(this.displayField).substring(0,1).toUpperCase() == k) {
1610                 match = this.store.indexOf(v);
1611                 return false;
1612             }
1613             return true;
1614         }, this);
1615         
1616         if (match === false) {
1617             return true; // no more action?
1618         }
1619         // scroll to?
1620         this.view.select(match);
1621         var sn = Roo.get(this.view.getSelectedNodes()[0]);
1622         sn.scrollIntoView(sn.dom.parentNode, false);
1623     },
1624     
1625     onViewScroll : function(e, t){
1626         
1627         if(this.view.el.getScroll().top == 0 ||this.view.el.getScroll().top < this.view.el.dom.scrollHeight - this.view.el.dom.clientHeight || !this.hasFocus || !this.append || this.hasQuery){
1628             return;
1629         }
1630         
1631         this.hasQuery = true;
1632         
1633         this.loading = this.list.select('.loading', true).first();
1634         
1635         if(this.loading === null){
1636             this.list.createChild({
1637                 tag: 'div',
1638                 cls: 'loading roo-select2-more-results roo-select2-active',
1639                 html: 'Loading more results...'
1640             });
1641             
1642             this.loading = this.list.select('.loading', true).first();
1643             
1644             this.loading.setVisibilityMode(Roo.Element.DISPLAY);
1645             
1646             this.loading.hide();
1647         }
1648         
1649         this.loading.show();
1650         
1651         var _combo = this;
1652         
1653         this.page++;
1654         this.loadNext = true;
1655         
1656         (function() { _combo.doQuery(_combo.allQuery, true); }).defer(500);
1657         
1658         return;
1659     },
1660     
1661     addItem : function(o)
1662     {   
1663         var dv = ''; // display value
1664         
1665         if (this.displayField) {
1666             dv = !o || typeof(o[this.displayField]) == 'undefined' ? '' : o[this.displayField];
1667         } else {
1668             // this is an error condition!!!
1669             Roo.log('no  displayField value set for '+ (this.name ? this.name : this.id));
1670         }
1671         
1672         if(!dv.length){
1673             return;
1674         }
1675         
1676         var choice = this.choices.createChild({
1677             tag: 'li',
1678             cls: 'roo-select2-search-choice',
1679             cn: [
1680                 {
1681                     tag: 'div',
1682                     html: dv
1683                 },
1684                 {
1685                     tag: 'a',
1686                     href: '#',
1687                     cls: 'roo-select2-search-choice-close fa fa-times',
1688                     tabindex: '-1'
1689                 }
1690             ]
1691             
1692         }, this.searchField);
1693         
1694         var close = choice.select('a.roo-select2-search-choice-close', true).first();
1695         
1696         close.on('click', this.onRemoveItem, this, { item : choice, data : o} );
1697         
1698         this.item.push(o);
1699         
1700         this.lastData = o;
1701         
1702         this.syncValue();
1703         
1704         this.inputEl().dom.value = '';
1705         
1706         this.validate();
1707     },
1708     
1709     onRemoveItem : function(e, _self, o)
1710     {
1711         e.preventDefault();
1712         
1713         this.lastItem = Roo.apply([], this.item);
1714         
1715         var index = this.item.indexOf(o.data) * 1;
1716         
1717         if( index < 0){
1718             Roo.log('not this item?!');
1719             return;
1720         }
1721         
1722         this.item.splice(index, 1);
1723         o.item.remove();
1724         
1725         this.syncValue();
1726         
1727         this.fireEvent('remove', this, e);
1728         
1729         this.validate();
1730         
1731     },
1732     
1733     syncValue : function()
1734     {
1735         if(!this.item.length){
1736             this.clearValue();
1737             return;
1738         }
1739             
1740         var value = [];
1741         var _this = this;
1742         Roo.each(this.item, function(i){
1743             if(_this.valueField){
1744                 value.push(i[_this.valueField]);
1745                 return;
1746             }
1747
1748             value.push(i);
1749         });
1750
1751         this.value = value.join(',');
1752
1753         if(this.hiddenField){
1754             this.hiddenField.dom.value = this.value;
1755         }
1756         
1757         this.store.fireEvent("datachanged", this.store);
1758         
1759         this.validate();
1760     },
1761     
1762     clearItem : function()
1763     {
1764         if(!this.multiple){
1765             return;
1766         }
1767         
1768         this.item = [];
1769         
1770         Roo.each(this.choices.select('>li.roo-select2-search-choice', true).elements, function(c){
1771            c.remove();
1772         });
1773         
1774         this.syncValue();
1775         
1776         this.validate();
1777         
1778         if(this.tickable && !Roo.isTouch){
1779             this.view.refresh();
1780         }
1781     },
1782     
1783     inputEl: function ()
1784     {
1785         if(Roo.isIOS && this.useNativeIOS){
1786             return this.el.select('select.roo-ios-select', true).first();
1787         }
1788         
1789         if(Roo.isTouch && this.mobileTouchView){
1790             return this.el.select('input.form-control',true).first();
1791         }
1792         
1793         if(this.tickable){
1794             return this.searchField;
1795         }
1796         
1797         return this.el.select('input.form-control',true).first();
1798     },
1799     
1800     onTickableFooterButtonClick : function(e, btn, el)
1801     {
1802         e.preventDefault();
1803         
1804         this.lastItem = Roo.apply([], this.item);
1805         
1806         if(btn && btn.name == 'cancel'){
1807             this.tickItems = Roo.apply([], this.item);
1808             this.collapse();
1809             return;
1810         }
1811         
1812         this.clearItem();
1813         
1814         var _this = this;
1815         
1816         Roo.each(this.tickItems, function(o){
1817             _this.addItem(o);
1818         });
1819         
1820         this.collapse();
1821         
1822     },
1823     
1824     validate : function()
1825     {
1826         var v = this.getRawValue();
1827         
1828         if(this.multiple){
1829             v = this.getValue();
1830         }
1831         
1832         if(this.disabled || this.allowBlank || v.length){
1833             this.markValid();
1834             return true;
1835         }
1836         
1837         this.markInvalid();
1838         return false;
1839     },
1840     
1841     tickableInputEl : function()
1842     {
1843         if(!this.tickable || !this.editable){
1844             return this.inputEl();
1845         }
1846         
1847         return this.inputEl().select('.roo-select2-search-field-input', true).first();
1848     },
1849     
1850     
1851     getAutoCreateTouchView : function()
1852     {
1853         var id = Roo.id();
1854         
1855         var cfg = {
1856             cls: 'form-group' //input-group
1857         };
1858         
1859         var input =  {
1860             tag: 'input',
1861             id : id,
1862             type : this.inputType,
1863             cls : 'form-control x-combo-noedit',
1864             autocomplete: 'new-password',
1865             placeholder : this.placeholder || '',
1866             readonly : true
1867         };
1868         
1869         if (this.name) {
1870             input.name = this.name;
1871         }
1872         
1873         if (this.size) {
1874             input.cls += ' input-' + this.size;
1875         }
1876         
1877         if (this.disabled) {
1878             input.disabled = true;
1879         }
1880         
1881         var inputblock = {
1882             cls : '',
1883             cn : [
1884                 input
1885             ]
1886         };
1887         
1888         if(this.before){
1889             inputblock.cls += ' input-group';
1890             
1891             inputblock.cn.unshift({
1892                 tag :'span',
1893                 cls : 'input-group-addon',
1894                 html : this.before
1895             });
1896         }
1897         
1898         if(this.removable && !this.multiple){
1899             inputblock.cls += ' roo-removable';
1900             
1901             inputblock.cn.push({
1902                 tag: 'button',
1903                 html : 'x',
1904                 cls : 'roo-combo-removable-btn close'
1905             });
1906         }
1907
1908         if(this.hasFeedback && !this.allowBlank){
1909             
1910             inputblock.cls += ' has-feedback';
1911             
1912             inputblock.cn.push({
1913                 tag: 'span',
1914                 cls: 'glyphicon form-control-feedback'
1915             });
1916             
1917         }
1918         
1919         if (this.after) {
1920             
1921             inputblock.cls += (this.before) ? '' : ' input-group';
1922             
1923             inputblock.cn.push({
1924                 tag :'span',
1925                 cls : 'input-group-addon',
1926                 html : this.after
1927             });
1928         }
1929
1930         var box = {
1931             tag: 'div',
1932             cn: [
1933                 {
1934                     tag: 'input',
1935                     type : 'hidden',
1936                     cls: 'form-hidden-field'
1937                 },
1938                 inputblock
1939             ]
1940             
1941         };
1942         
1943         if(this.multiple){
1944             box = {
1945                 tag: 'div',
1946                 cn: [
1947                     {
1948                         tag: 'input',
1949                         type : 'hidden',
1950                         cls: 'form-hidden-field'
1951                     },
1952                     {
1953                         tag: 'ul',
1954                         cls: 'roo-select2-choices',
1955                         cn:[
1956                             {
1957                                 tag: 'li',
1958                                 cls: 'roo-select2-search-field',
1959                                 cn: [
1960
1961                                     inputblock
1962                                 ]
1963                             }
1964                         ]
1965                     }
1966                 ]
1967             }
1968         };
1969         
1970         var PhoneInput = {
1971             cls: 'roo-select2-container input-group roo-touchview-PhoneInput ',
1972             cn: [
1973                 box
1974             ]
1975         };
1976         
1977         if(!this.multiple && this.showToggleBtn){
1978             
1979             var caret = {
1980                         tag: 'span',
1981                         cls: 'caret'
1982             };
1983             
1984             if (this.caret != false) {
1985                 caret = {
1986                      tag: 'i',
1987                      cls: 'fa fa-' + this.caret
1988                 };
1989                 
1990             }
1991             
1992             PhoneInput.cn.push({
1993                 tag :'span',
1994                 cls : 'input-group-addon btn dropdown-toggle',
1995                 cn : [
1996                     caret,
1997                     {
1998                         tag: 'span',
1999                         cls: 'PhoneInput-clear',
2000                         cn  : [
2001                             {
2002                                 tag : 'i',
2003                                 cls: 'icon-remove'
2004                             }
2005                         ]
2006                     }
2007                 ]
2008
2009             })
2010         }
2011         
2012         if(this.multiple){
2013             PhoneInput.cls += ' roo-select2-container-multi';
2014         }
2015         
2016         var align = this.labelAlign || this.parentLabelAlign();
2017         
2018         if (align ==='left' && this.fieldLabel.length) {
2019
2020             cfg.cn = [
2021                 {
2022                    tag : 'i',
2023                    cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
2024                    tooltip : 'This field is required'
2025                 },
2026                 {
2027                     tag: 'label',
2028                     cls : 'control-label',
2029                     html : this.fieldLabel
2030
2031                 },
2032                 {
2033                     cls : '', 
2034                     cn: [
2035                         PhoneInput
2036                     ]
2037                 }
2038             ];
2039             
2040             var labelCfg = cfg.cn[1];
2041             var contentCfg = cfg.cn[2];
2042             
2043
2044             if(this.indicatorpos == 'right'){
2045                 cfg.cn = [
2046                     {
2047                         tag: 'label',
2048                         cls : 'control-label',
2049                         html : this.fieldLabel,
2050                         cn : [
2051                             {
2052                                tag : 'i',
2053                                cls : 'roo-required-indicator right-indicator text-danger fa fa-lg fa-star',
2054                                tooltip : 'This field is required'
2055                             }
2056                         ]
2057                     },
2058                     {
2059                         cls : '', 
2060                         cn: [
2061                             PhoneInput
2062                         ]
2063                     }
2064                 ];
2065             }
2066             
2067             labelCfg = cfg.cn[0];
2068             contentCfg = cfg.cn[2];
2069             
2070             if(this.labelWidth > 12){
2071                 labelCfg.style = "width: " + this.labelWidth + 'px';
2072             }
2073             
2074             if(this.labelWidth < 13 && this.labelmd == 0){
2075                 this.labelmd = this.labelWidth;
2076             }
2077             
2078             if(this.labellg > 0){
2079                 labelCfg.cls += ' col-lg-' + this.labellg;
2080                 contentCfg.cls += ' col-lg-' + (12 - this.labellg);
2081             }
2082             
2083             if(this.labelmd > 0){
2084                 labelCfg.cls += ' col-md-' + this.labelmd;
2085                 contentCfg.cls += ' col-md-' + (12 - this.labelmd);
2086             }
2087             
2088             if(this.labelsm > 0){
2089                 labelCfg.cls += ' col-sm-' + this.labelsm;
2090                 contentCfg.cls += ' col-sm-' + (12 - this.labelsm);
2091             }
2092             
2093             if(this.labelxs > 0){
2094                 labelCfg.cls += ' col-xs-' + this.labelxs;
2095                 contentCfg.cls += ' col-xs-' + (12 - this.labelxs);
2096             }
2097                 
2098                 
2099         } else if ( this.fieldLabel.length) {
2100             cfg.cn = [
2101                 {
2102                    tag : 'i',
2103                    cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
2104                    tooltip : 'This field is required'
2105                 },
2106                 {
2107                     tag: 'label',
2108                     cls : 'control-label',
2109                     html : this.fieldLabel
2110
2111                 },
2112                 {
2113                     cls : '', 
2114                     cn: [
2115                         PhoneInput
2116                     ]
2117                 }
2118             ];
2119             
2120             if(this.indicatorpos == 'right'){
2121                 cfg.cn = [
2122                     {
2123                         tag: 'label',
2124                         cls : 'control-label',
2125                         html : this.fieldLabel,
2126                         cn : [
2127                             {
2128                                tag : 'i',
2129                                cls : 'roo-required-indicator right-indicator text-danger fa fa-lg fa-star',
2130                                tooltip : 'This field is required'
2131                             }
2132                         ]
2133                     },
2134                     {
2135                         cls : '', 
2136                         cn: [
2137                             PhoneInput
2138                         ]
2139                     }
2140                 ];
2141             }
2142         } else {
2143             cfg.cn = PhoneInput;    
2144         }
2145         
2146         
2147         var settings = this;
2148         
2149         ['xs','sm','md','lg'].map(function(size){
2150             if (settings[size]) {
2151                 cfg.cls += ' col-' + size + '-' + settings[size];
2152             }
2153         });
2154         
2155         return cfg;
2156     },
2157     
2158     initTouchView : function()
2159     {
2160         this.renderTouchView();
2161         
2162         this.touchViewEl.on('scroll', function(){
2163             this.el.dom.scrollTop = 0;
2164         }, this);
2165         
2166         this.originalValue = this.getValue();
2167         
2168         this.triggerEl = this.el.select('span.dropdown-toggle',true).first();
2169         
2170         this.inputEl().on("click", this.showTouchView, this);
2171         if (this.triggerEl) {
2172             this.triggerEl.on("click", this.showTouchView, this);
2173         }
2174         
2175         
2176         this.touchViewFooterEl.select('.roo-touch-view-cancel', true).first().on('click', this.hideTouchView, this);
2177         this.touchViewFooterEl.select('.roo-touch-view-ok', true).first().on('click', this.setTouchViewValue, this);
2178         
2179         this.maskEl = new Roo.LoadMask(this.touchViewEl, { store : this.store, msgCls: 'roo-el-mask-msg' });
2180         
2181         this.store.on('beforeload', this.onTouchViewBeforeLoad, this);
2182         this.store.on('load', this.onTouchViewLoad, this);
2183         this.store.on('loadexception', this.onTouchViewLoadException, this);
2184         
2185         if(this.hiddenName){
2186             
2187             this.hiddenField = this.el.select('input.form-hidden-field',true).first();
2188             
2189             this.hiddenField.dom.value =
2190                 this.hiddenValue !== undefined ? this.hiddenValue :
2191                 this.value !== undefined ? this.value : '';
2192         
2193             this.el.dom.removeAttribute('name');
2194             this.hiddenField.dom.setAttribute('name', this.hiddenName);
2195         }
2196         
2197         if(this.multiple){
2198             this.choices = this.el.select('ul.roo-select2-choices', true).first();
2199             this.searchField = this.el.select('ul li.roo-select2-search-field', true).first();
2200         }
2201         
2202         if(this.removable && !this.multiple){
2203             var close = this.closeTriggerEl();
2204             if(close){
2205                 close.setVisibilityMode(Roo.Element.DISPLAY).hide();
2206                 close.on('click', this.removeBtnClick, this, close);
2207             }
2208         }
2209         /*
2210          * fix the bug in Safari iOS8
2211          */
2212         this.inputEl().on("focus", function(e){
2213             document.activeElement.blur();
2214         }, this);
2215         
2216         return;
2217         
2218         
2219     },
2220     
2221     renderTouchView : function()
2222     {
2223         this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.PhoneInput.touchViewTemplate);
2224         this.touchViewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
2225         
2226         this.touchViewHeaderEl = this.touchViewEl.select('.modal-header', true).first();
2227         this.touchViewHeaderEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
2228         
2229         this.touchViewBodyEl = this.touchViewEl.select('.modal-body', true).first();
2230         this.touchViewBodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
2231         this.touchViewBodyEl.setStyle('overflow', 'auto');
2232         
2233         this.touchViewListGroup = this.touchViewBodyEl.select('.list-group', true).first();
2234         this.touchViewListGroup.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
2235         
2236         this.touchViewFooterEl = this.touchViewEl.select('.modal-footer', true).first();
2237         this.touchViewFooterEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
2238         
2239     },
2240     
2241     showTouchView : function()
2242     {
2243         if(this.disabled){
2244             return;
2245         }
2246         
2247         this.touchViewHeaderEl.hide();
2248
2249         if(this.modalTitle.length){
2250             this.touchViewHeaderEl.dom.innerHTML = this.modalTitle;
2251             this.touchViewHeaderEl.show();
2252         }
2253
2254         this.touchViewEl.setStyle('z-index', Roo.bootstrap.Modal.zIndex++);
2255         this.touchViewEl.show();
2256
2257         this.touchViewEl.select('.modal-dialog', true).first().setStyle('margin', '0px');
2258         this.touchViewEl.select('.modal-dialog > .modal-content', true).first().setSize(
2259                 Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
2260
2261         var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
2262
2263         if(this.modalTitle.length){
2264             bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
2265         }
2266         
2267         this.touchViewBodyEl.setHeight(bodyHeight);
2268
2269         if(this.animate){
2270             var _this = this;
2271             (function(){ _this.touchViewEl.addClass('in'); }).defer(50);
2272         }else{
2273             this.touchViewEl.addClass('in');
2274         }
2275
2276         this.doTouchViewQuery();
2277         
2278     },
2279     
2280     hideTouchView : function()
2281     {
2282         this.touchViewEl.removeClass('in');
2283
2284         if(this.animate){
2285             var _this = this;
2286             (function(){ _this.touchViewEl.setStyle('display', 'none'); }).defer(150);
2287         }else{
2288             this.touchViewEl.setStyle('display', 'none');
2289         }
2290         
2291     },
2292     
2293     setTouchViewValue : function()
2294     {
2295         if(this.multiple){
2296             this.clearItem();
2297         
2298             var _this = this;
2299
2300             Roo.each(this.tickItems, function(o){
2301                 this.addItem(o);
2302             }, this);
2303         }
2304         
2305         this.hideTouchView();
2306     },
2307     
2308     doTouchViewQuery : function()
2309     {
2310         var qe = {
2311             query: '',
2312             forceAll: true,
2313             combo: this,
2314             cancel:false
2315         };
2316         
2317         if(this.fireEvent('beforequery', qe) ===false || qe.cancel){
2318             return false;
2319         }
2320         
2321         if(!this.alwaysQuery || this.mode == 'local'){
2322             this.onTouchViewLoad();
2323             return;
2324         }
2325         
2326         this.store.load();
2327     },
2328     
2329     onTouchViewBeforeLoad : function(combo,opts)
2330     {
2331         return;
2332     },
2333
2334     // private
2335     onTouchViewLoad : function()
2336     {
2337         if(this.store.getCount() < 1){
2338             this.onTouchViewEmptyResults();
2339             return;
2340         }
2341         
2342         this.clearTouchView();
2343         
2344         var rawValue = this.getRawValue();
2345         
2346         var template = (this.multiple) ? Roo.bootstrap.PhoneInput.listItemCheckbox : Roo.bootstrap.PhoneInput.listItemRadio;
2347         
2348         this.tickItems = [];
2349         
2350         this.store.data.each(function(d, rowIndex){
2351             var row = this.touchViewListGroup.createChild(template);
2352             
2353             if(typeof(d.data.cls) != 'undefined' && d.data.cls.length){
2354                 row.addClass(d.data.cls);
2355             }
2356             
2357             if(this.displayField && typeof(d.data[this.displayField]) != 'undefined'){
2358                 var cfg = {
2359                     data : d.data,
2360                     html : d.data[this.displayField]
2361                 };
2362                 
2363                 if(this.fireEvent('touchviewdisplay', this, cfg) !== false){
2364                     row.select('.roo-PhoneInput-list-group-item-value', true).first().dom.innerHTML = cfg.html;
2365                 }
2366             }
2367             row.removeClass('selected');
2368             if(!this.multiple && this.valueField &&
2369                     typeof(d.data[this.valueField]) != 'undefined' && d.data[this.valueField] == this.getValue())
2370             {
2371                 // radio buttons..
2372                 row.select('.roo-PhoneInput-list-group-item-box > input', true).first().attr('checked', true);
2373                 row.addClass('selected');
2374             }
2375             
2376             if(this.multiple && this.valueField &&
2377                     typeof(d.data[this.valueField]) != 'undefined' && this.getValue().indexOf(d.data[this.valueField]) != -1)
2378             {
2379                 
2380                 // checkboxes...
2381                 row.select('.roo-PhoneInput-list-group-item-box > input', true).first().attr('checked', true);
2382                 this.tickItems.push(d.data);
2383             }
2384             
2385             row.on('click', this.onTouchViewClick, this, {row : row, rowIndex : rowIndex});
2386             
2387         }, this);
2388         
2389         var firstChecked = this.touchViewListGroup.select('.list-group-item > .roo-PhoneInput-list-group-item-box > input:checked', true).first();
2390         
2391         var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
2392
2393         if(this.modalTitle.length){
2394             bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
2395         }
2396
2397         var listHeight = this.touchViewListGroup.getHeight();
2398         
2399         var _this = this;
2400         
2401         if(firstChecked && listHeight > bodyHeight){
2402             (function() { firstChecked.findParent('li').scrollIntoView(_this.touchViewListGroup.dom); }).defer(500);
2403         }
2404         
2405     },
2406     
2407     onTouchViewLoadException : function()
2408     {
2409         this.hideTouchView();
2410     },
2411     
2412     onTouchViewEmptyResults : function()
2413     {
2414         this.clearTouchView();
2415         
2416         this.touchViewListGroup.createChild(Roo.bootstrap.PhoneInput.emptyResult);
2417         
2418         this.touchViewListGroup.select('.roo-PhoneInput-touch-view-empty-result', true).first().dom.innerHTML = this.emptyResultText;
2419         
2420     },
2421     
2422     clearTouchView : function()
2423     {
2424         this.touchViewListGroup.dom.innerHTML = '';
2425     },
2426     
2427     onTouchViewClick : function(e, el, o)
2428     {
2429         e.preventDefault();
2430         
2431         var row = o.row;
2432         var rowIndex = o.rowIndex;
2433         
2434         var r = this.store.getAt(rowIndex);
2435         
2436         if(this.fireEvent('beforeselect', this, r, rowIndex) !== false){
2437             
2438             if(!this.multiple){
2439                 Roo.each(this.touchViewListGroup.select('.list-group-item > .roo-PhoneInput-list-group-item-box > input:checked', true).elements, function(c){
2440                     c.dom.removeAttribute('checked');
2441                 }, this);
2442
2443                 row.select('.roo-PhoneInput-list-group-item-box > input', true).first().attr('checked', true);
2444
2445                 this.setFromData(r.data);
2446
2447                 var close = this.closeTriggerEl();
2448
2449                 if(close){
2450                     close.show();
2451                 }
2452
2453                 this.hideTouchView();
2454
2455                 this.fireEvent('select', this, r, rowIndex);
2456
2457                 return;
2458             }
2459
2460             if(this.valueField && typeof(r.data[this.valueField]) != 'undefined' && this.getValue().indexOf(r.data[this.valueField]) != -1){
2461                 row.select('.roo-PhoneInput-list-group-item-box > input', true).first().dom.removeAttribute('checked');
2462                 this.tickItems.splice(this.tickItems.indexOf(r.data), 1);
2463                 return;
2464             }
2465
2466             row.select('.roo-PhoneInput-list-group-item-box > input', true).first().attr('checked', true);
2467             this.addItem(r.data);
2468             this.tickItems.push(r.data);
2469         }
2470     },
2471     
2472     getAutoCreateNativeIOS : function()
2473     {
2474         var cfg = {
2475             cls: 'form-group' //input-group,
2476         };
2477         
2478         var PhoneInput =  {
2479             tag: 'select',
2480             cls : 'roo-ios-select'
2481         };
2482         
2483         if (this.name) {
2484             PhoneInput.name = this.name;
2485         }
2486         
2487         if (this.disabled) {
2488             PhoneInput.disabled = true;
2489         }
2490         
2491         var settings = this;
2492         
2493         ['xs','sm','md','lg'].map(function(size){
2494             if (settings[size]) {
2495                 cfg.cls += ' col-' + size + '-' + settings[size];
2496             }
2497         });
2498         
2499         cfg.cn = PhoneInput;
2500         
2501         return cfg;
2502         
2503     },
2504     
2505     initIOSView : function()
2506     {
2507         this.store.on('load', this.onIOSViewLoad, this);
2508         
2509         return;
2510     },
2511     
2512     onIOSViewLoad : function()
2513     {
2514         if(this.store.getCount() < 1){
2515             return;
2516         }
2517         
2518         this.clearIOSView();
2519         
2520         if(this.allowBlank) {
2521             
2522             var default_text = '-- SELECT --';
2523             
2524             var opt = this.inputEl().createChild({
2525                 tag: 'option',
2526                 value : 0,
2527                 html : default_text
2528             });
2529             
2530             var o = {};
2531             o[this.valueField] = 0;
2532             o[this.displayField] = default_text;
2533             
2534             this.ios_options.push({
2535                 data : o,
2536                 el : opt
2537             });
2538             
2539         }
2540         
2541         this.store.data.each(function(d, rowIndex){
2542             
2543             var html = '';
2544             
2545             if(this.displayField && typeof(d.data[this.displayField]) != 'undefined'){
2546                 html = d.data[this.displayField];
2547             }
2548             
2549             var value = '';
2550             
2551             if(this.valueField && typeof(d.data[this.valueField]) != 'undefined'){
2552                 value = d.data[this.valueField];
2553             }
2554             
2555             var option = {
2556                 tag: 'option',
2557                 value : value,
2558                 html : html
2559             };
2560             
2561             if(this.value == d.data[this.valueField]){
2562                 option['selected'] = true;
2563             }
2564             
2565             var opt = this.inputEl().createChild(option);
2566             
2567             this.ios_options.push({
2568                 data : d.data,
2569                 el : opt
2570             });
2571             
2572         }, this);
2573         
2574         this.inputEl().on('change', function(){
2575            this.fireEvent('select', this);
2576         }, this);
2577         
2578     },
2579     
2580     clearIOSView: function()
2581     {
2582         this.inputEl().dom.innerHTML = '';
2583         
2584         this.ios_options = [];
2585     },
2586     
2587     setIOSValue: function(v)
2588     {
2589         this.value = v;
2590         
2591         if(!this.ios_options){
2592             return;
2593         }
2594         
2595         Roo.each(this.ios_options, function(opts){
2596            
2597            opts.el.dom.removeAttribute('selected');
2598            
2599            if(opts.data[this.valueField] != v){
2600                return;
2601            }
2602            
2603            opts.el.dom.setAttribute('selected', true);
2604            
2605         }, this);
2606     }
2607
2608     /** 
2609     * @cfg {Boolean} grow 
2610     * @hide 
2611     */
2612     /** 
2613     * @cfg {Number} growMin 
2614     * @hide 
2615     */
2616     /** 
2617     * @cfg {Number} growMax 
2618     * @hide 
2619     */
2620     /**
2621      * @hide
2622      * @method autoSize
2623      */
2624 });
2625
2626 Roo.apply(Roo.bootstrap.PhoneInput,  {
2627     
2628     header : {
2629         tag: 'div',
2630         cls: 'modal-header',
2631         cn: [
2632             {
2633                 tag: 'h4',
2634                 cls: 'modal-title'
2635             }
2636         ]
2637     },
2638     
2639     body : {
2640         tag: 'div',
2641         cls: 'modal-body',
2642         cn: [
2643             {
2644                 tag: 'ul',
2645                 cls: 'list-group'
2646             }
2647         ]
2648     },
2649     
2650     listItemRadio : {
2651         tag: 'li',
2652         cls: 'list-group-item',
2653         cn: [
2654             {
2655                 tag: 'span',
2656                 cls: 'roo-PhoneInput-list-group-item-value'
2657             },
2658             {
2659                 tag: 'div',
2660                 cls: 'roo-PhoneInput-list-group-item-box pull-xs-right radio-inline radio radio-info',
2661                 cn: [
2662                     {
2663                         tag: 'input',
2664                         type: 'radio'
2665                     },
2666                     {
2667                         tag: 'label'
2668                     }
2669                 ]
2670             }
2671         ]
2672     },
2673     
2674     listItemCheckbox : {
2675         tag: 'li',
2676         cls: 'list-group-item',
2677         cn: [
2678             {
2679                 tag: 'span',
2680                 cls: 'roo-PhoneInput-list-group-item-value'
2681             },
2682             {
2683                 tag: 'div',
2684                 cls: 'roo-PhoneInput-list-group-item-box pull-xs-right checkbox-inline checkbox checkbox-info',
2685                 cn: [
2686                     {
2687                         tag: 'input',
2688                         type: 'checkbox'
2689                     },
2690                     {
2691                         tag: 'label'
2692                     }
2693                 ]
2694             }
2695         ]
2696     },
2697     
2698     emptyResult : {
2699         tag: 'div',
2700         cls: 'alert alert-danger roo-PhoneInput-touch-view-empty-result'
2701     },
2702     
2703     footer : {
2704         tag: 'div',
2705         cls: 'modal-footer',
2706         cn: [
2707             {
2708                 tag: 'div',
2709                 cls: 'row',
2710                 cn: [
2711                     {
2712                         tag: 'div',
2713                         cls: 'col-xs-6 text-left',
2714                         cn: {
2715                             tag: 'button',
2716                             cls: 'btn btn-danger roo-touch-view-cancel',
2717                             html: 'Cancel'
2718                         }
2719                     },
2720                     {
2721                         tag: 'div',
2722                         cls: 'col-xs-6 text-right',
2723                         cn: {
2724                             tag: 'button',
2725                             cls: 'btn btn-success roo-touch-view-ok',
2726                             html: 'OK'
2727                         }
2728                     }
2729                 ]
2730             }
2731         ]
2732         
2733     }
2734 });