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