roojs-bootstrap.js
[roojs1] / roojs-bootstrap-debug.js
1 /*
2  * - LGPL
3  *
4  * base class for bootstrap elements.
5  * 
6  */
7
8 Roo.bootstrap = Roo.bootstrap || {};
9 /**
10  * @class Roo.bootstrap.Component
11  * @extends Roo.Component
12  * Bootstrap Component base class
13  * @cfg {String} cls css class
14  * @cfg {String} style any extra css
15  * @cfg {Object} xattr extra attributes to add to 'element' (used by builder to store stuff.)
16  * @cfg {Boolean} can_build_overlaid  True if element can be rebuild from a HTML page
17  * @cfg {string} dataId cutomer id
18  * @cfg {string} name Specifies name attribute
19  * 
20  * @constructor
21  * Do not use directly - it does not do anything..
22  * @param {Object} config The config object
23  */
24
25
26
27 Roo.bootstrap.Component = function(config){
28     Roo.bootstrap.Component.superclass.constructor.call(this, config);
29 };
30
31 Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent,  {
32     
33     
34     allowDomMove : false, // to stop relocations in parent onRender...
35     
36     cls : false,
37     
38     style : false,
39     
40     autoCreate : false,
41     
42     initEvents : function() {  },
43     
44     xattr : false,
45     
46     parentId : false,
47     
48     can_build_overlaid : true,
49     
50     dataId : false,
51     
52     name : false,
53     
54     parent: function() {
55         // returns the parent component..
56         return Roo.ComponentMgr.get(this.parentId)
57         
58         
59     },
60     
61     // private
62     onRender : function(ct, position)
63     {
64        // Roo.log("Call onRender: " + this.xtype);
65         
66         Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
67         
68         if(this.el){
69             if (this.el.attr('xtype')) {
70                 this.el.attr('xtypex', this.el.attr('xtype'));
71                 this.el.dom.removeAttribute('xtype');
72                 
73                 this.initEvents();
74             }
75             
76             return;
77         }
78         
79          
80         
81         var cfg = Roo.apply({},  this.getAutoCreate());
82         cfg.id = Roo.id();
83         
84         // fill in the extra attributes 
85         if (this.xattr && typeof(this.xattr) =='object') {
86             for (var i in this.xattr) {
87                 cfg[i] = this.xattr[i];
88             }
89         }
90         
91         if(this.dataId){
92             cfg.dataId = this.dataId;
93         }
94         
95         if (this.cls) {
96             cfg.cls = (typeof(cfg.cls) == 'undefined') ? this.cls : cfg.cls + ' ' + this.cls;
97         }
98         
99         if (this.style) { // fixme needs to support more complex style data.
100             cfg.style = this.style;
101         }
102         
103         if(this.name){
104             cfg.name = this.name;
105         }
106         
107         this.el = ct.createChild(cfg, position);
108         
109         if(this.tabIndex !== undefined){
110             this.el.dom.setAttribute('tabIndex', this.tabIndex);
111         }
112         this.initEvents();
113         
114         
115     },
116     
117     getChildContainer : function()
118     {
119         return this.el;
120     },
121     
122     
123     addxtype  : function(tree,cntr)
124     {
125         var cn = this;
126         
127         cn = Roo.factory(tree);
128            
129         cn.parentType = this.xtype; //??
130         cn.parentId = this.id;
131         
132         cntr = (typeof(cntr) == 'undefined' ) ? 'getChildContainer' : cntr;
133         
134         var has_flexy_each =  (typeof(tree['flexy:foreach']) != 'undefined');
135         
136         var has_flexy_if =  (typeof(tree['flexy:if']) != 'undefined');
137         
138         var build_from_html =  Roo.XComponent.build_from_html;
139           
140         var is_body  = (tree.xtype == 'Body') ;
141           
142         var page_has_body = (Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body');
143           
144         var self_cntr_el = Roo.get(this[cntr]());
145         
146         if (!has_flexy_each || !build_from_html || is_body || !page_has_body) {
147             if(!has_flexy_if || typeof(tree.name) == 'undefined' || !build_from_html || is_body || !page_has_body){
148                 return this.addxtypeChild(tree,cntr);
149             }
150             
151             var echild =self_cntr_el ? self_cntr_el.child('>*[name=' + tree.name + ']') : false;
152                 
153             if(echild){
154                 return this.addxtypeChild(Roo.apply({}, tree),cntr);
155             }
156             
157             Roo.log('skipping render');
158             return cn;
159             
160         }
161         
162         var ret = false;
163         
164         while (true) {
165             var echild =self_cntr_el ? self_cntr_el.child('>*[xtype]') : false;
166             
167             if (!echild) {
168                 break;
169             }
170             
171             if (echild && echild.attr('xtype').split('.').pop() != cn.xtype) {
172                 break;
173             }
174             
175             ret = this.addxtypeChild(Roo.apply({}, tree),cntr);
176         }
177         return ret;
178     },
179     
180     addxtypeChild : function (tree, cntr)
181     {
182         Roo.log('addxtypeChild:' + cntr);
183         var cn = this;
184         cntr = (typeof(cntr) == 'undefined' ) ? 'getChildContainer' : cntr;
185         
186         
187         var has_flexy = (typeof(tree['flexy:if']) != 'undefined') ||
188                     (typeof(tree['flexy:foreach']) != 'undefined');
189           
190         
191         
192         
193         // render the element if it's not BODY.
194         if (tree.xtype != 'Body') {
195            
196             cn = Roo.factory(tree);
197            
198             cn.parentType = this.xtype; //??
199             cn.parentId = this.id;
200             
201             var build_from_html =  Roo.XComponent.build_from_html;
202             
203             
204             // does the container contain child eleemnts with 'xtype' attributes.
205             // that match this xtype..
206             // note - when we render we create these as well..
207             // so we should check to see if body has xtype set.
208             if (Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body') {
209                
210                 var self_cntr_el = Roo.get(this[cntr]());
211                 var echild =self_cntr_el ? self_cntr_el.child('>*[xtype]') : false;
212                 
213                 if (echild && echild.attr('xtype').split('.').pop() == cn.xtype) {
214                   //  Roo.log("found child for " + this.xtype +": " + echild.attr('xtype') );
215                   
216                   
217                   
218                     cn.el = echild;
219                   //  Roo.log("GOT");
220                     //echild.dom.removeAttribute('xtype');
221                 } else {
222                     Roo.log("MISSING " + cn.xtype + " on child of " + (this.el ? this.el.attr('xbuilderid') : 'no parent'));
223                    
224                 }
225             }
226            
227             
228                
229             // if object has flexy:if - then it may or may not be rendered.
230             if (build_from_html && has_flexy && !cn.el &&  cn.can_build_overlaid) {
231                 // skip a flexy if element.
232                 Roo.log('skipping render');
233              } else {
234                  
235                 // actually if flexy:foreach is found, we really want to create 
236                 // multiple copies here...
237                 //Roo.log('render');
238                 //Roo.log(this[cntr]());
239                 cn.render(this[cntr]());
240              }
241             // then add the element..
242         }
243         
244         
245         // handle the kids..
246         
247         var nitems = [];
248         /*
249         if (typeof (tree.menu) != 'undefined') {
250             tree.menu.parentType = cn.xtype;
251             tree.menu.triggerEl = cn.el;
252             nitems.push(cn.addxtype(Roo.apply({}, tree.menu)));
253             
254         }
255         */
256         if (!tree.items || !tree.items.length) {
257             cn.items = nitems;
258             return cn;
259         }
260         var items = tree.items;
261         delete tree.items;
262         
263         //Roo.log(items.length);
264             // add the items..
265         for(var i =0;i < items.length;i++) {
266             nitems.push(cn.addxtype(Roo.apply({}, items[i])));
267         }
268         
269         cn.items = nitems;
270         
271         return cn;
272     }
273     
274     
275     
276     
277 });
278
279  /*
280  * - LGPL
281  *
282  * Body
283  * 
284  */
285
286 /**
287  * @class Roo.bootstrap.Body
288  * @extends Roo.bootstrap.Component
289  * Bootstrap Body class
290  * 
291  * @constructor
292  * Create a new body
293  * @param {Object} config The config object
294  */
295
296 Roo.bootstrap.Body = function(config){
297     Roo.bootstrap.Body.superclass.constructor.call(this, config);
298     this.el = Roo.get(document.body);
299     if (this.cls && this.cls.length) {
300         Roo.get(document.body).addClass(this.cls);
301     }
302 };
303
304 Roo.extend(Roo.bootstrap.Body, Roo.bootstrap.Component,  {
305       
306         autoCreate : {
307         cls: 'container'
308     },
309     onRender : function(ct, position)
310     {
311        /* Roo.log("Roo.bootstrap.Body - onRender");
312         if (this.cls && this.cls.length) {
313             Roo.get(document.body).addClass(this.cls);
314         }
315         // style??? xttr???
316         */
317     }
318     
319     
320  
321    
322 });
323
324  /*
325  * - LGPL
326  *
327  * button group
328  * 
329  */
330
331
332 /**
333  * @class Roo.bootstrap.ButtonGroup
334  * @extends Roo.bootstrap.Component
335  * Bootstrap ButtonGroup class
336  * @cfg {String} size lg | sm | xs (default empty normal)
337  * @cfg {String} align vertical | justified  (default none)
338  * @cfg {String} direction up | down (default down)
339  * @cfg {Boolean} toolbar false | true
340  * @cfg {Boolean} btn true | false
341  * 
342  * 
343  * @constructor
344  * Create a new Input
345  * @param {Object} config The config object
346  */
347
348 Roo.bootstrap.ButtonGroup = function(config){
349     Roo.bootstrap.ButtonGroup.superclass.constructor.call(this, config);
350 };
351
352 Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component,  {
353     
354     size: '',
355     align: '',
356     direction: '',
357     toolbar: false,
358     btn: true,
359
360     getAutoCreate : function(){
361         var cfg = {
362             cls: 'btn-group',
363             html : null
364         }
365         
366         cfg.html = this.html || cfg.html;
367         
368         if (this.toolbar) {
369             cfg = {
370                 cls: 'btn-toolbar',
371                 html: null
372             }
373             
374             return cfg;
375         }
376         
377         if (['vertical','justified'].indexOf(this.align)!==-1) {
378             cfg.cls = 'btn-group-' + this.align;
379             
380             if (this.align == 'justified') {
381                 console.log(this.items);
382             }
383         }
384         
385         if (['lg','sm','xs'].indexOf(this.size)!==-1) {
386             cfg.cls += ' btn-group-' + this.size;
387         }
388         
389         if (this.direction == 'up') {
390             cfg.cls += ' dropup' ;
391         }
392         
393         return cfg;
394     }
395    
396 });
397
398  /*
399  * - LGPL
400  *
401  * button
402  * 
403  */
404
405 /**
406  * @class Roo.bootstrap.Button
407  * @extends Roo.bootstrap.Component
408  * Bootstrap Button class
409  * @cfg {String} html The button content
410  * @cfg {String} weight default (or empty) | primary | success | info | warning | danger | link
411  * @cfg {String} size empty | lg | sm | xs
412  * @cfg {String} tag empty | a | input | submit
413  * @cfg {String} href empty or href
414  * @cfg {Boolean} disabled false | true
415  * @cfg {Boolean} isClose false | true
416  * @cfg {String} glyphicon empty | adjust | align-center | align-justify | align-left | align-right | arrow-down | arrow-left | arrow-right | arrow-up | asterisk | backward | ban-circle | barcode | bell | bold | book | bookmark | briefcase | bullhorn | calendar | camera | certificate | check | chevron-down | chevron-left | chevron-right | chevron-up | circle-arrow-down | circle-arrow-left | circle-arrow-right | circle-arrow-up | cloud | cloud-download | cloud-upload | cog | collapse-down | collapse-up | comment | compressed | copyright-mark | credit-card | cutlery | dashboard | download | download-alt | earphone | edit | eject | envelope | euro | exclamation-sign | expand | export | eye-close | eye-open | facetime-video | fast-backward | fast-forward | file | film | filter | fire | flag | flash | floppy-disk | floppy-open | floppy-remove | floppy-save | floppy-saved | folder-close | folder-open | font | forward | fullscreen | gbp | gift | glass | globe | hand-down | hand-left | hand-right | hand-up | hd-video | hdd | header | headphones | heart | heart-empty | home | import | inbox | indent-left | indent-right | info-sign | italic | leaf | link | list | list-alt | lock | log-in | log-out | magnet | map-marker | minus | minus-sign | move | music | new-window | off | ok | ok-circle | ok-sign | open | paperclip | pause | pencil | phone | phone-alt | picture | plane | play | play-circle | plus | plus-sign | print | pushpin | qrcode | question-sign | random | record | refresh | registration-mark | remove | remove-circle | remove-sign | repeat | resize-full | resize-horizontal | resize-small | resize-vertical | retweet | road | save | saved | screenshot | sd-video | search | send | share | share-alt | shopping-cart | signal | sort | sort-by-alphabet | sort-by-alphabet-alt | sort-by-attributes | sort-by-attributes-alt | sort-by-order | sort-by-order-alt | sound-5-1 | sound-6-1 | sound-7-1 | sound-dolby | sound-stereo | star | star-empty | stats | step-backward | step-forward | stop | subtitles | tag | tags | tasks | text-height | text-width | th | th-large | th-list | thumbs-down | thumbs-up | time | tint | tower | transfer | trash | tree-conifer | tree-deciduous | unchecked | upload | usd | user | volume-down | volume-off | volume-up | warning-sign | wrench | zoom-in | zoom-out
417  * @cfg {String} badge text for badge
418  * @cfg {String} theme default (or empty) | glow
419  * @cfg {Boolean} inverse false | true
420  * @cfg {Boolean} toggle false | true
421  * @cfg {String} ontext text for on toggle state
422  * @cfg {String} offtext text for off toggle state
423  * @cfg {Boolean} defaulton true | false
424  * @cfg {Boolean} preventDefault (true | false) default true
425  * @cfg {Boolean} removeClass true | false remove the standard class..
426  * @cfg {String} target (_self|_blank|_parent|_top)target for a href.
427  * 
428  * @constructor
429  * Create a new button
430  * @param {Object} config The config object
431  */
432
433
434 Roo.bootstrap.Button = function(config){
435     Roo.bootstrap.Button.superclass.constructor.call(this, config);
436     this.addEvents({
437         // raw events
438         /**
439          * @event click
440          * When a butotn is pressed
441          * @param {Roo.EventObject} e
442          */
443         "click" : true,
444          /**
445          * @event toggle
446          * After the button has been toggles
447          * @param {Roo.EventObject} e
448          * @param {boolean} pressed (also available as button.pressed)
449          */
450         "toggle" : true
451     });
452 };
453
454 Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
455     html: false,
456     active: false,
457     weight: '',
458     size: '',
459     tag: 'button',
460     href: '',
461     disabled: false,
462     isClose: false,
463     glyphicon: '',
464     badge: '',
465     theme: 'default',
466     inverse: false,
467     
468     toggle: false,
469     ontext: 'ON',
470     offtext: 'OFF',
471     defaulton: true,
472     preventDefault: true,
473     removeClass: false,
474     name: false,
475     target: false,
476     
477     
478     pressed : null,
479      
480     
481     getAutoCreate : function(){
482         
483         var cfg = {
484             tag : 'button',
485             cls : 'roo-button',
486             html: ''
487         };
488         
489         if (['a', 'button', 'input', 'submit'].indexOf(this.tag) < 0) {
490             throw "Invalid value for tag: " + this.tag + ". must be a, button, input or submit.";
491             this.tag = 'button';
492         } else {
493             cfg.tag = this.tag;
494         }
495         cfg.html = '<span class="roo-button-text">' + (this.html || cfg.html) + '</span>';
496         
497         if (this.toggle == true) {
498             cfg={
499                 tag: 'div',
500                 cls: 'slider-frame roo-button',
501                 cn: [
502                     {
503                         tag: 'span',
504                         'data-on-text':'ON',
505                         'data-off-text':'OFF',
506                         cls: 'slider-button',
507                         html: this.offtext
508                     }
509                 ]
510             };
511             
512             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
513                 cfg.cls += ' '+this.weight;
514             }
515             
516             return cfg;
517         }
518         
519         if (this.isClose) {
520             cfg.cls += ' close';
521             
522             cfg["aria-hidden"] = true;
523             
524             cfg.html = "&times;";
525             
526             return cfg;
527         }
528         
529          
530         if (this.theme==='default') {
531             cfg.cls = 'btn roo-button';
532             
533             //if (this.parentType != 'Navbar') {
534             this.weight = this.weight.length ?  this.weight : 'default';
535             //}
536             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
537                 
538                 cfg.cls += ' btn-' + this.weight;
539             }
540         } else if (this.theme==='glow') {
541             
542             cfg.tag = 'a';
543             cfg.cls = 'btn-glow roo-button';
544             
545             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
546                 
547                 cfg.cls += ' ' + this.weight;
548             }
549         }
550    
551         
552         if (this.inverse) {
553             this.cls += ' inverse';
554         }
555         
556         
557         if (this.active) {
558             cfg.cls += ' active';
559         }
560         
561         if (this.disabled) {
562             cfg.disabled = 'disabled';
563         }
564         
565         if (this.items) {
566             Roo.log('changing to ul' );
567             cfg.tag = 'ul';
568             this.glyphicon = 'caret';
569         }
570         
571         cfg.cls += this.size.length ? (' btn-' + this.size) : '';
572          
573         //gsRoo.log(this.parentType);
574         if (this.parentType === 'Navbar' && !this.parent().bar) {
575             Roo.log('changing to li?');
576             
577             cfg.tag = 'li';
578             
579             cfg.cls = '';
580             cfg.cn =  [{
581                 tag : 'a',
582                 cls : 'roo-button',
583                 html : this.html,
584                 href : this.href || '#'
585             }];
586             if (this.menu) {
587                 cfg.cn[0].html = this.html  + ' <span class="caret"></span>';
588                 cfg.cls += ' dropdown';
589             }   
590             
591             delete cfg.html;
592             
593         }
594         
595        cfg.cls += this.parentType === 'Navbar' ?  ' navbar-btn' : '';
596         
597         if (this.glyphicon) {
598             cfg.html = ' ' + cfg.html;
599             
600             cfg.cn = [
601                 {
602                     tag: 'span',
603                     cls: 'glyphicon glyphicon-' + this.glyphicon
604                 }
605             ];
606         }
607         
608         if (this.badge) {
609             cfg.html += ' ';
610             
611             cfg.tag = 'a';
612             
613 //            cfg.cls='btn roo-button';
614             
615             cfg.href=this.href;
616             
617             var value = cfg.html;
618             
619             if(this.glyphicon){
620                 value = {
621                             tag: 'span',
622                             cls: 'glyphicon glyphicon-' + this.glyphicon,
623                             html: this.html
624                         };
625                 
626             }
627             
628             cfg.cn = [
629                 value,
630                 {
631                     tag: 'span',
632                     cls: 'badge',
633                     html: this.badge
634                 }
635             ];
636             
637             cfg.html='';
638         }
639         
640         if (this.menu) {
641             cfg.cls += ' dropdown';
642             cfg.html = typeof(cfg.html) != 'undefined' ? cfg.html + ' <span class="caret"></span>' : '<span class="caret"></span>';
643         }
644         
645         if (cfg.tag !== 'a' && this.href !== '') {
646             throw "Tag must be a to set href.";
647         } else if (this.href.length > 0) {
648             cfg.href = this.href;
649         }
650         
651         if(this.removeClass){
652             cfg.cls = '';
653         }
654         
655         if(this.target){
656             cfg.target = this.target;
657         }
658         
659         return cfg;
660     },
661     initEvents: function() {
662        // Roo.log('init events?');
663 //        Roo.log(this.el.dom);
664        if (this.el.hasClass('roo-button')) {
665             this.el.on('click', this.onClick, this);
666        } else {
667             this.el.select('.roo-button').on('click', this.onClick, this);
668        }
669        
670        if(this.removeClass){
671            this.el.on('click', this.onClick, this);
672        }
673        
674        this.el.enableDisplayMode();
675         
676     },
677     onClick : function(e)
678     {
679         if (this.disabled) {
680             return;
681         }
682         
683         Roo.log('button on click ');
684         if(this.preventDefault){
685             e.preventDefault();
686         }
687         if (this.pressed === true || this.pressed === false) {
688             this.pressed = !this.pressed;
689             this.el[this.pressed ? 'addClass' : 'removeClass']('active');
690             this.fireEvent('toggle', this, e, this.pressed);
691         }
692         
693         
694         this.fireEvent('click', this, e);
695     },
696     
697     /**
698      * Enables this button
699      */
700     enable : function()
701     {
702         this.disabled = false;
703         this.el.removeClass('disabled');
704     },
705     
706     /**
707      * Disable this button
708      */
709     disable : function()
710     {
711         this.disabled = true;
712         this.el.addClass('disabled');
713     },
714      /**
715      * sets the active state on/off, 
716      * @param {Boolean} state (optional) Force a particular state
717      */
718     setActive : function(v) {
719         
720         this.el[v ? 'addClass' : 'removeClass']('active');
721     },
722      /**
723      * toggles the current active state 
724      */
725     toggleActive : function()
726     {
727        var active = this.el.hasClass('active');
728        this.setActive(!active);
729        
730         
731     },
732     setText : function(str)
733     {
734         this.el.select('.roo-button-text',true).first().dom.innerHTML = str;
735     },
736     hide: function() {
737        
738      
739         this.el.hide();   
740     },
741     show: function() {
742        
743         this.el.show();   
744     }
745     
746     
747 });
748
749  /*
750  * - LGPL
751  *
752  * column
753  * 
754  */
755
756 /**
757  * @class Roo.bootstrap.Column
758  * @extends Roo.bootstrap.Component
759  * Bootstrap Column class
760  * @cfg {Number} xs colspan out of 12 for mobile-sized screens
761  * @cfg {Number} sm colspan out of 12 for tablet-sized screens
762  * @cfg {Number} md colspan out of 12 for computer-sized screens
763  * @cfg {Number} lg colspan out of 12 for large computer-sized screens
764  * @cfg {String} html content of column.
765  * 
766  * @constructor
767  * Create a new Column
768  * @param {Object} config The config object
769  */
770
771 Roo.bootstrap.Column = function(config){
772     Roo.bootstrap.Column.superclass.constructor.call(this, config);
773 };
774
775 Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
776     
777     xs: null,
778     sm: null,
779     md: null,
780     lg: null,
781     html: '',
782     offset: 0,
783     
784     getAutoCreate : function(){
785         var cfg = Roo.apply({}, Roo.bootstrap.Column.superclass.getAutoCreate.call(this));
786         
787         cfg = {
788             tag: 'div',
789             cls: 'column'
790         };
791         
792         var settings=this;
793         ['xs','sm','md','lg'].map(function(size){
794             if (settings[size]) {
795                 cfg.cls += ' col-' + size + '-' + settings[size];
796             }
797         });
798         if (this.html.length) {
799             cfg.html = this.html;
800         }
801         
802         return cfg;
803     }
804    
805 });
806
807  
808
809  /*
810  * - LGPL
811  *
812  * page container.
813  * 
814  */
815
816
817 /**
818  * @class Roo.bootstrap.Container
819  * @extends Roo.bootstrap.Component
820  * Bootstrap Container class
821  * @cfg {Boolean} jumbotron is it a jumbotron element
822  * @cfg {String} html content of element
823  * @cfg {String} well (lg|sm|md) a well, large, small or medium.
824  * @cfg {String} panel (primary|success|info|warning|danger) render as a panel.
825  * @cfg {String} header content of header (for panel)
826  * @cfg {String} footer content of footer (for panel)
827  * @cfg {String} sticky (footer|wrap|push) block to use as footer or body- needs css-bootstrap/sticky-footer.css
828  * @cfg {String} tag (header|aside|section) type of HTML tag.
829
830  *     
831  * @constructor
832  * Create a new Container
833  * @param {Object} config The config object
834  */
835
836 Roo.bootstrap.Container = function(config){
837     Roo.bootstrap.Container.superclass.constructor.call(this, config);
838 };
839
840 Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
841     
842     jumbotron : false,
843     well: '',
844     panel : '',
845     header: '',
846     footer : '',
847     sticky: '',
848     tag : false,
849   
850      
851     getChildContainer : function() {
852         
853         if(!this.el){
854             return false;
855         }
856         
857         if (this.panel.length) {
858             return this.el.select('.panel-body',true).first();
859         }
860         
861         return this.el;
862     },
863     
864     
865     getAutoCreate : function(){
866         
867         var cfg = {
868             tag : this.tag || 'div',
869             html : '',
870             cls : ''
871         };
872         if (this.jumbotron) {
873             cfg.cls = 'jumbotron';
874         }
875         // - this is applied by the parent..
876         //if (this.cls) {
877         //    cfg.cls = this.cls + '';
878         //}
879         
880         if (this.sticky.length) {
881             
882             var bd = Roo.get(document.body);
883             if (!bd.hasClass('bootstrap-sticky')) {
884                 bd.addClass('bootstrap-sticky');
885                 Roo.select('html',true).setStyle('height', '100%');
886             }
887              
888             cfg.cls += 'bootstrap-sticky-' + this.sticky;
889         }
890         
891         
892         if (this.well.length) {
893             switch (this.well) {
894                 case 'lg':
895                 case 'sm':
896                     cfg.cls +=' well well-' +this.well;
897                     break;
898                 default:
899                     cfg.cls +=' well';
900                     break;
901             }
902         }
903         
904         var body = cfg;
905         
906         if (this.panel.length) {
907             cfg.cls += ' panel panel-' + this.panel;
908             cfg.cn = [];
909             if (this.header.length) {
910                 cfg.cn.push({
911                     
912                     cls : 'panel-heading',
913                     cn : [{
914                         tag: 'h3',
915                         cls : 'panel-title',
916                         html : this.header
917                     }]
918                     
919                 });
920             }
921             body = false;
922             cfg.cn.push({
923                 cls : 'panel-body',
924                 html : this.html
925             });
926             
927             
928             if (this.footer.length) {
929                 cfg.cn.push({
930                     cls : 'panel-footer',
931                     html : this.footer
932                     
933                 });
934             }
935             
936         }
937         
938         if (body) {
939             body.html = this.html || cfg.html;
940         }
941         if ((!this.cls || !this.cls.length) && (!cfg.cls || !cfg.cls.length)) {
942             cfg.cls =  'container';
943         }
944         
945         return cfg;
946     }
947    
948 });
949
950  /*
951  * - LGPL
952  *
953  * image
954  * 
955  */
956
957
958 /**
959  * @class Roo.bootstrap.Img
960  * @extends Roo.bootstrap.Component
961  * Bootstrap Img class
962  * @cfg {Boolean} imgResponsive false | true
963  * @cfg {String} border rounded | circle | thumbnail
964  * @cfg {String} src image source
965  * @cfg {String} alt image alternative text
966  * @cfg {String} href a tag href
967  * @cfg {String} target (_self|_blank|_parent|_top)target for a href.
968  * 
969  * @constructor
970  * Create a new Input
971  * @param {Object} config The config object
972  */
973
974 Roo.bootstrap.Img = function(config){
975     Roo.bootstrap.Img.superclass.constructor.call(this, config);
976     
977     this.addEvents({
978         // img events
979         /**
980          * @event click
981          * The img click event for the img.
982          * @param {Roo.EventObject} e
983          */
984         "click" : true
985     });
986 };
987
988 Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
989     
990     imgResponsive: true,
991     border: '',
992     src: '',
993     href: false,
994     target: false,
995
996     getAutoCreate : function(){
997         
998         var cfg = {
999             tag: 'img',
1000             cls: (this.imgResponsive) ? 'img-responsive' : '',
1001             html : null
1002         }
1003         
1004         cfg.html = this.html || cfg.html;
1005         
1006         cfg.src = this.src || cfg.src;
1007         
1008         if (['rounded','circle','thumbnail'].indexOf(this.border)>-1) {
1009             cfg.cls += ' img-' + this.border;
1010         }
1011         
1012         if(this.alt){
1013             cfg.alt = this.alt;
1014         }
1015         
1016         if(this.href){
1017             var a = {
1018                 tag: 'a',
1019                 href: this.href,
1020                 cn: [
1021                     cfg
1022                 ]
1023             }
1024             
1025             if(this.target){
1026                 a.target = this.target;
1027             }
1028             
1029         }
1030         
1031         
1032         return (this.href) ? a : cfg;
1033     },
1034     
1035     initEvents: function() {
1036         
1037         if(!this.href){
1038             this.el.on('click', this.onClick, this);
1039         }
1040     },
1041     
1042     onClick : function(e)
1043     {
1044         Roo.log('img onclick');
1045         this.fireEvent('click', this, e);
1046     }
1047    
1048 });
1049
1050  /*
1051  * - LGPL
1052  *
1053  * image
1054  * 
1055  */
1056
1057
1058 /**
1059  * @class Roo.bootstrap.Link
1060  * @extends Roo.bootstrap.Component
1061  * Bootstrap Link Class
1062  * @cfg {String} alt image alternative text
1063  * @cfg {String} href a tag href
1064  * @cfg {String} target (_self|_blank|_parent|_top) target for a href.
1065  * @cfg {String} html the content of the link.
1066
1067  * 
1068  * @constructor
1069  * Create a new Input
1070  * @param {Object} config The config object
1071  */
1072
1073 Roo.bootstrap.Link = function(config){
1074     Roo.bootstrap.Link.superclass.constructor.call(this, config);
1075     
1076     this.addEvents({
1077         // img events
1078         /**
1079          * @event click
1080          * The img click event for the img.
1081          * @param {Roo.EventObject} e
1082          */
1083         "click" : true
1084     });
1085 };
1086
1087 Roo.extend(Roo.bootstrap.Link, Roo.bootstrap.Component,  {
1088     
1089     href: false,
1090     target: false,
1091
1092     getAutoCreate : function(){
1093         
1094         var cfg = {
1095             tag: 'a',
1096             html : this.html || 'html-missing'
1097         }
1098         
1099         
1100         if(this.alt){
1101             cfg.alt = this.alt;
1102         }
1103         cfg.href = this.href || '#';
1104         if(this.target){
1105             cfg.target = this.target;
1106         }
1107         
1108         return cfg;
1109     },
1110     
1111     initEvents: function() {
1112         
1113         if(!this.href){
1114             this.el.on('click', this.onClick, this);
1115         }
1116     },
1117     
1118     onClick : function(e)
1119     {
1120         //Roo.log('img onclick');
1121         this.fireEvent('click', this, e);
1122     }
1123    
1124 });
1125
1126  /*
1127  * - LGPL
1128  *
1129  * header
1130  * 
1131  */
1132
1133 /**
1134  * @class Roo.bootstrap.Header
1135  * @extends Roo.bootstrap.Component
1136  * Bootstrap Header class
1137  * @cfg {String} html content of header
1138  * @cfg {Number} level (1|2|3|4|5|6) default 1
1139  * 
1140  * @constructor
1141  * Create a new Header
1142  * @param {Object} config The config object
1143  */
1144
1145
1146 Roo.bootstrap.Header  = function(config){
1147     Roo.bootstrap.Header.superclass.constructor.call(this, config);
1148 };
1149
1150 Roo.extend(Roo.bootstrap.Header, Roo.bootstrap.Component,  {
1151     
1152     //href : false,
1153     html : false,
1154     level : 1,
1155     
1156     
1157     
1158     getAutoCreate : function(){
1159         
1160         var cfg = {
1161             tag: 'h' + (1 *this.level),
1162             html: this.html || 'fill in html'
1163         } ;
1164         
1165         return cfg;
1166     }
1167    
1168 });
1169
1170  
1171
1172  /*
1173  * Based on:
1174  * Ext JS Library 1.1.1
1175  * Copyright(c) 2006-2007, Ext JS, LLC.
1176  *
1177  * Originally Released Under LGPL - original licence link has changed is not relivant.
1178  *
1179  * Fork - LGPL
1180  * <script type="text/javascript">
1181  */
1182  
1183 /**
1184  * @class Roo.bootstrap.MenuMgr
1185  * Provides a common registry of all menu items on a page so that they can be easily accessed by id.
1186  * @singleton
1187  */
1188 Roo.bootstrap.MenuMgr = function(){
1189    var menus, active, groups = {}, attached = false, lastShow = new Date();
1190
1191    // private - called when first menu is created
1192    function init(){
1193        menus = {};
1194        active = new Roo.util.MixedCollection();
1195        Roo.get(document).addKeyListener(27, function(){
1196            if(active.length > 0){
1197                hideAll();
1198            }
1199        });
1200    }
1201
1202    // private
1203    function hideAll(){
1204        if(active && active.length > 0){
1205            var c = active.clone();
1206            c.each(function(m){
1207                m.hide();
1208            });
1209        }
1210    }
1211
1212    // private
1213    function onHide(m){
1214        active.remove(m);
1215        if(active.length < 1){
1216            Roo.get(document).un("mouseup", onMouseDown);
1217             
1218            attached = false;
1219        }
1220    }
1221
1222    // private
1223    function onShow(m){
1224        var last = active.last();
1225        lastShow = new Date();
1226        active.add(m);
1227        if(!attached){
1228           Roo.get(document).on("mouseup", onMouseDown);
1229            
1230            attached = true;
1231        }
1232        if(m.parentMenu){
1233           //m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
1234           m.parentMenu.activeChild = m;
1235        }else if(last && last.isVisible()){
1236           //m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
1237        }
1238    }
1239
1240    // private
1241    function onBeforeHide(m){
1242        if(m.activeChild){
1243            m.activeChild.hide();
1244        }
1245        if(m.autoHideTimer){
1246            clearTimeout(m.autoHideTimer);
1247            delete m.autoHideTimer;
1248        }
1249    }
1250
1251    // private
1252    function onBeforeShow(m){
1253        var pm = m.parentMenu;
1254        if(!pm && !m.allowOtherMenus){
1255            hideAll();
1256        }else if(pm && pm.activeChild && active != m){
1257            pm.activeChild.hide();
1258        }
1259    }
1260
1261    // private
1262    function onMouseDown(e){
1263         Roo.log("on MouseDown");
1264         if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
1265            hideAll();
1266         }
1267         
1268         
1269    }
1270
1271    // private
1272    function onBeforeCheck(mi, state){
1273        if(state){
1274            var g = groups[mi.group];
1275            for(var i = 0, l = g.length; i < l; i++){
1276                if(g[i] != mi){
1277                    g[i].setChecked(false);
1278                }
1279            }
1280        }
1281    }
1282
1283    return {
1284
1285        /**
1286         * Hides all menus that are currently visible
1287         */
1288        hideAll : function(){
1289             hideAll();  
1290        },
1291
1292        // private
1293        register : function(menu){
1294            if(!menus){
1295                init();
1296            }
1297            menus[menu.id] = menu;
1298            menu.on("beforehide", onBeforeHide);
1299            menu.on("hide", onHide);
1300            menu.on("beforeshow", onBeforeShow);
1301            menu.on("show", onShow);
1302            var g = menu.group;
1303            if(g && menu.events["checkchange"]){
1304                if(!groups[g]){
1305                    groups[g] = [];
1306                }
1307                groups[g].push(menu);
1308                menu.on("checkchange", onCheck);
1309            }
1310        },
1311
1312         /**
1313          * Returns a {@link Roo.menu.Menu} object
1314          * @param {String/Object} menu The string menu id, an existing menu object reference, or a Menu config that will
1315          * be used to generate and return a new Menu instance.
1316          */
1317        get : function(menu){
1318            if(typeof menu == "string"){ // menu id
1319                return menus[menu];
1320            }else if(menu.events){  // menu instance
1321                return menu;
1322            }
1323            /*else if(typeof menu.length == 'number'){ // array of menu items?
1324                return new Roo.bootstrap.Menu({items:menu});
1325            }else{ // otherwise, must be a config
1326                return new Roo.bootstrap.Menu(menu);
1327            }
1328            */
1329            return false;
1330        },
1331
1332        // private
1333        unregister : function(menu){
1334            delete menus[menu.id];
1335            menu.un("beforehide", onBeforeHide);
1336            menu.un("hide", onHide);
1337            menu.un("beforeshow", onBeforeShow);
1338            menu.un("show", onShow);
1339            var g = menu.group;
1340            if(g && menu.events["checkchange"]){
1341                groups[g].remove(menu);
1342                menu.un("checkchange", onCheck);
1343            }
1344        },
1345
1346        // private
1347        registerCheckable : function(menuItem){
1348            var g = menuItem.group;
1349            if(g){
1350                if(!groups[g]){
1351                    groups[g] = [];
1352                }
1353                groups[g].push(menuItem);
1354                menuItem.on("beforecheckchange", onBeforeCheck);
1355            }
1356        },
1357
1358        // private
1359        unregisterCheckable : function(menuItem){
1360            var g = menuItem.group;
1361            if(g){
1362                groups[g].remove(menuItem);
1363                menuItem.un("beforecheckchange", onBeforeCheck);
1364            }
1365        }
1366    };
1367 }();/*
1368  * - LGPL
1369  *
1370  * menu
1371  * 
1372  */
1373
1374 /**
1375  * @class Roo.bootstrap.Menu
1376  * @extends Roo.bootstrap.Component
1377  * Bootstrap Menu class - container for MenuItems
1378  * @cfg {String} type (dropdown|treeview|submenu) type of menu
1379  * 
1380  * @constructor
1381  * Create a new Menu
1382  * @param {Object} config The config object
1383  */
1384
1385
1386 Roo.bootstrap.Menu = function(config){
1387     Roo.bootstrap.Menu.superclass.constructor.call(this, config);
1388     if (this.registerMenu) {
1389         Roo.bootstrap.MenuMgr.register(this);
1390     }
1391     this.addEvents({
1392         /**
1393          * @event beforeshow
1394          * Fires before this menu is displayed
1395          * @param {Roo.menu.Menu} this
1396          */
1397         beforeshow : true,
1398         /**
1399          * @event beforehide
1400          * Fires before this menu is hidden
1401          * @param {Roo.menu.Menu} this
1402          */
1403         beforehide : true,
1404         /**
1405          * @event show
1406          * Fires after this menu is displayed
1407          * @param {Roo.menu.Menu} this
1408          */
1409         show : true,
1410         /**
1411          * @event hide
1412          * Fires after this menu is hidden
1413          * @param {Roo.menu.Menu} this
1414          */
1415         hide : true,
1416         /**
1417          * @event click
1418          * Fires when this menu is clicked (or when the enter key is pressed while it is active)
1419          * @param {Roo.menu.Menu} this
1420          * @param {Roo.menu.Item} menuItem The menu item that was clicked
1421          * @param {Roo.EventObject} e
1422          */
1423         click : true,
1424         /**
1425          * @event mouseover
1426          * Fires when the mouse is hovering over this menu
1427          * @param {Roo.menu.Menu} this
1428          * @param {Roo.EventObject} e
1429          * @param {Roo.menu.Item} menuItem The menu item that was clicked
1430          */
1431         mouseover : true,
1432         /**
1433          * @event mouseout
1434          * Fires when the mouse exits this menu
1435          * @param {Roo.menu.Menu} this
1436          * @param {Roo.EventObject} e
1437          * @param {Roo.menu.Item} menuItem The menu item that was clicked
1438          */
1439         mouseout : true,
1440         /**
1441          * @event itemclick
1442          * Fires when a menu item contained in this menu is clicked
1443          * @param {Roo.menu.BaseItem} baseItem The BaseItem that was clicked
1444          * @param {Roo.EventObject} e
1445          */
1446         itemclick: true
1447     });
1448     this.menuitems = new Roo.util.MixedCollection(false, function(o) { return o.el.id; });
1449 };
1450
1451 Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
1452     
1453    /// html : false,
1454     //align : '',
1455     triggerEl : false,  // is this set by component builder? -- it should really be fetched from parent()???
1456     type: false,
1457     /**
1458      * @cfg {Boolean} registerMenu True (default) - means that clicking on screen etc. hides it.
1459      */
1460     registerMenu : true,
1461     
1462     menuItems :false, // stores the menu items..
1463     
1464     hidden:true,
1465     
1466     parentMenu : false,
1467     
1468     getChildContainer : function() {
1469         return this.el;  
1470     },
1471     
1472     getAutoCreate : function(){
1473          
1474         //if (['right'].indexOf(this.align)!==-1) {
1475         //    cfg.cn[1].cls += ' pull-right'
1476         //}
1477         
1478         
1479         var cfg = {
1480             tag : 'ul',
1481             cls : 'dropdown-menu' ,
1482             style : 'z-index:1000'
1483             
1484         }
1485         
1486         if (this.type === 'submenu') {
1487             cfg.cls = 'submenu active';
1488         }
1489         if (this.type === 'treeview') {
1490             cfg.cls = 'treeview-menu';
1491         }
1492         
1493         return cfg;
1494     },
1495     initEvents : function() {
1496         
1497        // Roo.log("ADD event");
1498        // Roo.log(this.triggerEl.dom);
1499         this.triggerEl.on('click', this.onTriggerPress, this);
1500         this.triggerEl.addClass('dropdown-toggle');
1501         this.el.on(Roo.isTouch ? 'touchstart' : 'click'   , this.onClick, this);
1502
1503         this.el.on("mouseover", this.onMouseOver, this);
1504         this.el.on("mouseout", this.onMouseOut, this);
1505         
1506         
1507     },
1508     findTargetItem : function(e){
1509         var t = e.getTarget(".dropdown-menu-item", this.el,  true);
1510         if(!t){
1511             return false;
1512         }
1513         //Roo.log(t);         Roo.log(t.id);
1514         if(t && t.id){
1515             //Roo.log(this.menuitems);
1516             return this.menuitems.get(t.id);
1517             
1518             //return this.items.get(t.menuItemId);
1519         }
1520         
1521         return false;
1522     },
1523     onClick : function(e){
1524         Roo.log("menu.onClick");
1525         var t = this.findTargetItem(e);
1526         if(!t){
1527             return;
1528         }
1529         Roo.log(e);
1530         /*
1531         if (Roo.isTouch && e.type == 'touchstart' && t.menu  && !t.disabled) {
1532             if(t == this.activeItem && t.shouldDeactivate(e)){
1533                 this.activeItem.deactivate();
1534                 delete this.activeItem;
1535                 return;
1536             }
1537             if(t.canActivate){
1538                 this.setActiveItem(t, true);
1539             }
1540             return;
1541             
1542             
1543         }
1544         */
1545         Roo.log('pass click event');
1546         
1547         t.onClick(e);
1548         
1549         this.fireEvent("click", this, t, e);
1550         
1551         this.hide();
1552     },
1553      onMouseOver : function(e){
1554         var t  = this.findTargetItem(e);
1555         //Roo.log(t);
1556         //if(t){
1557         //    if(t.canActivate && !t.disabled){
1558         //        this.setActiveItem(t, true);
1559         //    }
1560         //}
1561         
1562         this.fireEvent("mouseover", this, e, t);
1563     },
1564     isVisible : function(){
1565         return !this.hidden;
1566     },
1567      onMouseOut : function(e){
1568         var t  = this.findTargetItem(e);
1569         
1570         //if(t ){
1571         //    if(t == this.activeItem && t.shouldDeactivate(e)){
1572         //        this.activeItem.deactivate();
1573         //        delete this.activeItem;
1574         //    }
1575         //}
1576         this.fireEvent("mouseout", this, e, t);
1577     },
1578     
1579     
1580     /**
1581      * Displays this menu relative to another element
1582      * @param {String/HTMLElement/Roo.Element} element The element to align to
1583      * @param {String} position (optional) The {@link Roo.Element#alignTo} anchor position to use in aligning to
1584      * the element (defaults to this.defaultAlign)
1585      * @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
1586      */
1587     show : function(el, pos, parentMenu){
1588         this.parentMenu = parentMenu;
1589         if(!this.el){
1590             this.render();
1591         }
1592         this.fireEvent("beforeshow", this);
1593         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
1594     },
1595      /**
1596      * Displays this menu at a specific xy position
1597      * @param {Array} xyPosition Contains X & Y [x, y] values for the position at which to show the menu (coordinates are page-based)
1598      * @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
1599      */
1600     showAt : function(xy, parentMenu, /* private: */_e){
1601         this.parentMenu = parentMenu;
1602         if(!this.el){
1603             this.render();
1604         }
1605         if(_e !== false){
1606             this.fireEvent("beforeshow", this);
1607             
1608             //xy = this.el.adjustForConstraints(xy);
1609         }
1610         //this.el.setXY(xy);
1611         //this.el.show();
1612         this.hideMenuItems();
1613         this.hidden = false;
1614         this.triggerEl.addClass('open');
1615         this.focus();
1616         this.fireEvent("show", this);
1617     },
1618     
1619     focus : function(){
1620         return;
1621         if(!this.hidden){
1622             this.doFocus.defer(50, this);
1623         }
1624     },
1625
1626     doFocus : function(){
1627         if(!this.hidden){
1628             this.focusEl.focus();
1629         }
1630     },
1631
1632     /**
1633      * Hides this menu and optionally all parent menus
1634      * @param {Boolean} deep (optional) True to hide all parent menus recursively, if any (defaults to false)
1635      */
1636     hide : function(deep){
1637         
1638         this.hideMenuItems();
1639         if(this.el && this.isVisible()){
1640             this.fireEvent("beforehide", this);
1641             if(this.activeItem){
1642                 this.activeItem.deactivate();
1643                 this.activeItem = null;
1644             }
1645             this.triggerEl.removeClass('open');;
1646             this.hidden = true;
1647             this.fireEvent("hide", this);
1648         }
1649         if(deep === true && this.parentMenu){
1650             this.parentMenu.hide(true);
1651         }
1652     },
1653     
1654     onTriggerPress  : function(e)
1655     {
1656         
1657         Roo.log('trigger press');
1658         //Roo.log(e.getTarget());
1659        // Roo.log(this.triggerEl.dom);
1660         if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
1661             return;
1662         }
1663         if (this.isVisible()) {
1664             Roo.log('hide');
1665             this.hide();
1666         } else {
1667             this.show(this.triggerEl, false, false);
1668         }
1669         
1670         
1671     },
1672     
1673          
1674        
1675     
1676     hideMenuItems : function()
1677     {
1678         //$(backdrop).remove()
1679         Roo.select('.open',true).each(function(aa) {
1680             
1681             aa.removeClass('open');
1682           //var parent = getParent($(this))
1683           //var relatedTarget = { relatedTarget: this }
1684           
1685            //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
1686           //if (e.isDefaultPrevented()) return
1687            //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
1688         })
1689     },
1690     addxtypeChild : function (tree, cntr) {
1691         var comp= Roo.bootstrap.Menu.superclass.addxtypeChild.call(this, tree, cntr);
1692           
1693         this.menuitems.add(comp);
1694         return comp;
1695
1696     },
1697     getEl : function()
1698     {
1699         Roo.log(this.el);
1700         return this.el;
1701     }
1702 });
1703
1704  
1705  /*
1706  * - LGPL
1707  *
1708  * menu item
1709  * 
1710  */
1711
1712
1713 /**
1714  * @class Roo.bootstrap.MenuItem
1715  * @extends Roo.bootstrap.Component
1716  * Bootstrap MenuItem class
1717  * @cfg {String} html the menu label
1718  * @cfg {String} href the link
1719  * @cfg {Boolean} preventDefault (true | false) default true
1720  * 
1721  * 
1722  * @constructor
1723  * Create a new MenuItem
1724  * @param {Object} config The config object
1725  */
1726
1727
1728 Roo.bootstrap.MenuItem = function(config){
1729     Roo.bootstrap.MenuItem.superclass.constructor.call(this, config);
1730     this.addEvents({
1731         // raw events
1732         /**
1733          * @event click
1734          * The raw click event for the entire grid.
1735          * @param {Roo.EventObject} e
1736          */
1737         "click" : true
1738     });
1739 };
1740
1741 Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component,  {
1742     
1743     href : false,
1744     html : false,
1745     preventDefault: true,
1746     
1747     getAutoCreate : function(){
1748         var cfg= {
1749             tag: 'li',
1750             cls: 'dropdown-menu-item',
1751             cn: [
1752                     {
1753                         tag : 'a',
1754                         href : '#',
1755                         html : 'Link'
1756                     }
1757                 ]
1758         };
1759         if (this.parent().type == 'treeview') {
1760             cfg.cls = 'treeview-menu';
1761         }
1762         
1763         cfg.cn[0].href = this.href || cfg.cn[0].href ;
1764         cfg.cn[0].html = this.html || cfg.cn[0].html ;
1765         return cfg;
1766     },
1767     
1768     initEvents: function() {
1769         
1770         //this.el.select('a').on('click', this.onClick, this);
1771         
1772     },
1773     onClick : function(e)
1774     {
1775         Roo.log('item on click ');
1776         //if(this.preventDefault){
1777         //    e.preventDefault();
1778         //}
1779         //this.parent().hideMenuItems();
1780         
1781         this.fireEvent('click', this, e);
1782     },
1783     getEl : function()
1784     {
1785         return this.el;
1786     }
1787 });
1788
1789  
1790
1791  /*
1792  * - LGPL
1793  *
1794  * menu separator
1795  * 
1796  */
1797
1798
1799 /**
1800  * @class Roo.bootstrap.MenuSeparator
1801  * @extends Roo.bootstrap.Component
1802  * Bootstrap MenuSeparator class
1803  * 
1804  * @constructor
1805  * Create a new MenuItem
1806  * @param {Object} config The config object
1807  */
1808
1809
1810 Roo.bootstrap.MenuSeparator = function(config){
1811     Roo.bootstrap.MenuSeparator.superclass.constructor.call(this, config);
1812 };
1813
1814 Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component,  {
1815     
1816     getAutoCreate : function(){
1817         var cfg = {
1818             cls: 'divider',
1819             tag : 'li'
1820         };
1821         
1822         return cfg;
1823     }
1824    
1825 });
1826
1827  
1828
1829  
1830 /*
1831 <div class="modal fade">
1832   <div class="modal-dialog">
1833     <div class="modal-content">
1834       <div class="modal-header">
1835         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1836         <h4 class="modal-title">Modal title</h4>
1837       </div>
1838       <div class="modal-body">
1839         <p>One fine body&hellip;</p>
1840       </div>
1841       <div class="modal-footer">
1842         <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
1843         <button type="button" class="btn btn-primary">Save changes</button>
1844       </div>
1845     </div><!-- /.modal-content -->
1846   </div><!-- /.modal-dialog -->
1847 </div><!-- /.modal -->
1848 */
1849 /*
1850  * - LGPL
1851  *
1852  * page contgainer.
1853  * 
1854  */
1855
1856 /**
1857  * @class Roo.bootstrap.Modal
1858  * @extends Roo.bootstrap.Component
1859  * Bootstrap Modal class
1860  * @cfg {String} title Title of dialog
1861  * @cfg {Boolean} specificTitle (true|false) default false
1862  * @cfg {Array} buttons Array of buttons or standard button set..
1863  * @cfg {String} buttonPosition (left|right|center) default right
1864  * 
1865  * @constructor
1866  * Create a new Modal Dialog
1867  * @param {Object} config The config object
1868  */
1869
1870 Roo.bootstrap.Modal = function(config){
1871     Roo.bootstrap.Modal.superclass.constructor.call(this, config);
1872     this.addEvents({
1873         // raw events
1874         /**
1875          * @event btnclick
1876          * The raw btnclick event for the button
1877          * @param {Roo.EventObject} e
1878          */
1879         "btnclick" : true
1880     });
1881     this.buttons = this.buttons || [];
1882 };
1883
1884 Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
1885     
1886     title : 'test dialog',
1887    
1888     buttons : false,
1889     
1890     // set on load...
1891     body:  false,
1892     
1893     specificTitle: false,
1894     
1895     buttonPosition: 'right',
1896     
1897     onRender : function(ct, position)
1898     {
1899         Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
1900      
1901         if(!this.el){
1902             var cfg = Roo.apply({},  this.getAutoCreate());
1903             cfg.id = Roo.id();
1904             //if(!cfg.name){
1905             //    cfg.name = typeof(this.name) == 'undefined' ? this.id : this.name;
1906             //}
1907             //if (!cfg.name.length) {
1908             //    delete cfg.name;
1909            // }
1910             if (this.cls) {
1911                 cfg.cls += ' ' + this.cls;
1912             }
1913             if (this.style) {
1914                 cfg.style = this.style;
1915             }
1916             this.el = Roo.get(document.body).createChild(cfg, position);
1917         }
1918         //var type = this.el.dom.type;
1919         
1920         if(this.tabIndex !== undefined){
1921             this.el.dom.setAttribute('tabIndex', this.tabIndex);
1922         }
1923         
1924         
1925         
1926         this.maskEl = Roo.DomHelper.append(document.body, {tag: "div", cls:"x-dlg-mask"}, true);
1927         this.maskEl.enableDisplayMode("block");
1928         this.maskEl.hide();
1929         //this.el.addClass("x-dlg-modal");
1930     
1931         if (this.buttons.length) {
1932             Roo.each(this.buttons, function(bb) {
1933                 b = Roo.apply({}, bb);
1934                 b.xns = b.xns || Roo.bootstrap;
1935                 b.xtype = b.xtype || 'Button';
1936                 if (typeof(b.listeners) == 'undefined') {
1937                     b.listeners = { click : this.onButtonClick.createDelegate(this)  };
1938                 }
1939                 
1940                 var btn = Roo.factory(b);
1941                 
1942                 btn.onRender(this.el.select('.modal-footer div').first());
1943                 
1944             },this);
1945         }
1946         // render the children.
1947         var nitems = [];
1948         
1949         if(typeof(this.items) != 'undefined'){
1950             var items = this.items;
1951             delete this.items;
1952
1953             for(var i =0;i < items.length;i++) {
1954                 nitems.push(this.addxtype(Roo.apply({}, items[i])));
1955             }
1956         }
1957         
1958         this.items = nitems;
1959         
1960         this.body = this.el.select('.modal-body',true).first();
1961         this.close = this.el.select('.modal-header .close', true).first();
1962         this.footer = this.el.select('.modal-footer',true).first();
1963         this.initEvents();
1964         //this.el.addClass([this.fieldClass, this.cls]);
1965         
1966     },
1967     getAutoCreate : function(){
1968         
1969         
1970         var bdy = {
1971                 cls : 'modal-body',
1972                 html : this.html || ''
1973         };
1974         
1975         var title = {
1976             tag: 'h4',
1977             cls : 'modal-title',
1978             html : this.title
1979         };
1980         
1981         if(this.specificTitle){
1982             title = this.title;
1983         };
1984         
1985         return modal = {
1986             cls: "modal fade",
1987             style : 'display: none',
1988             cn : [
1989                 {
1990                     cls: "modal-dialog",
1991                     cn : [
1992                         {
1993                             cls : "modal-content",
1994                             cn : [
1995                                 {
1996                                     cls : 'modal-header',
1997                                     cn : [
1998                                         {
1999                                             tag: 'button',
2000                                             cls : 'close',
2001                                             html : '&times'
2002                                         },
2003                                         title
2004                                     ]
2005                                 },
2006                                 bdy,
2007                                 {
2008                                     cls : 'modal-footer',
2009                                     cn : [
2010                                         {
2011                                             tag: 'div',
2012                                             cls: 'btn-' + this.buttonPosition
2013                                         }
2014                                     ]
2015                                     
2016                                 }
2017                                 
2018                                 
2019                             ]
2020                             
2021                         }
2022                     ]
2023                         
2024                 }
2025             ]
2026             
2027             
2028         };
2029           
2030     },
2031     getChildContainer : function() {
2032          
2033          return this.el.select('.modal-body',true).first();
2034         
2035     },
2036     getButtonContainer : function() {
2037          return this.el.select('.modal-footer div',true).first();
2038         
2039     },
2040     initEvents : function()
2041     {
2042         this.el.select('.modal-header .close').on('click', this.hide, this);
2043 //        
2044 //        this.addxtype(this);
2045     },
2046     show : function() {
2047         
2048         if (!this.rendered) {
2049             this.render();
2050         }
2051        
2052         this.el.addClass('on');
2053         this.el.removeClass('fade');
2054         this.el.setStyle('display', 'block');
2055         Roo.get(document.body).addClass("x-body-masked");
2056         this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
2057         this.maskEl.show();
2058         this.el.setStyle('zIndex', '10001');
2059         this.fireEvent('show', this);
2060         
2061         
2062     },
2063     hide : function()
2064     {
2065         Roo.log('Modal hide?!');
2066         this.maskEl.hide();
2067         Roo.get(document.body).removeClass("x-body-masked");
2068         this.el.removeClass('on');
2069         this.el.addClass('fade');
2070         this.el.setStyle('display', 'none');
2071         this.fireEvent('hide', this);
2072     },
2073     
2074     addButton : function(str, cb)
2075     {
2076          
2077         
2078         var b = Roo.apply({}, { html : str } );
2079         b.xns = b.xns || Roo.bootstrap;
2080         b.xtype = b.xtype || 'Button';
2081         if (typeof(b.listeners) == 'undefined') {
2082             b.listeners = { click : cb.createDelegate(this)  };
2083         }
2084         
2085         var btn = Roo.factory(b);
2086            
2087         btn.onRender(this.el.select('.modal-footer div').first());
2088         
2089         return btn;   
2090        
2091     },
2092     
2093     setDefaultButton : function(btn)
2094     {
2095         //this.el.select('.modal-footer').()
2096     },
2097     resizeTo: function(w,h)
2098     {
2099         // skip..
2100     },
2101     setContentSize  : function(w, h)
2102     {
2103         
2104     },
2105     onButtonClick: function(btn,e)
2106     {
2107         //Roo.log([a,b,c]);
2108         this.fireEvent('btnclick', btn.name, e);
2109     },
2110     setTitle: function(str) {
2111         this.el.select('.modal-title',true).first().dom.innerHTML = str;
2112         
2113     }
2114 });
2115
2116
2117 Roo.apply(Roo.bootstrap.Modal,  {
2118     /**
2119          * Button config that displays a single OK button
2120          * @type Object
2121          */
2122         OK :  [{
2123             name : 'ok',
2124             weight : 'primary',
2125             html : 'OK'
2126         }], 
2127         /**
2128          * Button config that displays Yes and No buttons
2129          * @type Object
2130          */
2131         YESNO : [
2132             {
2133                 name  : 'no',
2134                 html : 'No'
2135             },
2136             {
2137                 name  :'yes',
2138                 weight : 'primary',
2139                 html : 'Yes'
2140             }
2141         ],
2142         
2143         /**
2144          * Button config that displays OK and Cancel buttons
2145          * @type Object
2146          */
2147         OKCANCEL : [
2148             {
2149                name : 'cancel',
2150                 html : 'Cancel'
2151             },
2152             {
2153                 name : 'ok',
2154                 weight : 'primary',
2155                 html : 'OK'
2156             }
2157         ],
2158         /**
2159          * Button config that displays Yes, No and Cancel buttons
2160          * @type Object
2161          */
2162         YESNOCANCEL : [
2163             {
2164                 name : 'yes',
2165                 weight : 'primary',
2166                 html : 'Yes'
2167             },
2168             {
2169                 name : 'no',
2170                 html : 'No'
2171             },
2172             {
2173                 name : 'cancel',
2174                 html : 'Cancel'
2175             }
2176         ]
2177 });
2178  /*
2179  * - LGPL
2180  *
2181  * messagebox - can be used as a replace
2182  * 
2183  */
2184 /**
2185  * @class Roo.MessageBox
2186  * Utility class for generating different styles of message boxes.  The alias Roo.Msg can also be used.
2187  * Example usage:
2188  *<pre><code>
2189 // Basic alert:
2190 Roo.Msg.alert('Status', 'Changes saved successfully.');
2191
2192 // Prompt for user data:
2193 Roo.Msg.prompt('Name', 'Please enter your name:', function(btn, text){
2194     if (btn == 'ok'){
2195         // process text value...
2196     }
2197 });
2198
2199 // Show a dialog using config options:
2200 Roo.Msg.show({
2201    title:'Save Changes?',
2202    msg: 'Your are closing a tab that has unsaved changes. Would you like to save your changes?',
2203    buttons: Roo.Msg.YESNOCANCEL,
2204    fn: processResult,
2205    animEl: 'elId'
2206 });
2207 </code></pre>
2208  * @singleton
2209  */
2210 Roo.bootstrap.MessageBox = function(){
2211     var dlg, opt, mask, waitTimer;
2212     var bodyEl, msgEl, textboxEl, textareaEl, progressEl, pp;
2213     var buttons, activeTextEl, bwidth;
2214
2215     
2216     // private
2217     var handleButton = function(button){
2218         dlg.hide();
2219         Roo.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value], 1);
2220     };
2221
2222     // private
2223     var handleHide = function(){
2224         if(opt && opt.cls){
2225             dlg.el.removeClass(opt.cls);
2226         }
2227         //if(waitTimer){
2228         //    Roo.TaskMgr.stop(waitTimer);
2229         //    waitTimer = null;
2230         //}
2231     };
2232
2233     // private
2234     var updateButtons = function(b){
2235         var width = 0;
2236         if(!b){
2237             buttons["ok"].hide();
2238             buttons["cancel"].hide();
2239             buttons["yes"].hide();
2240             buttons["no"].hide();
2241             //dlg.footer.dom.style.display = 'none';
2242             return width;
2243         }
2244         dlg.footer.dom.style.display = '';
2245         for(var k in buttons){
2246             if(typeof buttons[k] != "function"){
2247                 if(b[k]){
2248                     buttons[k].show();
2249                     buttons[k].setText(typeof b[k] == "string" ? b[k] : Roo.bootstrap.MessageBox.buttonText[k]);
2250                     width += buttons[k].el.getWidth()+15;
2251                 }else{
2252                     buttons[k].hide();
2253                 }
2254             }
2255         }
2256         return width;
2257     };
2258
2259     // private
2260     var handleEsc = function(d, k, e){
2261         if(opt && opt.closable !== false){
2262             dlg.hide();
2263         }
2264         if(e){
2265             e.stopEvent();
2266         }
2267     };
2268
2269     return {
2270         /**
2271          * Returns a reference to the underlying {@link Roo.BasicDialog} element
2272          * @return {Roo.BasicDialog} The BasicDialog element
2273          */
2274         getDialog : function(){
2275            if(!dlg){
2276                 dlg = new Roo.bootstrap.Modal( {
2277                     //draggable: true,
2278                     //resizable:false,
2279                     //constraintoviewport:false,
2280                     //fixedcenter:true,
2281                     //collapsible : false,
2282                     //shim:true,
2283                     //modal: true,
2284                   //  width:400,
2285                   //  height:100,
2286                     //buttonAlign:"center",
2287                     closeClick : function(){
2288                         if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
2289                             handleButton("no");
2290                         }else{
2291                             handleButton("cancel");
2292                         }
2293                     }
2294                 });
2295                 dlg.render();
2296                 dlg.on("hide", handleHide);
2297                 mask = dlg.mask;
2298                 //dlg.addKeyListener(27, handleEsc);
2299                 buttons = {};
2300                 this.buttons = buttons;
2301                 var bt = this.buttonText;
2302                 buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));
2303                 buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));
2304                 buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));
2305                 buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));
2306                 Roo.log(buttons)
2307                 bodyEl = dlg.body.createChild({
2308
2309                     html:'<span class="roo-mb-text"></span><br /><input type="text" class="roo-mb-input" />' +
2310                         '<textarea class="roo-mb-textarea"></textarea>' +
2311                         '<div class="roo-mb-progress-wrap"><div class="roo-mb-progress"><div class="roo-mb-progress-bar">&#160;</div></div></div>'
2312                 });
2313                 msgEl = bodyEl.dom.firstChild;
2314                 textboxEl = Roo.get(bodyEl.dom.childNodes[2]);
2315                 textboxEl.enableDisplayMode();
2316                 textboxEl.addKeyListener([10,13], function(){
2317                     if(dlg.isVisible() && opt && opt.buttons){
2318                         if(opt.buttons.ok){
2319                             handleButton("ok");
2320                         }else if(opt.buttons.yes){
2321                             handleButton("yes");
2322                         }
2323                     }
2324                 });
2325                 textareaEl = Roo.get(bodyEl.dom.childNodes[3]);
2326                 textareaEl.enableDisplayMode();
2327                 progressEl = Roo.get(bodyEl.dom.childNodes[4]);
2328                 progressEl.enableDisplayMode();
2329                 var pf = progressEl.dom.firstChild;
2330                 if (pf) {
2331                     pp = Roo.get(pf.firstChild);
2332                     pp.setHeight(pf.offsetHeight);
2333                 }
2334                 
2335             }
2336             return dlg;
2337         },
2338
2339         /**
2340          * Updates the message box body text
2341          * @param {String} text (optional) Replaces the message box element's innerHTML with the specified string (defaults to
2342          * the XHTML-compliant non-breaking space character '&amp;#160;')
2343          * @return {Roo.MessageBox} This message box
2344          */
2345         updateText : function(text){
2346             if(!dlg.isVisible() && !opt.width){
2347                 dlg.resizeTo(this.maxWidth, 100); // resize first so content is never clipped from previous shows
2348             }
2349             msgEl.innerHTML = text || '&#160;';
2350       
2351             var cw =  Math.max(msgEl.offsetWidth, msgEl.parentNode.scrollWidth);
2352             //Roo.log("guesed size: " + JSON.stringify([cw,msgEl.offsetWidth, msgEl.parentNode.scrollWidth]));
2353             var w = Math.max(
2354                     Math.min(opt.width || cw , this.maxWidth), 
2355                     Math.max(opt.minWidth || this.minWidth, bwidth)
2356             );
2357             if(opt.prompt){
2358                 activeTextEl.setWidth(w);
2359             }
2360             if(dlg.isVisible()){
2361                 dlg.fixedcenter = false;
2362             }
2363             // to big, make it scroll. = But as usual stupid IE does not support
2364             // !important..
2365             
2366             if ( bodyEl.getHeight() > (Roo.lib.Dom.getViewHeight() - 100)) {
2367                 bodyEl.setHeight ( Roo.lib.Dom.getViewHeight() - 100 );
2368                 bodyEl.dom.style.overflowY = 'auto' + ( Roo.isIE ? '' : ' !important');
2369             } else {
2370                 bodyEl.dom.style.height = '';
2371                 bodyEl.dom.style.overflowY = '';
2372             }
2373             if (cw > w) {
2374                 bodyEl.dom.style.get = 'auto' + ( Roo.isIE ? '' : ' !important');
2375             } else {
2376                 bodyEl.dom.style.overflowX = '';
2377             }
2378             
2379             dlg.setContentSize(w, bodyEl.getHeight());
2380             if(dlg.isVisible()){
2381                 dlg.fixedcenter = true;
2382             }
2383             return this;
2384         },
2385
2386         /**
2387          * Updates a progress-style message box's text and progress bar.  Only relevant on message boxes
2388          * initiated via {@link Roo.MessageBox#progress} or by calling {@link Roo.MessageBox#show} with progress: true.
2389          * @param {Number} value Any number between 0 and 1 (e.g., .5)
2390          * @param {String} text (optional) If defined, the message box's body text is replaced with the specified string (defaults to undefined)
2391          * @return {Roo.MessageBox} This message box
2392          */
2393         updateProgress : function(value, text){
2394             if(text){
2395                 this.updateText(text);
2396             }
2397             if (pp) { // weird bug on my firefox - for some reason this is not defined
2398                 pp.setWidth(Math.floor(value*progressEl.dom.firstChild.offsetWidth));
2399             }
2400             return this;
2401         },        
2402
2403         /**
2404          * Returns true if the message box is currently displayed
2405          * @return {Boolean} True if the message box is visible, else false
2406          */
2407         isVisible : function(){
2408             return dlg && dlg.isVisible();  
2409         },
2410
2411         /**
2412          * Hides the message box if it is displayed
2413          */
2414         hide : function(){
2415             if(this.isVisible()){
2416                 dlg.hide();
2417             }  
2418         },
2419
2420         /**
2421          * Displays a new message box, or reinitializes an existing message box, based on the config options
2422          * passed in. All functions (e.g. prompt, alert, etc) on MessageBox call this function internally.
2423          * The following config object properties are supported:
2424          * <pre>
2425 Property    Type             Description
2426 ----------  ---------------  ------------------------------------------------------------------------------------
2427 animEl            String/Element   An id or Element from which the message box should animate as it opens and
2428                                    closes (defaults to undefined)
2429 buttons           Object/Boolean   A button config object (e.g., Roo.MessageBox.OKCANCEL or {ok:'Foo',
2430                                    cancel:'Bar'}), or false to not show any buttons (defaults to false)
2431 closable          Boolean          False to hide the top-right close button (defaults to true).  Note that
2432                                    progress and wait dialogs will ignore this property and always hide the
2433                                    close button as they can only be closed programmatically.
2434 cls               String           A custom CSS class to apply to the message box element
2435 defaultTextHeight Number           The default height in pixels of the message box's multiline textarea if
2436                                    displayed (defaults to 75)
2437 fn                Function         A callback function to execute after closing the dialog.  The arguments to the
2438                                    function will be btn (the name of the button that was clicked, if applicable,
2439                                    e.g. "ok"), and text (the value of the active text field, if applicable).
2440                                    Progress and wait dialogs will ignore this option since they do not respond to
2441                                    user actions and can only be closed programmatically, so any required function
2442                                    should be called by the same code after it closes the dialog.
2443 icon              String           A CSS class that provides a background image to be used as an icon for
2444                                    the dialog (e.g., Roo.MessageBox.WARNING or 'custom-class', defaults to '')
2445 maxWidth          Number           The maximum width in pixels of the message box (defaults to 600)
2446 minWidth          Number           The minimum width in pixels of the message box (defaults to 100)
2447 modal             Boolean          False to allow user interaction with the page while the message box is
2448                                    displayed (defaults to true)
2449 msg               String           A string that will replace the existing message box body text (defaults
2450                                    to the XHTML-compliant non-breaking space character '&#160;')
2451 multiline         Boolean          True to prompt the user to enter multi-line text (defaults to false)
2452 progress          Boolean          True to display a progress bar (defaults to false)
2453 progressText      String           The text to display inside the progress bar if progress = true (defaults to '')
2454 prompt            Boolean          True to prompt the user to enter single-line text (defaults to false)
2455 proxyDrag         Boolean          True to display a lightweight proxy while dragging (defaults to false)
2456 title             String           The title text
2457 value             String           The string value to set into the active textbox element if displayed
2458 wait              Boolean          True to display a progress bar (defaults to false)
2459 width             Number           The width of the dialog in pixels
2460 </pre>
2461          *
2462          * Example usage:
2463          * <pre><code>
2464 Roo.Msg.show({
2465    title: 'Address',
2466    msg: 'Please enter your address:',
2467    width: 300,
2468    buttons: Roo.MessageBox.OKCANCEL,
2469    multiline: true,
2470    fn: saveAddress,
2471    animEl: 'addAddressBtn'
2472 });
2473 </code></pre>
2474          * @param {Object} config Configuration options
2475          * @return {Roo.MessageBox} This message box
2476          */
2477         show : function(options)
2478         {
2479             
2480             // this causes nightmares if you show one dialog after another
2481             // especially on callbacks..
2482              
2483             if(this.isVisible()){
2484                 
2485                 this.hide();
2486                 Roo.log("[Roo.Messagebox] Show called while message displayed:" );
2487                 Roo.log("Old Dialog Message:" +  msgEl.innerHTML );
2488                 Roo.log("New Dialog Message:" +  options.msg )
2489                 //this.alert("ERROR", "Multiple dialogs where displayed at the same time");
2490                 //throw "Roo.MessageBox ERROR : Multiple dialogs where displayed at the same time";
2491                 
2492             }
2493             var d = this.getDialog();
2494             opt = options;
2495             d.setTitle(opt.title || "&#160;");
2496             d.close.setDisplayed(opt.closable !== false);
2497             activeTextEl = textboxEl;
2498             opt.prompt = opt.prompt || (opt.multiline ? true : false);
2499             if(opt.prompt){
2500                 if(opt.multiline){
2501                     textboxEl.hide();
2502                     textareaEl.show();
2503                     textareaEl.setHeight(typeof opt.multiline == "number" ?
2504                         opt.multiline : this.defaultTextHeight);
2505                     activeTextEl = textareaEl;
2506                 }else{
2507                     textboxEl.show();
2508                     textareaEl.hide();
2509                 }
2510             }else{
2511                 textboxEl.hide();
2512                 textareaEl.hide();
2513             }
2514             progressEl.setDisplayed(opt.progress === true);
2515             this.updateProgress(0);
2516             activeTextEl.dom.value = opt.value || "";
2517             if(opt.prompt){
2518                 dlg.setDefaultButton(activeTextEl);
2519             }else{
2520                 var bs = opt.buttons;
2521                 var db = null;
2522                 if(bs && bs.ok){
2523                     db = buttons["ok"];
2524                 }else if(bs && bs.yes){
2525                     db = buttons["yes"];
2526                 }
2527                 dlg.setDefaultButton(db);
2528             }
2529             bwidth = updateButtons(opt.buttons);
2530             this.updateText(opt.msg);
2531             if(opt.cls){
2532                 d.el.addClass(opt.cls);
2533             }
2534             d.proxyDrag = opt.proxyDrag === true;
2535             d.modal = opt.modal !== false;
2536             d.mask = opt.modal !== false ? mask : false;
2537             if(!d.isVisible()){
2538                 // force it to the end of the z-index stack so it gets a cursor in FF
2539                 document.body.appendChild(dlg.el.dom);
2540                 d.animateTarget = null;
2541                 d.show(options.animEl);
2542             }
2543             return this;
2544         },
2545
2546         /**
2547          * Displays a message box with a progress bar.  This message box has no buttons and is not closeable by
2548          * the user.  You are responsible for updating the progress bar as needed via {@link Roo.MessageBox#updateProgress}
2549          * and closing the message box when the process is complete.
2550          * @param {String} title The title bar text
2551          * @param {String} msg The message box body text
2552          * @return {Roo.MessageBox} This message box
2553          */
2554         progress : function(title, msg){
2555             this.show({
2556                 title : title,
2557                 msg : msg,
2558                 buttons: false,
2559                 progress:true,
2560                 closable:false,
2561                 minWidth: this.minProgressWidth,
2562                 modal : true
2563             });
2564             return this;
2565         },
2566
2567         /**
2568          * Displays a standard read-only message box with an OK button (comparable to the basic JavaScript Window.alert).
2569          * If a callback function is passed it will be called after the user clicks the button, and the
2570          * id of the button that was clicked will be passed as the only parameter to the callback
2571          * (could also be the top-right close button).
2572          * @param {String} title The title bar text
2573          * @param {String} msg The message box body text
2574          * @param {Function} fn (optional) The callback function invoked after the message box is closed
2575          * @param {Object} scope (optional) The scope of the callback function
2576          * @return {Roo.MessageBox} This message box
2577          */
2578         alert : function(title, msg, fn, scope){
2579             this.show({
2580                 title : title,
2581                 msg : msg,
2582                 buttons: this.OK,
2583                 fn: fn,
2584                 scope : scope,
2585                 modal : true
2586             });
2587             return this;
2588         },
2589
2590         /**
2591          * Displays a message box with an infinitely auto-updating progress bar.  This can be used to block user
2592          * interaction while waiting for a long-running process to complete that does not have defined intervals.
2593          * You are responsible for closing the message box when the process is complete.
2594          * @param {String} msg The message box body text
2595          * @param {String} title (optional) The title bar text
2596          * @return {Roo.MessageBox} This message box
2597          */
2598         wait : function(msg, title){
2599             this.show({
2600                 title : title,
2601                 msg : msg,
2602                 buttons: false,
2603                 closable:false,
2604                 progress:true,
2605                 modal:true,
2606                 width:300,
2607                 wait:true
2608             });
2609             waitTimer = Roo.TaskMgr.start({
2610                 run: function(i){
2611                     Roo.MessageBox.updateProgress(((((i+20)%20)+1)*5)*.01);
2612                 },
2613                 interval: 1000
2614             });
2615             return this;
2616         },
2617
2618         /**
2619          * Displays a confirmation message box with Yes and No buttons (comparable to JavaScript's Window.confirm).
2620          * If a callback function is passed it will be called after the user clicks either button, and the id of the
2621          * button that was clicked will be passed as the only parameter to the callback (could also be the top-right close button).
2622          * @param {String} title The title bar text
2623          * @param {String} msg The message box body text
2624          * @param {Function} fn (optional) The callback function invoked after the message box is closed
2625          * @param {Object} scope (optional) The scope of the callback function
2626          * @return {Roo.MessageBox} This message box
2627          */
2628         confirm : function(title, msg, fn, scope){
2629             this.show({
2630                 title : title,
2631                 msg : msg,
2632                 buttons: this.YESNO,
2633                 fn: fn,
2634                 scope : scope,
2635                 modal : true
2636             });
2637             return this;
2638         },
2639
2640         /**
2641          * Displays a message box with OK and Cancel buttons prompting the user to enter some text (comparable to
2642          * JavaScript's Window.prompt).  The prompt can be a single-line or multi-line textbox.  If a callback function
2643          * is passed it will be called after the user clicks either button, and the id of the button that was clicked
2644          * (could also be the top-right close button) and the text that was entered will be passed as the two
2645          * parameters to the callback.
2646          * @param {String} title The title bar text
2647          * @param {String} msg The message box body text
2648          * @param {Function} fn (optional) The callback function invoked after the message box is closed
2649          * @param {Object} scope (optional) The scope of the callback function
2650          * @param {Boolean/Number} multiline (optional) True to create a multiline textbox using the defaultTextHeight
2651          * property, or the height in pixels to create the textbox (defaults to false / single-line)
2652          * @return {Roo.MessageBox} This message box
2653          */
2654         prompt : function(title, msg, fn, scope, multiline){
2655             this.show({
2656                 title : title,
2657                 msg : msg,
2658                 buttons: this.OKCANCEL,
2659                 fn: fn,
2660                 minWidth:250,
2661                 scope : scope,
2662                 prompt:true,
2663                 multiline: multiline,
2664                 modal : true
2665             });
2666             return this;
2667         },
2668
2669         /**
2670          * Button config that displays a single OK button
2671          * @type Object
2672          */
2673         OK : {ok:true},
2674         /**
2675          * Button config that displays Yes and No buttons
2676          * @type Object
2677          */
2678         YESNO : {yes:true, no:true},
2679         /**
2680          * Button config that displays OK and Cancel buttons
2681          * @type Object
2682          */
2683         OKCANCEL : {ok:true, cancel:true},
2684         /**
2685          * Button config that displays Yes, No and Cancel buttons
2686          * @type Object
2687          */
2688         YESNOCANCEL : {yes:true, no:true, cancel:true},
2689
2690         /**
2691          * The default height in pixels of the message box's multiline textarea if displayed (defaults to 75)
2692          * @type Number
2693          */
2694         defaultTextHeight : 75,
2695         /**
2696          * The maximum width in pixels of the message box (defaults to 600)
2697          * @type Number
2698          */
2699         maxWidth : 600,
2700         /**
2701          * The minimum width in pixels of the message box (defaults to 100)
2702          * @type Number
2703          */
2704         minWidth : 100,
2705         /**
2706          * The minimum width in pixels of the message box if it is a progress-style dialog.  This is useful
2707          * for setting a different minimum width than text-only dialogs may need (defaults to 250)
2708          * @type Number
2709          */
2710         minProgressWidth : 250,
2711         /**
2712          * An object containing the default button text strings that can be overriden for localized language support.
2713          * Supported properties are: ok, cancel, yes and no.
2714          * Customize the default text like so: Roo.MessageBox.buttonText.yes = "S?";
2715          * @type Object
2716          */
2717         buttonText : {
2718             ok : "OK",
2719             cancel : "Cancel",
2720             yes : "Yes",
2721             no : "No"
2722         }
2723     };
2724 }();
2725
2726 /**
2727  * Shorthand for {@link Roo.MessageBox}
2728  */
2729 Roo.MessageBox = Roo.MessageBox || Roo.bootstrap.MessageBox 
2730 Roo.Msg = Roo.Msg || Roo.MessageBox;
2731 /*
2732  * - LGPL
2733  *
2734  * navbar
2735  * 
2736  */
2737
2738 /**
2739  * @class Roo.bootstrap.Navbar
2740  * @extends Roo.bootstrap.Component
2741  * Bootstrap Navbar class
2742
2743  * @constructor
2744  * Create a new Navbar
2745  * @param {Object} config The config object
2746  */
2747
2748
2749 Roo.bootstrap.Navbar = function(config){
2750     Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
2751     
2752 };
2753
2754 Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
2755     
2756     
2757    
2758     // private
2759     navItems : false,
2760     loadMask : false,
2761     
2762     
2763     getAutoCreate : function(){
2764         
2765         
2766         throw { message : "nav bar is now a abstract base class - use NavSimplebar / NavHeaderbar / NavSidebar etc..."};
2767         
2768     },
2769     
2770     initEvents :function ()
2771     {
2772         //Roo.log(this.el.select('.navbar-toggle',true));
2773         this.el.select('.navbar-toggle',true).on('click', function() {
2774            // Roo.log('click');
2775             this.el.select('.navbar-collapse',true).toggleClass('in');                                 
2776         }, this);
2777         
2778         var mark = {
2779             tag: "div",
2780             cls:"x-dlg-mask"
2781         }
2782         
2783         this.maskEl = Roo.DomHelper.append(this.el, mark, true);
2784         
2785         var size = this.el.getSize();
2786         this.maskEl.setSize(size.width, size.height);
2787         this.maskEl.enableDisplayMode("block");
2788         this.maskEl.hide();
2789         
2790         if(this.loadMask){
2791             this.maskEl.show();
2792         }
2793     },
2794     
2795     
2796     getChildContainer : function()
2797     {
2798         if (this.el.select('.collapse').getCount()) {
2799             return this.el.select('.collapse',true).first();
2800         }
2801         
2802         return this.el;
2803     },
2804     
2805     mask : function()
2806     {
2807         this.maskEl.show();
2808     },
2809     
2810     unmask : function()
2811     {
2812         this.maskEl.hide();
2813     }
2814     
2815     
2816     
2817 });
2818
2819
2820
2821  
2822
2823  /*
2824  * - LGPL
2825  *
2826  * navbar
2827  * 
2828  */
2829
2830 /**
2831  * @class Roo.bootstrap.NavSimplebar
2832  * @extends Roo.bootstrap.Navbar
2833  * Bootstrap Sidebar class
2834  *
2835  * @cfg {Boolean} inverse is inverted color
2836  * 
2837  * @cfg {String} type (nav | pills | tabs)
2838  * @cfg {Boolean} arrangement stacked | justified
2839  * @cfg {String} align (left | right) alignment
2840  * 
2841  * @cfg {Boolean} main (true|false) main nav bar? default false
2842  * @cfg {Boolean} loadMask (true|false) loadMask on the bar
2843  * 
2844  * @cfg {String} tag (header|footer|nav|div) default is nav 
2845
2846  * 
2847  * 
2848  * 
2849  * @constructor
2850  * Create a new Sidebar
2851  * @param {Object} config The config object
2852  */
2853
2854
2855 Roo.bootstrap.NavSimplebar = function(config){
2856     Roo.bootstrap.NavSimplebar.superclass.constructor.call(this, config);
2857 };
2858
2859 Roo.extend(Roo.bootstrap.NavSimplebar, Roo.bootstrap.Navbar,  {
2860     
2861     inverse: false,
2862     
2863     type: false,
2864     arrangement: '',
2865     align : false,
2866     
2867     
2868     
2869     main : false,
2870     
2871     
2872     tag : false,
2873     
2874     
2875     getAutoCreate : function(){
2876         
2877         
2878         var cfg = {
2879             tag : this.tag || 'div',
2880             cls : 'navbar'
2881         };
2882           
2883         
2884         cfg.cn = [
2885             {
2886                 cls: 'nav',
2887                 tag : 'ul'
2888             }
2889         ];
2890         
2891          
2892         this.type = this.type || 'nav';
2893         if (['tabs','pills'].indexOf(this.type)!==-1) {
2894             cfg.cn[0].cls += ' nav-' + this.type
2895         
2896         
2897         } else {
2898             if (this.type!=='nav') {
2899                 Roo.log('nav type must be nav/tabs/pills')
2900             }
2901             cfg.cn[0].cls += ' navbar-nav'
2902         }
2903         
2904         
2905         
2906         
2907         if (['stacked','justified'].indexOf(this.arrangement)!==-1) {
2908             cfg.cn[0].cls += ' nav-' + this.arrangement;
2909         }
2910         
2911         
2912         if (this.align === 'right') {
2913             cfg.cn[0].cls += ' navbar-right';
2914         }
2915         
2916         if (this.inverse) {
2917             cfg.cls += ' navbar-inverse';
2918             
2919         }
2920         
2921         
2922         return cfg;
2923     
2924         
2925     }
2926     
2927     
2928     
2929 });
2930
2931
2932
2933  
2934
2935  
2936        /*
2937  * - LGPL
2938  *
2939  * navbar
2940  * 
2941  */
2942
2943 /**
2944  * @class Roo.bootstrap.NavHeaderbar
2945  * @extends Roo.bootstrap.NavSimplebar
2946  * Bootstrap Sidebar class
2947  *
2948  * @cfg {String} brand what is brand
2949  * @cfg {String} position (fixed-top|fixed-bottom|static-top) position
2950  * @cfg {String} brand_href href of the brand
2951  * 
2952  * @constructor
2953  * Create a new Sidebar
2954  * @param {Object} config The config object
2955  */
2956
2957
2958 Roo.bootstrap.NavHeaderbar = function(config){
2959     Roo.bootstrap.NavHeaderbar.superclass.constructor.call(this, config);
2960 };
2961
2962 Roo.extend(Roo.bootstrap.NavHeaderbar, Roo.bootstrap.NavSimplebar,  {
2963     
2964     position: '',
2965     brand: '',
2966     brand_href: false,
2967     
2968     
2969     getAutoCreate : function(){
2970         
2971         
2972         
2973         var   cfg = {
2974             tag: this.nav || 'nav',
2975             cls: 'navbar',
2976             role: 'navigation',
2977             cn: [
2978                 {
2979                     tag: 'div',
2980                     cls: 'navbar-header',
2981                     cn: [
2982                         {
2983                         tag: 'button',
2984                         type: 'button',
2985                         cls: 'navbar-toggle',
2986                         'data-toggle': 'collapse',
2987                         cn: [
2988                             {
2989                                 tag: 'span',
2990                                 cls: 'sr-only',
2991                                 html: 'Toggle navigation'
2992                             },
2993                             {
2994                                 tag: 'span',
2995                                 cls: 'icon-bar'
2996                             },
2997                             {
2998                                 tag: 'span',
2999                                 cls: 'icon-bar'
3000                             },
3001                             {
3002                                 tag: 'span',
3003                                 cls: 'icon-bar'
3004                             }
3005                         ]
3006                         }
3007                     ]
3008                 },
3009                 {
3010                 tag: 'div',
3011                 cls: 'collapse navbar-collapse'
3012                 }
3013             ]
3014         };
3015         
3016         cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
3017         
3018         if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
3019             cfg.cls += ' navbar-' + this.position;
3020             
3021             // tag can override this..
3022             
3023             cfg.tag = this.tag || (this.position  == 'fixed-bottom' ? 'footer' : 'header');
3024         }
3025         
3026         if (this.brand !== '') {
3027             cfg.cn[0].cn.push({
3028                 tag: 'a',
3029                 href: this.brand_href ? this.brand_href : '#',
3030                 cls: 'navbar-brand',
3031                 cn: [
3032                 this.brand
3033                 ]
3034             });
3035         }
3036         
3037         if(this.main){
3038             cfg.cls += ' main-nav';
3039         }
3040         
3041         
3042         return cfg;
3043
3044         
3045     }
3046     
3047     
3048     
3049 });
3050
3051
3052
3053  
3054
3055  /*
3056  * - LGPL
3057  *
3058  * navbar
3059  * 
3060  */
3061
3062 /**
3063  * @class Roo.bootstrap.NavSidebar
3064  * @extends Roo.bootstrap.Navbar
3065  * Bootstrap Sidebar class
3066  * 
3067  * @constructor
3068  * Create a new Sidebar
3069  * @param {Object} config The config object
3070  */
3071
3072
3073 Roo.bootstrap.NavSidebar = function(config){
3074     Roo.bootstrap.NavSidebar.superclass.constructor.call(this, config);
3075 };
3076
3077 Roo.extend(Roo.bootstrap.NavSidebar, Roo.bootstrap.Navbar,  {
3078     
3079     sidebar : true, // used by Navbar Item and NavbarGroup at present...
3080     
3081     getAutoCreate : function(){
3082         
3083         
3084         return  {
3085             tag: 'div',
3086             cls: 'sidebar sidebar-nav'
3087         };
3088     
3089         
3090     }
3091     
3092     
3093     
3094 });
3095
3096
3097
3098  
3099
3100  /*
3101  * - LGPL
3102  *
3103  * nav group
3104  * 
3105  */
3106
3107 /**
3108  * @class Roo.bootstrap.NavGroup
3109  * @extends Roo.bootstrap.Component
3110  * Bootstrap NavGroup class
3111  * @cfg {String} align left | right
3112  * @cfg {Boolean} inverse false | true
3113  * @cfg {String} type (nav|pills|tab) default nav
3114  * @cfg {String} navId - reference Id for navbar.
3115
3116  * 
3117  * @constructor
3118  * Create a new nav group
3119  * @param {Object} config The config object
3120  */
3121
3122 Roo.bootstrap.NavGroup = function(config){
3123     Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
3124     this.navItems = [];
3125     Roo.bootstrap.NavGroup.register(this);
3126      this.addEvents({
3127         /**
3128              * @event changed
3129              * Fires when the active item changes
3130              * @param {Roo.bootstrap.NavGroup} this
3131              * @param {Roo.bootstrap.Navbar.Item} item The item selected
3132              * @param {Roo.bootstrap.Navbar.Item} item The previously selected item 
3133          */
3134         'changed': true
3135      });
3136     
3137 };
3138
3139 Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
3140     
3141     align: '',
3142     inverse: false,
3143     form: false,
3144     type: 'nav',
3145     navId : '',
3146     // private
3147     
3148     navItems : false,
3149     
3150     getAutoCreate : function()
3151     {
3152         var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
3153         
3154         cfg = {
3155             tag : 'ul',
3156             cls: 'nav' 
3157         }
3158         
3159         if (['tabs','pills'].indexOf(this.type)!==-1) {
3160             cfg.cls += ' nav-' + this.type
3161         } else {
3162             if (this.type!=='nav') {
3163                 Roo.log('nav type must be nav/tabs/pills')
3164             }
3165             cfg.cls += ' navbar-nav'
3166         }
3167         
3168         if (this.parent().sidebar) {
3169             cfg = {
3170                 tag: 'ul',
3171                 cls: 'dashboard-menu sidebar-menu'
3172             }
3173             
3174             return cfg;
3175         }
3176         
3177         if (this.form === true) {
3178             cfg = {
3179                 tag: 'form',
3180                 cls: 'navbar-form'
3181             }
3182             
3183             if (this.align === 'right') {
3184                 cfg.cls += ' navbar-right';
3185             } else {
3186                 cfg.cls += ' navbar-left';
3187             }
3188         }
3189         
3190         if (this.align === 'right') {
3191             cfg.cls += ' navbar-right';
3192         }
3193         
3194         if (this.inverse) {
3195             cfg.cls += ' navbar-inverse';
3196             
3197         }
3198         
3199         
3200         return cfg;
3201     },
3202     
3203     setActiveItem : function(item)
3204     {
3205         var prev = false;
3206         Roo.each(this.navItems, function(v){
3207             if (v == item) {
3208                 return ;
3209             }
3210             if (v.isActive()) {
3211                 v.setActive(false, true);
3212                 prev = v;
3213                 
3214             }
3215             
3216         });
3217
3218         item.setActive(true, true);
3219         this.fireEvent('changed', this, item, prev);
3220         
3221         
3222     },
3223     
3224     
3225     register : function(item)
3226     {
3227         this.navItems.push( item);
3228         item.navId = this.navId;
3229     
3230     },
3231     getNavItem: function(tabId)
3232     {
3233         var ret = false;
3234         Roo.each(this.navItems, function(e) {
3235             if (e.tabId == tabId) {
3236                ret =  e;
3237                return false;
3238             }
3239             return true;
3240             
3241         });
3242         return ret;
3243     }
3244 });
3245
3246  
3247 Roo.apply(Roo.bootstrap.NavGroup, {
3248     
3249     groups: {},
3250     
3251     register : function(navgrp)
3252     {
3253         this.groups[navgrp.navId] = navgrp;
3254         
3255     },
3256     get: function(navId) {
3257         return this.groups[navId];
3258     }
3259     
3260     
3261     
3262 });
3263
3264  /*
3265  * - LGPL
3266  *
3267  * row
3268  * 
3269  */
3270
3271 /**
3272  * @class Roo.bootstrap.Navbar.Item
3273  * @extends Roo.bootstrap.Component
3274  * Bootstrap Navbar.Button class
3275  * @cfg {String} href  link to
3276  * @cfg {String} html content of button
3277  * @cfg {String} badge text inside badge
3278  * @cfg {String} glyphicon name of glyphicon
3279  * @cfg {String} icon name of font awesome icon
3280  * @cfg {Boolean} active Is item active
3281  * @cfg {Boolean} preventDefault (true | false) default false
3282  * @cfg {String} tabId the tab that this item activates.
3283   
3284  * @constructor
3285  * Create a new Navbar Button
3286  * @param {Object} config The config object
3287  */
3288 Roo.bootstrap.Navbar.Item = function(config){
3289     Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
3290     this.addEvents({
3291         // raw events
3292         /**
3293          * @event click
3294          * The raw click event for the entire grid.
3295          * @param {Roo.EventObject} e
3296          */
3297         "click" : true,
3298          /**
3299             * @event changed
3300             * Fires when the active item active state changes
3301             * @param {Roo.bootstrap.Navbar.Item} this
3302             * @param {boolean} state the new state
3303              
3304          */
3305         'changed': true
3306     });
3307    
3308 };
3309
3310 Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component,  {
3311     
3312     href: false,
3313     html: '',
3314     badge: '',
3315     icon: false,
3316     glyphicon: false,
3317     active: false,
3318     preventDefault : false,
3319     tabId : false,
3320     
3321     getAutoCreate : function(){
3322         
3323         var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
3324         
3325         if (this.parent().parent().sidebar === true) {
3326             cfg = {
3327                 tag: 'li',
3328                 cls: '',
3329                 cn: [
3330                     {
3331                     tag: 'p',
3332                     cls: ''
3333                     }
3334                 ]
3335             }
3336             
3337             if (this.html) {
3338                 cfg.cn[0].html = this.html;
3339             }
3340             
3341             if (this.active) {
3342                 this.cls += ' active';
3343             }
3344             
3345             if (this.menu) {
3346                 cfg.cn[0].cls += ' dropdown-toggle';
3347                 cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
3348             }
3349             
3350             if (this.href) {
3351                 cfg.cn[0].tag = 'a',
3352                 cfg.cn[0].href = this.href;
3353             }
3354             
3355             if (this.glyphicon) {
3356                 cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
3357             }
3358                 
3359             if (this.icon) {
3360                 cfg.cn[0].html = '<i class="'+this.icon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
3361             }
3362             
3363             return cfg;
3364         }
3365         
3366         cfg = {
3367             tag: 'li',
3368                 cls: 'nav-item'
3369         }
3370             
3371         if (this.active) {
3372             cfg.cls = typeof(cfg.cls) == 'undefined' ? 'active' : cfg.cls + ' active';
3373         }
3374             
3375         cfg.cn = [
3376             {
3377                 tag: 'p',
3378                 html: 'Text'
3379             }
3380         ];
3381         
3382         if (this.glyphicon) {
3383             if(cfg.html){cfg.html = ' ' + this.html};
3384             cfg.cn=[
3385                 {
3386                     tag: 'span',
3387                     cls: 'glyphicon glyphicon-' + this.glyphicon
3388                 }
3389             ];
3390         }
3391         
3392         cfg.cn[0].html = this.html || cfg.cn[0].html ;
3393         
3394         if (this.menu) {
3395             cfg.cn[0].tag='a';
3396             cfg.cn[0].href='#';
3397             cfg.cn[0].html += " <span class='caret'></span>";
3398         //}else if (!this.href) {
3399         //    cfg.cn[0].tag='p';
3400         //    cfg.cn[0].cls='navbar-text';
3401         } else {
3402             cfg.cn[0].tag='a';
3403             cfg.cn[0].href=this.href||'#';
3404             cfg.cn[0].html=this.html;
3405         }
3406         
3407         if (this.badge !== '') {
3408             
3409             cfg.cn[0].cn=[
3410             cfg.cn[0].html + ' ',
3411             {
3412                 tag: 'span',
3413                 cls: 'badge',
3414                 html: this.badge
3415             }
3416             ];
3417             cfg.cn[0].html=''
3418         }
3419          
3420         if (this.icon) {
3421             cfg.cn[0].html = '<i class="'+this.icon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
3422         }
3423         
3424         return cfg;
3425     },
3426     initEvents: function() {
3427        // Roo.log('init events?');
3428        // Roo.log(this.el.dom);
3429         this.el.select('a',true).on('click', this.onClick, this);
3430         // at this point parent should be available..
3431         this.parent().register(this);
3432     },
3433     
3434     onClick : function(e)
3435     {
3436         if(this.preventDefault){
3437             e.preventDefault();
3438         }
3439         
3440         if(this.fireEvent('click', this, e) === false){
3441             return;
3442         };
3443         
3444         if (['tabs','pills'].indexOf(this.parent().type)!==-1) {
3445              if (typeof(this.parent().setActiveItem) !== 'undefined') {
3446                 this.parent().setActiveItem(this);
3447             }
3448             
3449             
3450             
3451         } 
3452     },
3453     
3454     isActive: function () {
3455         return this.active
3456     },
3457     setActive : function(state, fire)
3458     {
3459         this.active = state;
3460         if (!state ) {
3461             this.el.removeClass('active');
3462         } else if (!this.el.hasClass('active')) {
3463             this.el.addClass('active');
3464         }
3465         if (fire) {
3466             this.fireEvent('changed', this, state);
3467         }
3468         
3469         
3470     }
3471      // this should not be here...
3472  
3473 });
3474  
3475
3476  /*
3477  * - LGPL
3478  *
3479  * row
3480  * 
3481  */
3482
3483 /**
3484  * @class Roo.bootstrap.NavItem
3485  * @extends Roo.bootstrap.Component
3486  * Bootstrap Navbar.NavItem class
3487  * @cfg {String} href  link to
3488  * @cfg {String} html content of button
3489  * @cfg {String} badge text inside badge
3490  * @cfg {String} badgecls (bg-green|bg-red|bg-yellow)the extra classes for the badge
3491  * @cfg {String} glyphicon name of glyphicon
3492  * @cfg {String} icon name of font awesome icon
3493  * @cfg {Boolean} active Is item active
3494  * @cfg {Boolean} preventDefault (true | false) default false
3495  * @cfg {String} tabId the tab that this item activates.
3496   
3497  * @constructor
3498  * Create a new Navbar Item
3499  * @param {Object} config The config object
3500  */
3501 Roo.bootstrap.NavItem = function(config){
3502     Roo.bootstrap.NavItem.superclass.constructor.call(this, config);
3503     this.addEvents({
3504         // raw events
3505         /**
3506          * @event click
3507          * The raw click event for the entire grid.
3508          * @param {Roo.EventObject} e
3509          */
3510         "click" : true,
3511          /**
3512             * @event changed
3513             * Fires when the active item active state changes
3514             * @param {Roo.bootstrap.NavItem} this
3515             * @param {boolean} state the new state
3516              
3517          */
3518         'changed': true
3519     });
3520    
3521 };
3522
3523 Roo.extend(Roo.bootstrap.NavItem, Roo.bootstrap.Component,  {
3524     
3525     href: false,
3526     html: '',
3527     badge: '',
3528     icon: false,
3529     glyphicon: false,
3530     active: false,
3531     preventDefault : false,
3532     tabId : false,
3533     
3534     getAutoCreate : function(){
3535          
3536         var cfg = {
3537             tag: 'li',
3538             cls: 'nav-item',
3539             cn : [
3540                 {
3541                     tag: 'a',
3542                     href : this.href || "#",
3543                     html: this.html || ''
3544                 }
3545             ]
3546         }
3547             
3548         if (this.active) {
3549             cfg.cls = typeof(cfg.cls) == 'undefined' ? 'active' : cfg.cls + ' active';
3550         }
3551             
3552         // glyphicon and icon go before content..
3553         if (this.glyphicon || this.icon) {
3554              if (this.icon) {
3555                 cfg.cn[0].html = '<i class="'+this.icon+'"></i><span>' + cfg.cn[0].html + '</span>'
3556             } else {
3557                 cfg.cn[0].html = '<span class="glyphicon glyphicon-' + this.glyphicon + '"></span>'  + cfg.cn[0].html;
3558             }
3559         }
3560         
3561         
3562         
3563         if (this.menu) {
3564             
3565             cfg.cn[0].html += " <span class='caret'></span>";
3566          
3567         }
3568         
3569         if (this.badge !== '') {
3570              
3571             cfg.cn[0].html += ' <span class="badge">' + this.badge + '</span>';
3572         }
3573         
3574         
3575         
3576         return cfg;
3577     },
3578     initEvents: function() {
3579        // Roo.log('init events?');
3580        // Roo.log(this.el.dom);
3581         this.el.select('a',true).on('click', this.onClick, this);
3582         // at this point parent should be available..
3583         this.parent().register(this);
3584     },
3585     
3586     onClick : function(e)
3587     {
3588         if(this.preventDefault){
3589             e.preventDefault();
3590         }
3591         
3592         if(this.fireEvent('click', this, e) === false){
3593             return;
3594         };
3595         
3596         if (['tabs','pills'].indexOf(this.parent().type)!==-1) {
3597              if (typeof(this.parent().setActiveItem) !== 'undefined') {
3598                 this.parent().setActiveItem(this);
3599             }
3600             
3601             
3602             
3603         } 
3604     },
3605     
3606     isActive: function () {
3607         return this.active
3608     },
3609     setActive : function(state, fire)
3610     {
3611         this.active = state;
3612         if (!state ) {
3613             this.el.removeClass('active');
3614         } else if (!this.el.hasClass('active')) {
3615             this.el.addClass('active');
3616         }
3617         if (fire) {
3618             this.fireEvent('changed', this, state);
3619         }
3620         
3621         
3622     }
3623      // this should not be here...
3624  
3625 });
3626  
3627
3628  /*
3629  * - LGPL
3630  *
3631  * sidebar item
3632  *
3633  *  li
3634  *    <span> icon </span>
3635  *    <span> text </span>
3636  *    <span>badge </span>
3637  */
3638
3639 /**
3640  * @class Roo.bootstrap.NavSidebarItem
3641  * @extends Roo.bootstrap.Component
3642  * Bootstrap Navbar.NavSidebarItem class
3643  * @constructor
3644  * Create a new Navbar Button
3645  * @param {Object} config The config object
3646  */
3647 Roo.bootstrap.NavSidebarItem = function(config){
3648     Roo.bootstrap.NavSidebarItem.superclass.constructor.call(this, config);
3649     this.addEvents({
3650         // raw events
3651         /**
3652          * @event click
3653          * The raw click event for the entire grid.
3654          * @param {Roo.EventObject} e
3655          */
3656         "click" : true,
3657          /**
3658             * @event changed
3659             * Fires when the active item active state changes
3660             * @param {Roo.bootstrap.Navbar.Item} this
3661             * @param {boolean} state the new state
3662              
3663          */
3664         'changed': true
3665     });
3666    
3667 };
3668
3669 Roo.extend(Roo.bootstrap.NavSidebarItem, Roo.bootstrap.NavItem,  {
3670     
3671     
3672     getAutoCreate : function(){
3673         
3674         
3675         var a = {
3676                 tag: 'a',
3677                 href : this.href || '#',
3678                 cls: '',
3679                 html : '',
3680                 cn : []
3681         };
3682         var cfg = {
3683             tag: 'li',
3684             cls: '',
3685             cn: [ a ]
3686         }
3687         var span = {
3688             tag: 'span',
3689             html : this.html || ''
3690         }
3691         
3692         
3693         if (this.active) {
3694             cfg.cls += ' active';
3695         }
3696         
3697         // left icon..
3698         if (this.glyphicon || this.icon) {
3699             var c = this.glyphicon  ? ('glyphicon glyphicon-'+this.glyphicon)  : this.icon;
3700             a.cn.push({ tag : 'i', cls : c }) ;
3701         }
3702         // html..
3703         a.cn.push(span);
3704         // then badge..
3705         if (this.badge !== '') {
3706             a.cn.push({ tag: 'span',  cls : 'badge pull-right ' + (this.badgecls || ''), html: this.badge }); 
3707         }
3708         // fi
3709         if (this.menu) {
3710             a.cn.push({ tag : 'i', cls : 'glyphicon glyphicon-chevron-down pull-right'});
3711             a.cls += 'dropdown-toggle treeview' ;
3712             
3713         }
3714         
3715         
3716         
3717         return cfg;
3718          
3719            
3720     }
3721    
3722      
3723  
3724 });
3725  
3726
3727  /*
3728  * - LGPL
3729  *
3730  * row
3731  * 
3732  */
3733
3734 /**
3735  * @class Roo.bootstrap.Row
3736  * @extends Roo.bootstrap.Component
3737  * Bootstrap Row class (contains columns...)
3738  * 
3739  * @constructor
3740  * Create a new Row
3741  * @param {Object} config The config object
3742  */
3743
3744 Roo.bootstrap.Row = function(config){
3745     Roo.bootstrap.Row.superclass.constructor.call(this, config);
3746 };
3747
3748 Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component,  {
3749     
3750     getAutoCreate : function(){
3751        return {
3752             cls: 'row clearfix'
3753        };
3754     }
3755     
3756     
3757 });
3758
3759  
3760
3761  /*
3762  * - LGPL
3763  *
3764  * element
3765  * 
3766  */
3767
3768 /**
3769  * @class Roo.bootstrap.Element
3770  * @extends Roo.bootstrap.Component
3771  * Bootstrap Element class
3772  * @cfg {String} html contents of the element
3773  * @cfg {String} tag tag of the element
3774  * @cfg {String} cls class of the element
3775  * 
3776  * @constructor
3777  * Create a new Element
3778  * @param {Object} config The config object
3779  */
3780
3781 Roo.bootstrap.Element = function(config){
3782     Roo.bootstrap.Element.superclass.constructor.call(this, config);
3783 };
3784
3785 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component,  {
3786     
3787     tag: 'div',
3788     cls: '',
3789     html: '',
3790      
3791     
3792     getAutoCreate : function(){
3793         
3794         var cfg = {
3795             tag: this.tag,
3796             cls: this.cls,
3797             html: this.html
3798         }
3799         
3800         
3801         
3802         return cfg;
3803     }
3804    
3805 });
3806
3807  
3808
3809  /*
3810  * - LGPL
3811  *
3812  * pagination
3813  * 
3814  */
3815
3816 /**
3817  * @class Roo.bootstrap.Pagination
3818  * @extends Roo.bootstrap.Component
3819  * Bootstrap Pagination class
3820  * @cfg {String} size xs | sm | md | lg
3821  * @cfg {Boolean} inverse false | true
3822  * 
3823  * @constructor
3824  * Create a new Pagination
3825  * @param {Object} config The config object
3826  */
3827
3828 Roo.bootstrap.Pagination = function(config){
3829     Roo.bootstrap.Pagination.superclass.constructor.call(this, config);
3830 };
3831
3832 Roo.extend(Roo.bootstrap.Pagination, Roo.bootstrap.Component,  {
3833     
3834     cls: false,
3835     size: false,
3836     inverse: false,
3837     
3838     getAutoCreate : function(){
3839         var cfg = {
3840             tag: 'ul',
3841                 cls: 'pagination'
3842         };
3843         if (this.inverse) {
3844             cfg.cls += ' inverse';
3845         }
3846         if (this.html) {
3847             cfg.html=this.html;
3848         }
3849         if (this.cls) {
3850             cfg.cls += " " + this.cls;
3851         }
3852         return cfg;
3853     }
3854    
3855 });
3856
3857  
3858
3859  /*
3860  * - LGPL
3861  *
3862  * Pagination item
3863  * 
3864  */
3865
3866
3867 /**
3868  * @class Roo.bootstrap.PaginationItem
3869  * @extends Roo.bootstrap.Component
3870  * Bootstrap PaginationItem class
3871  * @cfg {String} html text
3872  * @cfg {String} href the link
3873  * @cfg {Boolean} preventDefault (true | false) default true
3874  * @cfg {Boolean} active (true | false) default false
3875  * 
3876  * 
3877  * @constructor
3878  * Create a new PaginationItem
3879  * @param {Object} config The config object
3880  */
3881
3882
3883 Roo.bootstrap.PaginationItem = function(config){
3884     Roo.bootstrap.PaginationItem.superclass.constructor.call(this, config);
3885     this.addEvents({
3886         // raw events
3887         /**
3888          * @event click
3889          * The raw click event for the entire grid.
3890          * @param {Roo.EventObject} e
3891          */
3892         "click" : true
3893     });
3894 };
3895
3896 Roo.extend(Roo.bootstrap.PaginationItem, Roo.bootstrap.Component,  {
3897     
3898     href : false,
3899     html : false,
3900     preventDefault: true,
3901     active : false,
3902     cls : false,
3903     
3904     getAutoCreate : function(){
3905         var cfg= {
3906             tag: 'li',
3907             cn: [
3908                 {
3909                     tag : 'a',
3910                     href : this.href ? this.href : '#',
3911                     html : this.html ? this.html : ''
3912                 }
3913             ]
3914         };
3915         
3916         if(this.cls){
3917             cfg.cls = this.cls;
3918         }
3919         
3920         if(this.active){
3921             cfg.cls = typeof(cfg.cls) !== 'undefined' ? cfg.cls + ' active' : 'active';
3922         }
3923         
3924         return cfg;
3925     },
3926     
3927     initEvents: function() {
3928         
3929         this.el.on('click', this.onClick, this);
3930         
3931     },
3932     onClick : function(e)
3933     {
3934         Roo.log('PaginationItem on click ');
3935         if(this.preventDefault){
3936             e.preventDefault();
3937         }
3938         
3939         this.fireEvent('click', this, e);
3940     }
3941    
3942 });
3943
3944  
3945
3946  /*
3947  * - LGPL
3948  *
3949  * slider
3950  * 
3951  */
3952
3953
3954 /**
3955  * @class Roo.bootstrap.Slider
3956  * @extends Roo.bootstrap.Component
3957  * Bootstrap Slider class
3958  *    
3959  * @constructor
3960  * Create a new Slider
3961  * @param {Object} config The config object
3962  */
3963
3964 Roo.bootstrap.Slider = function(config){
3965     Roo.bootstrap.Slider.superclass.constructor.call(this, config);
3966 };
3967
3968 Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component,  {
3969     
3970     getAutoCreate : function(){
3971         
3972         var cfg = {
3973             tag: 'div',
3974             cls: 'slider slider-sample1 vertical-handler ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all',
3975             cn: [
3976                 {
3977                     tag: 'a',
3978                     cls: 'ui-slider-handle ui-state-default ui-corner-all'
3979                 }
3980             ]
3981         }
3982         
3983         return cfg;
3984     }
3985    
3986 });
3987
3988  /*
3989  * - LGPL
3990  *
3991  * table
3992  * 
3993  */
3994
3995 /**
3996  * @class Roo.bootstrap.Table
3997  * @extends Roo.bootstrap.Component
3998  * Bootstrap Table class
3999  * @cfg {String} cls table class
4000  * @cfg {String} align (left|center|right) Specifies the alignment of a table according to surrounding text
4001  * @cfg {String} bgcolor Specifies the background color for a table
4002  * @cfg {Number} border Specifies whether the table cells should have borders or not
4003  * @cfg {Number} cellpadding Specifies the space between the cell wall and the cell content
4004  * @cfg {Number} cellspacing Specifies the space between cells
4005  * @cfg {String} frame Specifies which parts of the outside borders that should be visible
4006  * @cfg {String} rules Specifies which parts of the inside borders that should be visible
4007  * @cfg {String} sortable Specifies that the table should be sortable
4008  * @cfg {String} summary Specifies a summary of the content of a table
4009  * @cfg {Number} width Specifies the width of a table
4010  * 
4011  * @cfg {boolean} striped Should the rows be alternative striped
4012  * @cfg {boolean} bordered Add borders to the table
4013  * @cfg {boolean} hover Add hover highlighting
4014  * @cfg {boolean} condensed Format condensed
4015  * @cfg {boolean} responsive Format condensed
4016  *
4017  
4018  
4019  * 
4020  * @constructor
4021  * Create a new Table
4022  * @param {Object} config The config object
4023  */
4024
4025 Roo.bootstrap.Table = function(config){
4026     Roo.bootstrap.Table.superclass.constructor.call(this, config);
4027     
4028     if (this.sm) {
4029         this.selModel = Roo.factory(this.sm, Roo.bootstrap.Table);
4030         this.sm = this.selModel;
4031         this.sm.xmodule = this.xmodule || false;
4032     }
4033     if (this.cm && typeof(this.cm.config) == 'undefined') {
4034         this.colModel = new Roo.bootstrap.Table.ColumnModel(this.cm);
4035         this.cm = this.colModel;
4036         this.cm.xmodule = this.xmodule || false;
4037     }
4038     if (this.store) {
4039         this.store= Roo.factory(this.store, Roo.data);
4040         this.ds = this.store;
4041         this.ds.xmodule = this.xmodule || false;
4042          
4043     }
4044 };
4045
4046 Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
4047     
4048     cls: false,
4049     align: false,
4050     bgcolor: false,
4051     border: false,
4052     cellpadding: false,
4053     cellspacing: false,
4054     frame: false,
4055     rules: false,
4056     sortable: false,
4057     summary: false,
4058     width: false,
4059     striped : false,
4060     bordered: false,
4061     hover:  false,
4062     condensed : false,
4063     responsive : false,
4064     sm : false,
4065     cm : false,
4066     store : false,
4067     
4068     getAutoCreate : function(){
4069         var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
4070         
4071         cfg = {
4072             tag: 'table',
4073             cls : 'table',
4074             cn : []
4075         }
4076             
4077         if (this.striped) {
4078             cfg.cls += ' table-striped';
4079         }
4080         if (this.hover) {
4081             cfg.cls += ' table-hover';
4082         }
4083         if (this.bordered) {
4084             cfg.cls += ' table-bordered';
4085         }
4086         if (this.condensed) {
4087             cfg.cls += ' table-condensed';
4088         }
4089         if (this.responsive) {
4090             cfg.cls += ' table-responsive';
4091         }
4092         
4093           
4094         
4095         
4096         if (this.cls) {
4097             cfg.cls+=  ' ' +this.cls;
4098         }
4099         
4100         // this lot should be simplifed...
4101         
4102         if (this.align) {
4103             cfg.align=this.align;
4104         }
4105         if (this.bgcolor) {
4106             cfg.bgcolor=this.bgcolor;
4107         }
4108         if (this.border) {
4109             cfg.border=this.border;
4110         }
4111         if (this.cellpadding) {
4112             cfg.cellpadding=this.cellpadding;
4113         }
4114         if (this.cellspacing) {
4115             cfg.cellspacing=this.cellspacing;
4116         }
4117         if (this.frame) {
4118             cfg.frame=this.frame;
4119         }
4120         if (this.rules) {
4121             cfg.rules=this.rules;
4122         }
4123         if (this.sortable) {
4124             cfg.sortable=this.sortable;
4125         }
4126         if (this.summary) {
4127             cfg.summary=this.summary;
4128         }
4129         if (this.width) {
4130             cfg.width=this.width;
4131         }
4132         
4133         if(this.store || this.cm){
4134             cfg.cn.push(this.renderHeader());
4135             cfg.cn.push(this.renderBody());
4136             cfg.cn.push(this.renderFooter());
4137             
4138             cfg.cls+=  ' TableGrid';
4139         }
4140         
4141         return cfg;
4142     },
4143 //    
4144 //    initTableGrid : function()
4145 //    {
4146 //        var cfg = {};
4147 //        
4148 //        var header = {
4149 //            tag: 'thead',
4150 //            cn : []
4151 //        };
4152 //        
4153 //        var cm = this.cm;
4154 //        
4155 //        for(var i = 0, len = cm.getColumnCount(); i < len; i++){
4156 //            header.cn.push({
4157 //                tag: 'th',
4158 //                html: cm.getColumnHeader(i)
4159 //            })
4160 //        }
4161 //        
4162 //        cfg.push(header);
4163 //        
4164 //        return cfg;
4165 //        
4166 //        
4167 //    },
4168     
4169     initEvents : function()
4170     {   
4171         if(!this.store || !this.cm){
4172             return;
4173         }
4174         
4175         Roo.log('initEvents with ds!!!!');
4176         
4177         var _this = this;
4178         
4179         Roo.each(this.el.select('thead th.sortable', true).elements, function(e){
4180             e.on('click', _this.sort, _this);
4181         });
4182 //        this.maskEl = Roo.DomHelper.append(this.el.select('.TableGrid', true).first(), {tag: "div", cls:"x-dlg-mask"}, true);
4183 //        this.maskEl.enableDisplayMode("block");
4184 //        this.maskEl.show();
4185         
4186         this.store.on('load', this.onLoad, this);
4187         this.store.on('beforeload', this.onBeforeLoad, this);
4188         
4189         this.store.load();
4190         
4191         
4192         
4193     },
4194     
4195     sort : function(e,el)
4196     {
4197         var col = Roo.get(el)
4198         
4199         if(!col.hasClass('sortable')){
4200             return;
4201         }
4202         
4203         var sort = col.attr('sort');
4204         var dir = 'ASC';
4205         
4206         if(col.hasClass('glyphicon-arrow-up')){
4207             dir = 'DESC';
4208         }
4209         
4210         this.store.sortInfo = {field : sort, direction : dir};
4211         
4212         this.store.load();
4213     },
4214     
4215     renderHeader : function()
4216     {
4217         var header = {
4218             tag: 'thead',
4219             cn : []
4220         };
4221         
4222         var cm = this.cm;
4223         
4224         for(var i = 0, len = cm.getColumnCount(); i < len; i++){
4225             
4226             var config = cm.config[i];
4227             
4228             var c = {
4229                 tag: 'th',
4230                 html: cm.getColumnHeader(i)
4231             };
4232             
4233             if(typeof(config.dataIndex) != 'undefined'){
4234                 c.sort = config.dataIndex;
4235             }
4236             
4237             if(typeof(config.sortable) != 'undefined' && config.sortable){
4238                 c.cls = 'sortable';
4239             }
4240             
4241             if(typeof(config.width) != 'undefined'){
4242                 c.style = 'width:' + config.width + 'px';
4243             }
4244             
4245             header.cn.push(c)
4246         }
4247         
4248         return header;
4249     },
4250     
4251     renderBody : function()
4252     {
4253         var body = {
4254             tag: 'tbody',
4255             cn : []
4256         };
4257         
4258         return body;
4259     },
4260     
4261     renderFooter : function()
4262     {
4263         var footer = {
4264             tag: 'tfoot',
4265             cn : []
4266         };
4267         
4268         return footer;
4269     },
4270     
4271     onLoad : function()
4272     {
4273         Roo.log('ds onload');
4274         
4275         var _this = this;
4276         var cm = this.cm;
4277         
4278         Roo.each(this.el.select('thead th.sortable', true).elements, function(e){
4279             e.removeClass(['glyphicon', 'glyphicon-arrow-up', 'glyphicon-arrow-down']);
4280             
4281             if(e.hasClass('sortable') && e.attr('sort') == _this.store.sortInfo.field && _this.store.sortInfo.direction.toUpperCase() == 'ASC'){
4282                 e.addClass(['glyphicon', 'glyphicon-arrow-up']);
4283             }
4284             
4285             if(e.hasClass('sortable') && e.attr('sort') == _this.store.sortInfo.field && _this.store.sortInfo.direction.toUpperCase() == 'DESC'){
4286                 e.addClass(['glyphicon', 'glyphicon-arrow-down']);
4287             }
4288         });
4289         
4290         var tbody = this.el.select('tbody', true).first();
4291         
4292         var renders = [];
4293         
4294         if(this.store.getCount() > 0){
4295             this.store.data.each(function(d){
4296                 var row = {
4297                     tag : 'tr',
4298                     cn : []
4299                 };
4300                 
4301                 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
4302                     var renderer = cm.getRenderer(i);
4303                     var config = cm.config[i];
4304                     var value = '';
4305                     var id = Roo.id();
4306                     
4307                     if(typeof(renderer) !== 'undefined'){
4308                         value = renderer(d.data[cm.getDataIndex(i)], false, d);
4309                     }
4310                     
4311                     if(typeof(value) === 'object'){
4312                         renders.push({
4313                             id : id,
4314                             cfg : value 
4315                         })
4316                     }
4317                     
4318                     var td = {
4319                         tag: 'td',
4320                         id: id,
4321                         html: (typeof(value) === 'object') ? '' : value
4322                     };
4323                     
4324                     if(typeof(config.width) != 'undefined'){
4325                         td.style = 'width:' +  config.width + 'px';
4326                     }
4327                     
4328                     row.cn.push(td);
4329                    
4330                 }
4331                 
4332                 tbody.createChild(row);
4333                 
4334             });
4335         }
4336         
4337         
4338         if(renders.length){
4339             var _this = this;
4340             Roo.each(renders, function(r){
4341                 _this.renderColumn(r);
4342             })
4343         }
4344 //        
4345 //        if(this.loadMask){
4346 //            this.maskEl.hide();
4347 //        }
4348     },
4349     
4350     onBeforeLoad : function()
4351     {
4352         Roo.log('ds onBeforeLoad');
4353         
4354         this.clear();
4355         
4356 //        if(this.loadMask){
4357 //            this.maskEl.show();
4358 //        }
4359     },
4360     
4361     clear : function()
4362     {
4363         this.el.select('tbody', true).first().dom.innerHTML = '';
4364     },
4365     
4366     getSelectionModel : function(){
4367         if(!this.selModel){
4368             this.selModel = new Roo.bootstrap.Table.RowSelectionModel();
4369         }
4370         return this.selModel;
4371     },
4372     
4373     renderColumn : function(r)
4374     {
4375         var _this = this;
4376         r.cfg.render(Roo.get(r.id));
4377         
4378         if(r.cfg.cn){
4379             Roo.each(r.cfg.cn, function(c){
4380                 var child = {
4381                     id: r.id,
4382                     cfg: c
4383                 }
4384                 _this.renderColumn(child);
4385             })
4386         }
4387     }
4388    
4389 });
4390
4391  
4392
4393  /*
4394  * - LGPL
4395  *
4396  * table cell
4397  * 
4398  */
4399
4400 /**
4401  * @class Roo.bootstrap.TableCell
4402  * @extends Roo.bootstrap.Component
4403  * Bootstrap TableCell class
4404  * @cfg {String} html cell contain text
4405  * @cfg {String} cls cell class
4406  * @cfg {String} tag cell tag (td|th) default td
4407  * @cfg {String} abbr Specifies an abbreviated version of the content in a cell
4408  * @cfg {String} align Aligns the content in a cell
4409  * @cfg {String} axis Categorizes cells
4410  * @cfg {String} bgcolor Specifies the background color of a cell
4411  * @cfg {Number} charoff Sets the number of characters the content will be aligned from the character specified by the char attribute
4412  * @cfg {Number} colspan Specifies the number of columns a cell should span
4413  * @cfg {String} headers Specifies one or more header cells a cell is related to
4414  * @cfg {Number} height Sets the height of a cell
4415  * @cfg {String} nowrap Specifies that the content inside a cell should not wrap
4416  * @cfg {Number} rowspan Sets the number of rows a cell should span
4417  * @cfg {String} scope Defines a way to associate header cells and data cells in a table
4418  * @cfg {String} valign Vertical aligns the content in a cell
4419  * @cfg {Number} width Specifies the width of a cell
4420  * 
4421  * @constructor
4422  * Create a new TableCell
4423  * @param {Object} config The config object
4424  */
4425
4426 Roo.bootstrap.TableCell = function(config){
4427     Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
4428 };
4429
4430 Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component,  {
4431     
4432     html: false,
4433     cls: false,
4434     tag: false,
4435     abbr: false,
4436     align: false,
4437     axis: false,
4438     bgcolor: false,
4439     charoff: false,
4440     colspan: false,
4441     headers: false,
4442     height: false,
4443     nowrap: false,
4444     rowspan: false,
4445     scope: false,
4446     valign: false,
4447     width: false,
4448     
4449     
4450     getAutoCreate : function(){
4451         var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
4452         
4453         cfg = {
4454             tag: 'td'
4455         }
4456         
4457         if(this.tag){
4458             cfg.tag = this.tag;
4459         }
4460         
4461         if (this.html) {
4462             cfg.html=this.html
4463         }
4464         if (this.cls) {
4465             cfg.cls=this.cls
4466         }
4467         if (this.abbr) {
4468             cfg.abbr=this.abbr
4469         }
4470         if (this.align) {
4471             cfg.align=this.align
4472         }
4473         if (this.axis) {
4474             cfg.axis=this.axis
4475         }
4476         if (this.bgcolor) {
4477             cfg.bgcolor=this.bgcolor
4478         }
4479         if (this.charoff) {
4480             cfg.charoff=this.charoff
4481         }
4482         if (this.colspan) {
4483             cfg.colspan=this.colspan
4484         }
4485         if (this.headers) {
4486             cfg.headers=this.headers
4487         }
4488         if (this.height) {
4489             cfg.height=this.height
4490         }
4491         if (this.nowrap) {
4492             cfg.nowrap=this.nowrap
4493         }
4494         if (this.rowspan) {
4495             cfg.rowspan=this.rowspan
4496         }
4497         if (this.scope) {
4498             cfg.scope=this.scope
4499         }
4500         if (this.valign) {
4501             cfg.valign=this.valign
4502         }
4503         if (this.width) {
4504             cfg.width=this.width
4505         }
4506         
4507         
4508         return cfg;
4509     }
4510    
4511 });
4512
4513  
4514
4515  /*
4516  * - LGPL
4517  *
4518  * table row
4519  * 
4520  */
4521
4522 /**
4523  * @class Roo.bootstrap.TableRow
4524  * @extends Roo.bootstrap.Component
4525  * Bootstrap TableRow class
4526  * @cfg {String} cls row class
4527  * @cfg {String} align Aligns the content in a table row
4528  * @cfg {String} bgcolor Specifies a background color for a table row
4529  * @cfg {Number} charoff Sets the number of characters the content will be aligned from the character specified by the char attribute
4530  * @cfg {String} valign Vertical aligns the content in a table row
4531  * 
4532  * @constructor
4533  * Create a new TableRow
4534  * @param {Object} config The config object
4535  */
4536
4537 Roo.bootstrap.TableRow = function(config){
4538     Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
4539 };
4540
4541 Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component,  {
4542     
4543     cls: false,
4544     align: false,
4545     bgcolor: false,
4546     charoff: false,
4547     valign: false,
4548     
4549     getAutoCreate : function(){
4550         var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
4551         
4552         cfg = {
4553             tag: 'tr'
4554         }
4555             
4556         if(this.cls){
4557             cfg.cls = this.cls;
4558         }
4559         if(this.align){
4560             cfg.align = this.align;
4561         }
4562         if(this.bgcolor){
4563             cfg.bgcolor = this.bgcolor;
4564         }
4565         if(this.charoff){
4566             cfg.charoff = this.charoff;
4567         }
4568         if(this.valign){
4569             cfg.valign = this.valign;
4570         }
4571         
4572         return cfg;
4573     }
4574    
4575 });
4576
4577  
4578
4579  /*
4580  * - LGPL
4581  *
4582  * table body
4583  * 
4584  */
4585
4586 /**
4587  * @class Roo.bootstrap.TableBody
4588  * @extends Roo.bootstrap.Component
4589  * Bootstrap TableBody class
4590  * @cfg {String} cls element class
4591  * @cfg {String} tag element tag (thead|tbody|tfoot) default tbody
4592  * @cfg {String} align Aligns the content inside the element
4593  * @cfg {Number} charoff Sets the number of characters the content inside the element will be aligned from the character specified by the char attribute
4594  * @cfg {String} valign Vertical aligns the content inside the <tbody> element
4595  * 
4596  * @constructor
4597  * Create a new TableBody
4598  * @param {Object} config The config object
4599  */
4600
4601 Roo.bootstrap.TableBody = function(config){
4602     Roo.bootstrap.TableBody.superclass.constructor.call(this, config);
4603 };
4604
4605 Roo.extend(Roo.bootstrap.TableBody, Roo.bootstrap.Component,  {
4606     
4607     cls: false,
4608     tag: false,
4609     align: false,
4610     charoff: false,
4611     valign: false,
4612     
4613     getAutoCreate : function(){
4614         var cfg = Roo.apply({}, Roo.bootstrap.TableBody.superclass.getAutoCreate.call(this));
4615         
4616         cfg = {
4617             tag: 'tbody'
4618         }
4619             
4620         if (this.cls) {
4621             cfg.cls=this.cls
4622         }
4623         if(this.tag){
4624             cfg.tag = this.tag;
4625         }
4626         
4627         if(this.align){
4628             cfg.align = this.align;
4629         }
4630         if(this.charoff){
4631             cfg.charoff = this.charoff;
4632         }
4633         if(this.valign){
4634             cfg.valign = this.valign;
4635         }
4636         
4637         return cfg;
4638     }
4639     
4640     
4641 //    initEvents : function()
4642 //    {
4643 //        
4644 //        if(!this.store){
4645 //            return;
4646 //        }
4647 //        
4648 //        this.store = Roo.factory(this.store, Roo.data);
4649 //        this.store.on('load', this.onLoad, this);
4650 //        
4651 //        this.store.load();
4652 //        
4653 //    },
4654 //    
4655 //    onLoad: function () 
4656 //    {   
4657 //        this.fireEvent('load', this);
4658 //    }
4659 //    
4660 //   
4661 });
4662
4663  
4664
4665  /*
4666  * Based on:
4667  * Ext JS Library 1.1.1
4668  * Copyright(c) 2006-2007, Ext JS, LLC.
4669  *
4670  * Originally Released Under LGPL - original licence link has changed is not relivant.
4671  *
4672  * Fork - LGPL
4673  * <script type="text/javascript">
4674  */
4675
4676 // as we use this in bootstrap.
4677 Roo.namespace('Roo.form');
4678  /**
4679  * @class Roo.form.Action
4680  * Internal Class used to handle form actions
4681  * @constructor
4682  * @param {Roo.form.BasicForm} el The form element or its id
4683  * @param {Object} config Configuration options
4684  */
4685
4686  
4687  
4688 // define the action interface
4689 Roo.form.Action = function(form, options){
4690     this.form = form;
4691     this.options = options || {};
4692 };
4693 /**
4694  * Client Validation Failed
4695  * @const 
4696  */
4697 Roo.form.Action.CLIENT_INVALID = 'client';
4698 /**
4699  * Server Validation Failed
4700  * @const 
4701  */
4702 Roo.form.Action.SERVER_INVALID = 'server';
4703  /**
4704  * Connect to Server Failed
4705  * @const 
4706  */
4707 Roo.form.Action.CONNECT_FAILURE = 'connect';
4708 /**
4709  * Reading Data from Server Failed
4710  * @const 
4711  */
4712 Roo.form.Action.LOAD_FAILURE = 'load';
4713
4714 Roo.form.Action.prototype = {
4715     type : 'default',
4716     failureType : undefined,
4717     response : undefined,
4718     result : undefined,
4719
4720     // interface method
4721     run : function(options){
4722
4723     },
4724
4725     // interface method
4726     success : function(response){
4727
4728     },
4729
4730     // interface method
4731     handleResponse : function(response){
4732
4733     },
4734
4735     // default connection failure
4736     failure : function(response){
4737         
4738         this.response = response;
4739         this.failureType = Roo.form.Action.CONNECT_FAILURE;
4740         this.form.afterAction(this, false);
4741     },
4742
4743     processResponse : function(response){
4744         this.response = response;
4745         if(!response.responseText){
4746             return true;
4747         }
4748         this.result = this.handleResponse(response);
4749         return this.result;
4750     },
4751
4752     // utility functions used internally
4753     getUrl : function(appendParams){
4754         var url = this.options.url || this.form.url || this.form.el.dom.action;
4755         if(appendParams){
4756             var p = this.getParams();
4757             if(p){
4758                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
4759             }
4760         }
4761         return url;
4762     },
4763
4764     getMethod : function(){
4765         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
4766     },
4767
4768     getParams : function(){
4769         var bp = this.form.baseParams;
4770         var p = this.options.params;
4771         if(p){
4772             if(typeof p == "object"){
4773                 p = Roo.urlEncode(Roo.applyIf(p, bp));
4774             }else if(typeof p == 'string' && bp){
4775                 p += '&' + Roo.urlEncode(bp);
4776             }
4777         }else if(bp){
4778             p = Roo.urlEncode(bp);
4779         }
4780         return p;
4781     },
4782
4783     createCallback : function(){
4784         return {
4785             success: this.success,
4786             failure: this.failure,
4787             scope: this,
4788             timeout: (this.form.timeout*1000),
4789             upload: this.form.fileUpload ? this.success : undefined
4790         };
4791     }
4792 };
4793
4794 Roo.form.Action.Submit = function(form, options){
4795     Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
4796 };
4797
4798 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
4799     type : 'submit',
4800
4801     haveProgress : false,
4802     uploadComplete : false,
4803     
4804     // uploadProgress indicator.
4805     uploadProgress : function()
4806     {
4807         if (!this.form.progressUrl) {
4808             return;
4809         }
4810         
4811         if (!this.haveProgress) {
4812             Roo.MessageBox.progress("Uploading", "Uploading");
4813         }
4814         if (this.uploadComplete) {
4815            Roo.MessageBox.hide();
4816            return;
4817         }
4818         
4819         this.haveProgress = true;
4820    
4821         var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
4822         
4823         var c = new Roo.data.Connection();
4824         c.request({
4825             url : this.form.progressUrl,
4826             params: {
4827                 id : uid
4828             },
4829             method: 'GET',
4830             success : function(req){
4831                //console.log(data);
4832                 var rdata = false;
4833                 var edata;
4834                 try  {
4835                    rdata = Roo.decode(req.responseText)
4836                 } catch (e) {
4837                     Roo.log("Invalid data from server..");
4838                     Roo.log(edata);
4839                     return;
4840                 }
4841                 if (!rdata || !rdata.success) {
4842                     Roo.log(rdata);
4843                     Roo.MessageBox.alert(Roo.encode(rdata));
4844                     return;
4845                 }
4846                 var data = rdata.data;
4847                 
4848                 if (this.uploadComplete) {
4849                    Roo.MessageBox.hide();
4850                    return;
4851                 }
4852                    
4853                 if (data){
4854                     Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
4855                        Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
4856                     );
4857                 }
4858                 this.uploadProgress.defer(2000,this);
4859             },
4860        
4861             failure: function(data) {
4862                 Roo.log('progress url failed ');
4863                 Roo.log(data);
4864             },
4865             scope : this
4866         });
4867            
4868     },
4869     
4870     
4871     run : function()
4872     {
4873         // run get Values on the form, so it syncs any secondary forms.
4874         this.form.getValues();
4875         
4876         var o = this.options;
4877         var method = this.getMethod();
4878         var isPost = method == 'POST';
4879         if(o.clientValidation === false || this.form.isValid()){
4880             
4881             if (this.form.progressUrl) {
4882                 this.form.findField('UPLOAD_IDENTIFIER').setValue(
4883                     (new Date() * 1) + '' + Math.random());
4884                     
4885             } 
4886             
4887             
4888             Roo.Ajax.request(Roo.apply(this.createCallback(), {
4889                 form:this.form.el.dom,
4890                 url:this.getUrl(!isPost),
4891                 method: method,
4892                 params:isPost ? this.getParams() : null,
4893                 isUpload: this.form.fileUpload
4894             }));
4895             
4896             this.uploadProgress();
4897
4898         }else if (o.clientValidation !== false){ // client validation failed
4899             this.failureType = Roo.form.Action.CLIENT_INVALID;
4900             this.form.afterAction(this, false);
4901         }
4902     },
4903
4904     success : function(response)
4905     {
4906         this.uploadComplete= true;
4907         if (this.haveProgress) {
4908             Roo.MessageBox.hide();
4909         }
4910         
4911         
4912         var result = this.processResponse(response);
4913         if(result === true || result.success){
4914             this.form.afterAction(this, true);
4915             return;
4916         }
4917         if(result.errors){
4918             this.form.markInvalid(result.errors);
4919             this.failureType = Roo.form.Action.SERVER_INVALID;
4920         }
4921         this.form.afterAction(this, false);
4922     },
4923     failure : function(response)
4924     {
4925         this.uploadComplete= true;
4926         if (this.haveProgress) {
4927             Roo.MessageBox.hide();
4928         }
4929         
4930         this.response = response;
4931         this.failureType = Roo.form.Action.CONNECT_FAILURE;
4932         this.form.afterAction(this, false);
4933     },
4934     
4935     handleResponse : function(response){
4936         if(this.form.errorReader){
4937             var rs = this.form.errorReader.read(response);
4938             var errors = [];
4939             if(rs.records){
4940                 for(var i = 0, len = rs.records.length; i < len; i++) {
4941                     var r = rs.records[i];
4942                     errors[i] = r.data;
4943                 }
4944             }
4945             if(errors.length < 1){
4946                 errors = null;
4947             }
4948             return {
4949                 success : rs.success,
4950                 errors : errors
4951             };
4952         }
4953         var ret = false;
4954         try {
4955             ret = Roo.decode(response.responseText);
4956         } catch (e) {
4957             ret = {
4958                 success: false,
4959                 errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
4960                 errors : []
4961             };
4962         }
4963         return ret;
4964         
4965     }
4966 });
4967
4968
4969 Roo.form.Action.Load = function(form, options){
4970     Roo.form.Action.Load.superclass.constructor.call(this, form, options);
4971     this.reader = this.form.reader;
4972 };
4973
4974 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
4975     type : 'load',
4976
4977     run : function(){
4978         
4979         Roo.Ajax.request(Roo.apply(
4980                 this.createCallback(), {
4981                     method:this.getMethod(),
4982                     url:this.getUrl(false),
4983                     params:this.getParams()
4984         }));
4985     },
4986
4987     success : function(response){
4988         
4989         var result = this.processResponse(response);
4990         if(result === true || !result.success || !result.data){
4991             this.failureType = Roo.form.Action.LOAD_FAILURE;
4992             this.form.afterAction(this, false);
4993             return;
4994         }
4995         this.form.clearInvalid();
4996         this.form.setValues(result.data);
4997         this.form.afterAction(this, true);
4998     },
4999
5000     handleResponse : function(response){
5001         if(this.form.reader){
5002             var rs = this.form.reader.read(response);
5003             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
5004             return {
5005                 success : rs.success,
5006                 data : data
5007             };
5008         }
5009         return Roo.decode(response.responseText);
5010     }
5011 });
5012
5013 Roo.form.Action.ACTION_TYPES = {
5014     'load' : Roo.form.Action.Load,
5015     'submit' : Roo.form.Action.Submit
5016 };/*
5017  * - LGPL
5018  *
5019  * form
5020  * 
5021  */
5022
5023 /**
5024  * @class Roo.bootstrap.Form
5025  * @extends Roo.bootstrap.Component
5026  * Bootstrap Form class
5027  * @cfg {String} method  GET | POST (default POST)
5028  * @cfg {String} labelAlign top | left (default top)
5029   * @cfg {String} align left  | right - for navbars
5030
5031  * 
5032  * @constructor
5033  * Create a new Form
5034  * @param {Object} config The config object
5035  */
5036
5037
5038 Roo.bootstrap.Form = function(config){
5039     Roo.bootstrap.Form.superclass.constructor.call(this, config);
5040     this.addEvents({
5041         /**
5042          * @event clientvalidation
5043          * If the monitorValid config option is true, this event fires repetitively to notify of valid state
5044          * @param {Form} this
5045          * @param {Boolean} valid true if the form has passed client-side validation
5046          */
5047         clientvalidation: true,
5048         /**
5049          * @event beforeaction
5050          * Fires before any action is performed. Return false to cancel the action.
5051          * @param {Form} this
5052          * @param {Action} action The action to be performed
5053          */
5054         beforeaction: true,
5055         /**
5056          * @event actionfailed
5057          * Fires when an action fails.
5058          * @param {Form} this
5059          * @param {Action} action The action that failed
5060          */
5061         actionfailed : true,
5062         /**
5063          * @event actioncomplete
5064          * Fires when an action is completed.
5065          * @param {Form} this
5066          * @param {Action} action The action that completed
5067          */
5068         actioncomplete : true
5069     });
5070     
5071 };
5072
5073 Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
5074       
5075      /**
5076      * @cfg {String} method
5077      * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
5078      */
5079     method : 'POST',
5080     /**
5081      * @cfg {String} url
5082      * The URL to use for form actions if one isn't supplied in the action options.
5083      */
5084     /**
5085      * @cfg {Boolean} fileUpload
5086      * Set to true if this form is a file upload.
5087      */
5088      
5089     /**
5090      * @cfg {Object} baseParams
5091      * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
5092      */
5093       
5094     /**
5095      * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
5096      */
5097     timeout: 30,
5098     /**
5099      * @cfg {Sting} align (left|right) for navbar forms
5100      */
5101     align : 'left',
5102
5103     // private
5104     activeAction : null,
5105  
5106     /**
5107      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
5108      * element by passing it or its id or mask the form itself by passing in true.
5109      * @type Mixed
5110      */
5111     waitMsgTarget : false,
5112     
5113      
5114     
5115     /**
5116      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
5117      * element by passing it or its id or mask the form itself by passing in true.
5118      * @type Mixed
5119      */
5120     
5121     getAutoCreate : function(){
5122         
5123         var cfg = {
5124             tag: 'form',
5125             method : this.method || 'POST',
5126             id : this.id || Roo.id(),
5127             cls : ''
5128         }
5129         if (this.parent().xtype.match(/^Nav/)) {
5130             cfg.cls = 'navbar-form navbar-' + this.align;
5131             
5132         }
5133         
5134         if (this.labelAlign == 'left' ) {
5135             cfg.cls += ' form-horizontal';
5136         }
5137         
5138         
5139         return cfg;
5140     },
5141     initEvents : function()
5142     {
5143         this.el.on('submit', this.onSubmit, this);
5144         
5145         
5146     },
5147     // private
5148     onSubmit : function(e){
5149         e.stopEvent();
5150     },
5151     
5152      /**
5153      * Returns true if client-side validation on the form is successful.
5154      * @return Boolean
5155      */
5156     isValid : function(){
5157         var items = this.getItems();
5158         var valid = true;
5159         items.each(function(f){
5160            if(!f.validate()){
5161                valid = false;
5162                
5163            }
5164         });
5165         return valid;
5166     },
5167     /**
5168      * Returns true if any fields in this form have changed since their original load.
5169      * @return Boolean
5170      */
5171     isDirty : function(){
5172         var dirty = false;
5173         var items = this.getItems();
5174         items.each(function(f){
5175            if(f.isDirty()){
5176                dirty = true;
5177                return false;
5178            }
5179            return true;
5180         });
5181         return dirty;
5182     },
5183      /**
5184      * Performs a predefined action (submit or load) or custom actions you define on this form.
5185      * @param {String} actionName The name of the action type
5186      * @param {Object} options (optional) The options to pass to the action.  All of the config options listed
5187      * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
5188      * accept other config options):
5189      * <pre>
5190 Property          Type             Description
5191 ----------------  ---------------  ----------------------------------------------------------------------------------
5192 url               String           The url for the action (defaults to the form's url)
5193 method            String           The form method to use (defaults to the form's method, or POST if not defined)
5194 params            String/Object    The params to pass (defaults to the form's baseParams, or none if not defined)
5195 clientValidation  Boolean          Applies to submit only.  Pass true to call form.isValid() prior to posting to
5196                                    validate the form on the client (defaults to false)
5197      * </pre>
5198      * @return {BasicForm} this
5199      */
5200     doAction : function(action, options){
5201         if(typeof action == 'string'){
5202             action = new Roo.form.Action.ACTION_TYPES[action](this, options);
5203         }
5204         if(this.fireEvent('beforeaction', this, action) !== false){
5205             this.beforeAction(action);
5206             action.run.defer(100, action);
5207         }
5208         return this;
5209     },
5210     
5211     // private
5212     beforeAction : function(action){
5213         var o = action.options;
5214         
5215         // not really supported yet.. ??
5216         
5217         //if(this.waitMsgTarget === true){
5218             this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
5219         //}else if(this.waitMsgTarget){
5220         //    this.waitMsgTarget = Roo.get(this.waitMsgTarget);
5221         //    this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
5222         //}else {
5223         //    Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
5224        // }
5225          
5226     },
5227
5228     // private
5229     afterAction : function(action, success){
5230         this.activeAction = null;
5231         var o = action.options;
5232         
5233         //if(this.waitMsgTarget === true){
5234             this.el.unmask();
5235         //}else if(this.waitMsgTarget){
5236         //    this.waitMsgTarget.unmask();
5237         //}else{
5238         //    Roo.MessageBox.updateProgress(1);
5239         //    Roo.MessageBox.hide();
5240        // }
5241         // 
5242         if(success){
5243             if(o.reset){
5244                 this.reset();
5245             }
5246             Roo.callback(o.success, o.scope, [this, action]);
5247             this.fireEvent('actioncomplete', this, action);
5248             
5249         }else{
5250             
5251             // failure condition..
5252             // we have a scenario where updates need confirming.
5253             // eg. if a locking scenario exists..
5254             // we look for { errors : { needs_confirm : true }} in the response.
5255             if (
5256                 (typeof(action.result) != 'undefined')  &&
5257                 (typeof(action.result.errors) != 'undefined')  &&
5258                 (typeof(action.result.errors.needs_confirm) != 'undefined')
5259            ){
5260                 var _t = this;
5261                 Roo.log("not supported yet");
5262                  /*
5263                 
5264                 Roo.MessageBox.confirm(
5265                     "Change requires confirmation",
5266                     action.result.errorMsg,
5267                     function(r) {
5268                         if (r != 'yes') {
5269                             return;
5270                         }
5271                         _t.doAction('submit', { params :  { _submit_confirmed : 1 } }  );
5272                     }
5273                     
5274                 );
5275                 */
5276                 
5277                 
5278                 return;
5279             }
5280             
5281             Roo.callback(o.failure, o.scope, [this, action]);
5282             // show an error message if no failed handler is set..
5283             if (!this.hasListener('actionfailed')) {
5284                 Roo.log("need to add dialog support");
5285                 /*
5286                 Roo.MessageBox.alert("Error",
5287                     (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
5288                         action.result.errorMsg :
5289                         "Saving Failed, please check your entries or try again"
5290                 );
5291                 */
5292             }
5293             
5294             this.fireEvent('actionfailed', this, action);
5295         }
5296         
5297     },
5298     /**
5299      * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
5300      * @param {String} id The value to search for
5301      * @return Field
5302      */
5303     findField : function(id){
5304         var items = this.getItems();
5305         var field = items.get(id);
5306         if(!field){
5307              items.each(function(f){
5308                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
5309                     field = f;
5310                     return false;
5311                 }
5312                 return true;
5313             });
5314         }
5315         return field || null;
5316     },
5317      /**
5318      * Mark fields in this form invalid in bulk.
5319      * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
5320      * @return {BasicForm} this
5321      */
5322     markInvalid : function(errors){
5323         if(errors instanceof Array){
5324             for(var i = 0, len = errors.length; i < len; i++){
5325                 var fieldError = errors[i];
5326                 var f = this.findField(fieldError.id);
5327                 if(f){
5328                     f.markInvalid(fieldError.msg);
5329                 }
5330             }
5331         }else{
5332             var field, id;
5333             for(id in errors){
5334                 if(typeof errors[id] != 'function' && (field = this.findField(id))){
5335                     field.markInvalid(errors[id]);
5336                 }
5337             }
5338         }
5339         //Roo.each(this.childForms || [], function (f) {
5340         //    f.markInvalid(errors);
5341         //});
5342         
5343         return this;
5344     },
5345
5346     /**
5347      * Set values for fields in this form in bulk.
5348      * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
5349      * @return {BasicForm} this
5350      */
5351     setValues : function(values){
5352         if(values instanceof Array){ // array of objects
5353             for(var i = 0, len = values.length; i < len; i++){
5354                 var v = values[i];
5355                 var f = this.findField(v.id);
5356                 if(f){
5357                     f.setValue(v.value);
5358                     if(this.trackResetOnLoad){
5359                         f.originalValue = f.getValue();
5360                     }
5361                 }
5362             }
5363         }else{ // object hash
5364             var field, id;
5365             for(id in values){
5366                 if(typeof values[id] != 'function' && (field = this.findField(id))){
5367                     
5368                     if (field.setFromData && 
5369                         field.valueField && 
5370                         field.displayField &&
5371                         // combos' with local stores can 
5372                         // be queried via setValue()
5373                         // to set their value..
5374                         (field.store && !field.store.isLocal)
5375                         ) {
5376                         // it's a combo
5377                         var sd = { };
5378                         sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
5379                         sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
5380                         field.setFromData(sd);
5381                         
5382                     } else {
5383                         field.setValue(values[id]);
5384                     }
5385                     
5386                     
5387                     if(this.trackResetOnLoad){
5388                         field.originalValue = field.getValue();
5389                     }
5390                 }
5391             }
5392         }
5393          
5394         //Roo.each(this.childForms || [], function (f) {
5395         //    f.setValues(values);
5396         //});
5397                 
5398         return this;
5399     },
5400
5401     /**
5402      * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
5403      * they are returned as an array.
5404      * @param {Boolean} asString
5405      * @return {Object}
5406      */
5407     getValues : function(asString){
5408         //if (this.childForms) {
5409             // copy values from the child forms
5410         //    Roo.each(this.childForms, function (f) {
5411         //        this.setValues(f.getValues());
5412         //    }, this);
5413         //}
5414         
5415         
5416         
5417         var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
5418         if(asString === true){
5419             return fs;
5420         }
5421         return Roo.urlDecode(fs);
5422     },
5423     
5424     /**
5425      * Returns the fields in this form as an object with key/value pairs. 
5426      * This differs from getValues as it calls getValue on each child item, rather than using dom data.
5427      * @return {Object}
5428      */
5429     getFieldValues : function(with_hidden)
5430     {
5431         var items = this.getItems();
5432         var ret = {};
5433         items.each(function(f){
5434             if (!f.getName()) {
5435                 return;
5436             }
5437             var v = f.getValue();
5438             if (f.inputType =='radio') {
5439                 if (typeof(ret[f.getName()]) == 'undefined') {
5440                     ret[f.getName()] = ''; // empty..
5441                 }
5442                 
5443                 if (!f.el.dom.checked) {
5444                     return;
5445                     
5446                 }
5447                 v = f.el.dom.value;
5448                 
5449             }
5450             
5451             // not sure if this supported any more..
5452             if ((typeof(v) == 'object') && f.getRawValue) {
5453                 v = f.getRawValue() ; // dates..
5454             }
5455             // combo boxes where name != hiddenName...
5456             if (f.name != f.getName()) {
5457                 ret[f.name] = f.getRawValue();
5458             }
5459             ret[f.getName()] = v;
5460         });
5461         
5462         return ret;
5463     },
5464
5465     /**
5466      * Clears all invalid messages in this form.
5467      * @return {BasicForm} this
5468      */
5469     clearInvalid : function(){
5470         var items = this.getItems();
5471         
5472         items.each(function(f){
5473            f.clearInvalid();
5474         });
5475         
5476         
5477         
5478         return this;
5479     },
5480
5481     /**
5482      * Resets this form.
5483      * @return {BasicForm} this
5484      */
5485     reset : function(){
5486         var items = this.getItems();
5487         items.each(function(f){
5488             f.reset();
5489         });
5490         
5491         Roo.each(this.childForms || [], function (f) {
5492             f.reset();
5493         });
5494        
5495         
5496         return this;
5497     },
5498     getItems : function()
5499     {
5500         var r=new Roo.util.MixedCollection(false, function(o){
5501             return o.id || (o.id = Roo.id());
5502         });
5503         var iter = function(el) {
5504             if (el.inputEl) {
5505                 r.add(el);
5506             }
5507             if (!el.items) {
5508                 return;
5509             }
5510             Roo.each(el.items,function(e) {
5511                 iter(e);
5512             });
5513             
5514             
5515         };
5516         iter(this);
5517         return r;
5518         
5519         
5520         
5521         
5522     }
5523     
5524 });
5525
5526  
5527 /*
5528  * Based on:
5529  * Ext JS Library 1.1.1
5530  * Copyright(c) 2006-2007, Ext JS, LLC.
5531  *
5532  * Originally Released Under LGPL - original licence link has changed is not relivant.
5533  *
5534  * Fork - LGPL
5535  * <script type="text/javascript">
5536  */
5537 /**
5538  * @class Roo.form.VTypes
5539  * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
5540  * @singleton
5541  */
5542 Roo.form.VTypes = function(){
5543     // closure these in so they are only created once.
5544     var alpha = /^[a-zA-Z_]+$/;
5545     var alphanum = /^[a-zA-Z0-9_]+$/;
5546     var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
5547     var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
5548
5549     // All these messages and functions are configurable
5550     return {
5551         /**
5552          * The function used to validate email addresses
5553          * @param {String} value The email address
5554          */
5555         'email' : function(v){
5556             return email.test(v);
5557         },
5558         /**
5559          * The error text to display when the email validation function returns false
5560          * @type String
5561          */
5562         'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
5563         /**
5564          * The keystroke filter mask to be applied on email input
5565          * @type RegExp
5566          */
5567         'emailMask' : /[a-z0-9_\.\-@]/i,
5568
5569         /**
5570          * The function used to validate URLs
5571          * @param {String} value The URL
5572          */
5573         'url' : function(v){
5574             return url.test(v);
5575         },
5576         /**
5577          * The error text to display when the url validation function returns false
5578          * @type String
5579          */
5580         'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
5581         
5582         /**
5583          * The function used to validate alpha values
5584          * @param {String} value The value
5585          */
5586         'alpha' : function(v){
5587             return alpha.test(v);
5588         },
5589         /**
5590          * The error text to display when the alpha validation function returns false
5591          * @type String
5592          */
5593         'alphaText' : 'This field should only contain letters and _',
5594         /**
5595          * The keystroke filter mask to be applied on alpha input
5596          * @type RegExp
5597          */
5598         'alphaMask' : /[a-z_]/i,
5599
5600         /**
5601          * The function used to validate alphanumeric values
5602          * @param {String} value The value
5603          */
5604         'alphanum' : function(v){
5605             return alphanum.test(v);
5606         },
5607         /**
5608          * The error text to display when the alphanumeric validation function returns false
5609          * @type String
5610          */
5611         'alphanumText' : 'This field should only contain letters, numbers and _',
5612         /**
5613          * The keystroke filter mask to be applied on alphanumeric input
5614          * @type RegExp
5615          */
5616         'alphanumMask' : /[a-z0-9_]/i
5617     };
5618 }();/*
5619  * - LGPL
5620  *
5621  * Input
5622  * 
5623  */
5624
5625 /**
5626  * @class Roo.bootstrap.Input
5627  * @extends Roo.bootstrap.Component
5628  * Bootstrap Input class
5629  * @cfg {Boolean} disabled is it disabled
5630  * @cfg {String} fieldLabel - the label associated
5631  * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
5632  * @cfg {String} name name of the input
5633  * @cfg {string} fieldLabel - the label associated
5634  * @cfg {string}  inputType - input / file submit ...
5635  * @cfg {string} placeholder - placeholder to put in text.
5636  * @cfg {string}  before - input group add on before
5637  * @cfg {string} after - input group add on after
5638  * @cfg {string} size - (lg|sm) or leave empty..
5639  * @cfg {Number} xs colspan out of 12 for mobile-sized screens
5640  * @cfg {Number} sm colspan out of 12 for tablet-sized screens
5641  * @cfg {Number} md colspan out of 12 for computer-sized screens
5642  * @cfg {Number} lg colspan out of 12 for large computer-sized screens
5643  * @cfg {string} value default value of the input
5644  * @cfg {Number} labelWidth set the width of label (0-12)
5645  * @cfg {String} labelAlign (top|left)
5646  * @cfg {Boolean} readOnly Specifies that the field should be read-only
5647  * 
5648  * 
5649  * @constructor
5650  * Create a new Input
5651  * @param {Object} config The config object
5652  */
5653
5654 Roo.bootstrap.Input = function(config){
5655     Roo.bootstrap.Input.superclass.constructor.call(this, config);
5656    
5657         this.addEvents({
5658             /**
5659              * @event focus
5660              * Fires when this field receives input focus.
5661              * @param {Roo.form.Field} this
5662              */
5663             focus : true,
5664             /**
5665              * @event blur
5666              * Fires when this field loses input focus.
5667              * @param {Roo.form.Field} this
5668              */
5669             blur : true,
5670             /**
5671              * @event specialkey
5672              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
5673              * {@link Roo.EventObject#getKey} to determine which key was pressed.
5674              * @param {Roo.form.Field} this
5675              * @param {Roo.EventObject} e The event object
5676              */
5677             specialkey : true,
5678             /**
5679              * @event change
5680              * Fires just before the field blurs if the field value has changed.
5681              * @param {Roo.form.Field} this
5682              * @param {Mixed} newValue The new value
5683              * @param {Mixed} oldValue The original value
5684              */
5685             change : true,
5686             /**
5687              * @event invalid
5688              * Fires after the field has been marked as invalid.
5689              * @param {Roo.form.Field} this
5690              * @param {String} msg The validation message
5691              */
5692             invalid : true,
5693             /**
5694              * @event valid
5695              * Fires after the field has been validated with no errors.
5696              * @param {Roo.form.Field} this
5697              */
5698             valid : true,
5699              /**
5700              * @event keyup
5701              * Fires after the key up
5702              * @param {Roo.form.Field} this
5703              * @param {Roo.EventObject}  e The event Object
5704              */
5705             keyup : true
5706         });
5707 };
5708
5709 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
5710      /**
5711      * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
5712       automatic validation (defaults to "keyup").
5713      */
5714     validationEvent : "keyup",
5715      /**
5716      * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
5717      */
5718     validateOnBlur : true,
5719     /**
5720      * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
5721      */
5722     validationDelay : 250,
5723      /**
5724      * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
5725      */
5726     focusClass : "x-form-focus",  // not needed???
5727     
5728        
5729     /**
5730      * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
5731      */
5732     invalidClass : "has-error",
5733     
5734     /**
5735      * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
5736      */
5737     selectOnFocus : false,
5738     
5739      /**
5740      * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
5741      */
5742     maskRe : null,
5743        /**
5744      * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
5745      */
5746     vtype : null,
5747     
5748       /**
5749      * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
5750      */
5751     disableKeyFilter : false,
5752     
5753        /**
5754      * @cfg {Boolean} disabled True to disable the field (defaults to false).
5755      */
5756     disabled : false,
5757      /**
5758      * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
5759      */
5760     allowBlank : true,
5761     /**
5762      * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
5763      */
5764     blankText : "This field is required",
5765     
5766      /**
5767      * @cfg {Number} minLength Minimum input field length required (defaults to 0)
5768      */
5769     minLength : 0,
5770     /**
5771      * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
5772      */
5773     maxLength : Number.MAX_VALUE,
5774     /**
5775      * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
5776      */
5777     minLengthText : "The minimum length for this field is {0}",
5778     /**
5779      * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
5780      */
5781     maxLengthText : "The maximum length for this field is {0}",
5782   
5783     
5784     /**
5785      * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
5786      * If available, this function will be called only after the basic validators all return true, and will be passed the
5787      * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
5788      */
5789     validator : null,
5790     /**
5791      * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
5792      * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
5793      * current field value.  If the test fails, the field will be marked invalid using {@link #regexText}.
5794      */
5795     regex : null,
5796     /**
5797      * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
5798      */
5799     regexText : "",
5800     
5801     
5802     
5803     fieldLabel : '',
5804     inputType : 'text',
5805     
5806     name : false,
5807     placeholder: false,
5808     before : false,
5809     after : false,
5810     size : false,
5811     // private
5812     hasFocus : false,
5813     preventMark: false,
5814     isFormField : true,
5815     value : '',
5816     labelWidth : 2,
5817     labelAlign : false,
5818     readOnly : false,
5819     
5820     parentLabelAlign : function()
5821     {
5822         var parent = this;
5823         while (parent.parent()) {
5824             parent = parent.parent();
5825             if (typeof(parent.labelAlign) !='undefined') {
5826                 return parent.labelAlign;
5827             }
5828         }
5829         return 'left';
5830         
5831     },
5832     
5833     getAutoCreate : function(){
5834         
5835         var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign;
5836         
5837         var id = Roo.id();
5838         
5839         var cfg = {};
5840         
5841         if(this.inputType != 'hidden'){
5842             cfg.cls = 'form-group' //input-group
5843         }
5844         
5845         var input =  {
5846             tag: 'input',
5847             id : id,
5848             type : this.inputType,
5849             value : this.value,
5850             cls : 'form-control',
5851             placeholder : this.placeholder || ''
5852             
5853         };
5854         
5855         if(this.maxLength && this.maxLength != Number.MAX_VALUE){
5856             input.maxLength = this.maxLength;
5857         }
5858         
5859         if (this.disabled) {
5860             input.disabled=true;
5861         }
5862         
5863         if (this.readOnly) {
5864             input.readonly=true;
5865         }
5866         
5867         if (this.name) {
5868             input.name = this.name;
5869         }
5870         if (this.size) {
5871             input.cls += ' input-' + this.size;
5872         }
5873         var settings=this;
5874         ['xs','sm','md','lg'].map(function(size){
5875             if (settings[size]) {
5876                 cfg.cls += ' col-' + size + '-' + settings[size];
5877             }
5878         });
5879         
5880         var inputblock = input;
5881         
5882         if (this.before || this.after) {
5883             
5884             inputblock = {
5885                 cls : 'input-group',
5886                 cn :  [] 
5887             };
5888             if (this.before && typeof(this.before) == 'string') {
5889                 
5890                 inputblock.cn.push({
5891                     tag :'span',
5892                     cls : 'roo-input-before input-group-addon',
5893                     html : this.before
5894                 });
5895             }
5896             if (this.before && typeof(this.before) == 'object') {
5897                 this.before = Roo.factory(this.before);
5898                 Roo.log(this.before);
5899                 inputblock.cn.push({
5900                     tag :'span',
5901                     cls : 'roo-input-before input-group-' +
5902                         (this.before.xtype == 'Button' ? 'btn' : 'addon'), //?? what about checkboxes - that looks like a bit of a hack thought? 
5903                 });
5904             }
5905             
5906             inputblock.cn.push(input);
5907             
5908             if (this.after && typeof(this.after) == 'string') {
5909                 inputblock.cn.push({
5910                     tag :'span',
5911                     cls : 'roo-input-after input-group-addon',
5912                     html : this.after
5913                 });
5914             }
5915             if (this.after && typeof(this.after) == 'object') {
5916                 this.after = Roo.factory(this.after);
5917                 Roo.log(this.after);
5918                 inputblock.cn.push({
5919                     tag :'span',
5920                     cls : 'roo-input-after input-group-' +
5921                         (this.before.xtype == 'Button' ? 'btn' : 'addon'), //?? what about checkboxes - that looks like a bit of a hack thought? 
5922                 });
5923             }
5924         };
5925         
5926         if (align ==='left' && this.fieldLabel.length) {
5927                 Roo.log("left and has label");
5928                 cfg.cn = [
5929                     
5930                     {
5931                         tag: 'label',
5932                         'for' :  id,
5933                         cls : 'control-label col-sm-' + this.labelWidth,
5934                         html : this.fieldLabel
5935                         
5936                     },
5937                     {
5938                         cls : "col-sm-" + (12 - this.labelWidth), 
5939                         cn: [
5940                             inputblock
5941                         ]
5942                     }
5943                     
5944                 ];
5945         } else if ( this.fieldLabel.length) {
5946                 Roo.log(" label");
5947                  cfg.cn = [
5948                    
5949                     {
5950                         tag: 'label',
5951                         //cls : 'input-group-addon',
5952                         html : this.fieldLabel
5953                         
5954                     },
5955                     
5956                     inputblock
5957                     
5958                 ];
5959
5960         } else {
5961             
5962                 Roo.log(" no label && no align");
5963                 cfg.cn = [
5964                     
5965                         inputblock
5966                     
5967                 ];
5968                 
5969                 
5970         };
5971         Roo.log('input-parentType: ' + this.parentType);
5972         
5973         if (this.parentType === 'Navbar' &&  this.parent().bar) {
5974            cfg.cls += ' navbar-form';
5975            Roo.log(cfg);
5976         }
5977         
5978         return cfg;
5979         
5980     },
5981     /**
5982      * return the real input element.
5983      */
5984     inputEl: function ()
5985     {
5986         return this.el.select('input.form-control',true).first();
5987     },
5988     setDisabled : function(v)
5989     {
5990         var i  = this.inputEl().dom;
5991         if (!v) {
5992             i.removeAttribute('disabled');
5993             return;
5994             
5995         }
5996         i.setAttribute('disabled','true');
5997     },
5998     initEvents : function()
5999     {
6000         
6001         this.inputEl().on("keydown" , this.fireKey,  this);
6002         this.inputEl().on("focus", this.onFocus,  this);
6003         this.inputEl().on("blur", this.onBlur,  this);
6004         
6005         this.inputEl().relayEvent('keyup', this);
6006
6007         // reference to original value for reset
6008         this.originalValue = this.getValue();
6009         //Roo.form.TextField.superclass.initEvents.call(this);
6010         if(this.validationEvent == 'keyup'){
6011             this.validationTask = new Roo.util.DelayedTask(this.validate, this);
6012             this.inputEl().on('keyup', this.filterValidation, this);
6013         }
6014         else if(this.validationEvent !== false){
6015             this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
6016         }
6017         
6018         if(this.selectOnFocus){
6019             this.on("focus", this.preFocus, this);
6020             
6021         }
6022         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
6023             this.inputEl().on("keypress", this.filterKeys, this);
6024         }
6025        /* if(this.grow){
6026             this.el.on("keyup", this.onKeyUp,  this, {buffer:50});
6027             this.el.on("click", this.autoSize,  this);
6028         }
6029         */
6030         if(this.inputEl().is('input[type=password]') && Roo.isSafari){
6031             this.inputEl().on('keydown', this.SafariOnKeyDown, this);
6032         }
6033         
6034         if (typeof(this.before) == 'object') {
6035             this.before.render(this.el.select('.roo-input-before',true).first());
6036         }
6037         if (typeof(this.after) == 'object') {
6038             this.after.render(this.el.select('.roo-input-after',true).first());
6039         }
6040         
6041         
6042     },
6043     filterValidation : function(e){
6044         if(!e.isNavKeyPress()){
6045             this.validationTask.delay(this.validationDelay);
6046         }
6047     },
6048      /**
6049      * Validates the field value
6050      * @return {Boolean} True if the value is valid, else false
6051      */
6052     validate : function(){
6053         //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
6054         if(this.disabled || this.validateValue(this.getRawValue())){
6055             this.clearInvalid();
6056             return true;
6057         }
6058         return false;
6059     },
6060     
6061     
6062     /**
6063      * Validates a value according to the field's validation rules and marks the field as invalid
6064      * if the validation fails
6065      * @param {Mixed} value The value to validate
6066      * @return {Boolean} True if the value is valid, else false
6067      */
6068     validateValue : function(value){
6069         if(value.length < 1)  { // if it's blank
6070              if(this.allowBlank){
6071                 this.clearInvalid();
6072                 return true;
6073              }else{
6074                 this.markInvalid(this.blankText);
6075                 return false;
6076              }
6077         }
6078         if(value.length < this.minLength){
6079             this.markInvalid(String.format(this.minLengthText, this.minLength));
6080             return false;
6081         }
6082         if(value.length > this.maxLength){
6083             this.markInvalid(String.format(this.maxLengthText, this.maxLength));
6084             return false;
6085         }
6086         if(this.vtype){
6087             var vt = Roo.form.VTypes;
6088             if(!vt[this.vtype](value, this)){
6089                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
6090                 return false;
6091             }
6092         }
6093         if(typeof this.validator == "function"){
6094             var msg = this.validator(value);
6095             if(msg !== true){
6096                 this.markInvalid(msg);
6097                 return false;
6098             }
6099         }
6100         if(this.regex && !this.regex.test(value)){
6101             this.markInvalid(this.regexText);
6102             return false;
6103         }
6104         return true;
6105     },
6106
6107     
6108     
6109      // private
6110     fireKey : function(e){
6111         //Roo.log('field ' + e.getKey());
6112         if(e.isNavKeyPress()){
6113             this.fireEvent("specialkey", this, e);
6114         }
6115     },
6116     focus : function (selectText){
6117         if(this.rendered){
6118             this.inputEl().focus();
6119             if(selectText === true){
6120                 this.inputEl().dom.select();
6121             }
6122         }
6123         return this;
6124     } ,
6125     
6126     onFocus : function(){
6127         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
6128            // this.el.addClass(this.focusClass);
6129         }
6130         if(!this.hasFocus){
6131             this.hasFocus = true;
6132             this.startValue = this.getValue();
6133             this.fireEvent("focus", this);
6134         }
6135     },
6136     
6137     beforeBlur : Roo.emptyFn,
6138
6139     
6140     // private
6141     onBlur : function(){
6142         this.beforeBlur();
6143         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
6144             //this.el.removeClass(this.focusClass);
6145         }
6146         this.hasFocus = false;
6147         if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
6148             this.validate();
6149         }
6150         var v = this.getValue();
6151         if(String(v) !== String(this.startValue)){
6152             this.fireEvent('change', this, v, this.startValue);
6153         }
6154         this.fireEvent("blur", this);
6155     },
6156     
6157     /**
6158      * Resets the current field value to the originally loaded value and clears any validation messages
6159      */
6160     reset : function(){
6161         this.setValue(this.originalValue);
6162         this.clearInvalid();
6163     },
6164      /**
6165      * Returns the name of the field
6166      * @return {Mixed} name The name field
6167      */
6168     getName: function(){
6169         return this.name;
6170     },
6171      /**
6172      * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
6173      * @return {Mixed} value The field value
6174      */
6175     getValue : function(){
6176         return this.inputEl().getValue();
6177     },
6178     /**
6179      * Returns the raw data value which may or may not be a valid, defined value.  To return a normalized value see {@link #getValue}.
6180      * @return {Mixed} value The field value
6181      */
6182     getRawValue : function(){
6183         var v = this.inputEl().getValue();
6184         
6185         return v;
6186     },
6187     
6188     /**
6189      * Sets the underlying DOM field's value directly, bypassing validation.  To set the value with validation see {@link #setValue}.
6190      * @param {Mixed} value The value to set
6191      */
6192     setRawValue : function(v){
6193         return this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
6194     },
6195     
6196     selectText : function(start, end){
6197         var v = this.getRawValue();
6198         if(v.length > 0){
6199             start = start === undefined ? 0 : start;
6200             end = end === undefined ? v.length : end;
6201             var d = this.inputEl().dom;
6202             if(d.setSelectionRange){
6203                 d.setSelectionRange(start, end);
6204             }else if(d.createTextRange){
6205                 var range = d.createTextRange();
6206                 range.moveStart("character", start);
6207                 range.moveEnd("character", v.length-end);
6208                 range.select();
6209             }
6210         }
6211     },
6212     
6213     /**
6214      * Sets a data value into the field and validates it.  To set the value directly without validation see {@link #setRawValue}.
6215      * @param {Mixed} value The value to set
6216      */
6217     setValue : function(v){
6218         this.value = v;
6219         if(this.rendered){
6220             this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
6221             this.validate();
6222         }
6223     },
6224     
6225     /*
6226     processValue : function(value){
6227         if(this.stripCharsRe){
6228             var newValue = value.replace(this.stripCharsRe, '');
6229             if(newValue !== value){
6230                 this.setRawValue(newValue);
6231                 return newValue;
6232             }
6233         }
6234         return value;
6235     },
6236   */
6237     preFocus : function(){
6238         
6239         if(this.selectOnFocus){
6240             this.inputEl().dom.select();
6241         }
6242     },
6243     filterKeys : function(e){
6244         var k = e.getKey();
6245         if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
6246             return;
6247         }
6248         var c = e.getCharCode(), cc = String.fromCharCode(c);
6249         if(Roo.isIE && (e.isSpecialKey() || !cc)){
6250             return;
6251         }
6252         if(!this.maskRe.test(cc)){
6253             e.stopEvent();
6254         }
6255     },
6256      /**
6257      * Clear any invalid styles/messages for this field
6258      */
6259     clearInvalid : function(){
6260         
6261         if(!this.el || this.preventMark){ // not rendered
6262             return;
6263         }
6264         this.el.removeClass(this.invalidClass);
6265         /*
6266         switch(this.msgTarget){
6267             case 'qtip':
6268                 this.el.dom.qtip = '';
6269                 break;
6270             case 'title':
6271                 this.el.dom.title = '';
6272                 break;
6273             case 'under':
6274                 if(this.errorEl){
6275                     Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
6276                 }
6277                 break;
6278             case 'side':
6279                 if(this.errorIcon){
6280                     this.errorIcon.dom.qtip = '';
6281                     this.errorIcon.hide();
6282                     this.un('resize', this.alignErrorIcon, this);
6283                 }
6284                 break;
6285             default:
6286                 var t = Roo.getDom(this.msgTarget);
6287                 t.innerHTML = '';
6288                 t.style.display = 'none';
6289                 break;
6290         }
6291         */
6292         this.fireEvent('valid', this);
6293     },
6294      /**
6295      * Mark this field as invalid
6296      * @param {String} msg The validation message
6297      */
6298     markInvalid : function(msg){
6299         if(!this.el  || this.preventMark){ // not rendered
6300             return;
6301         }
6302         this.el.addClass(this.invalidClass);
6303         /*
6304         msg = msg || this.invalidText;
6305         switch(this.msgTarget){
6306             case 'qtip':
6307                 this.el.dom.qtip = msg;
6308                 this.el.dom.qclass = 'x-form-invalid-tip';
6309                 if(Roo.QuickTips){ // fix for floating editors interacting with DND
6310                     Roo.QuickTips.enable();
6311                 }
6312                 break;
6313             case 'title':
6314                 this.el.dom.title = msg;
6315                 break;
6316             case 'under':
6317                 if(!this.errorEl){
6318                     var elp = this.el.findParent('.x-form-element', 5, true);
6319                     this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
6320                     this.errorEl.setWidth(elp.getWidth(true)-20);
6321                 }
6322                 this.errorEl.update(msg);
6323                 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
6324                 break;
6325             case 'side':
6326                 if(!this.errorIcon){
6327                     var elp = this.el.findParent('.x-form-element', 5, true);
6328                     this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
6329                 }
6330                 this.alignErrorIcon();
6331                 this.errorIcon.dom.qtip = msg;
6332                 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
6333                 this.errorIcon.show();
6334                 this.on('resize', this.alignErrorIcon, this);
6335                 break;
6336             default:
6337                 var t = Roo.getDom(this.msgTarget);
6338                 t.innerHTML = msg;
6339                 t.style.display = this.msgDisplay;
6340                 break;
6341         }
6342         */
6343         this.fireEvent('invalid', this, msg);
6344     },
6345     // private
6346     SafariOnKeyDown : function(event)
6347     {
6348         // this is a workaround for a password hang bug on chrome/ webkit.
6349         
6350         var isSelectAll = false;
6351         
6352         if(this.inputEl().dom.selectionEnd > 0){
6353             isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
6354         }
6355         if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
6356             event.preventDefault();
6357             this.setValue('');
6358             return;
6359         }
6360         
6361         if(isSelectAll){ // backspace and delete key
6362             
6363             event.preventDefault();
6364             // this is very hacky as keydown always get's upper case.
6365             //
6366             var cc = String.fromCharCode(event.getCharCode());
6367             this.setValue( event.shiftKey ?  cc : cc.toLowerCase());
6368             
6369         }
6370     },
6371     adjustWidth : function(tag, w){
6372         tag = tag.toLowerCase();
6373         if(typeof w == 'number' && Roo.isStrict && !Roo.isSafari){
6374             if(Roo.isIE && (tag == 'input' || tag == 'textarea')){
6375                 if(tag == 'input'){
6376                     return w + 2;
6377                 }
6378                 if(tag == 'textarea'){
6379                     return w-2;
6380                 }
6381             }else if(Roo.isOpera){
6382                 if(tag == 'input'){
6383                     return w + 2;
6384                 }
6385                 if(tag == 'textarea'){
6386                     return w-2;
6387                 }
6388             }
6389         }
6390         return w;
6391     }
6392     
6393 });
6394
6395