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  
17  * 
18  * @constructor
19  * Do not use directly - it does not do anything..
20  * @param {Object} config The config object
21  */
22
23
24
25 Roo.bootstrap.Component = function(config){
26     Roo.bootstrap.Component.superclass.constructor.call(this, config);
27 };
28
29 Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent,  {
30     
31     cls : false,
32     
33     style : false,
34     
35     autoCreate : false,
36     
37     initEvents : function() {  },
38     
39     xattr : false,
40     
41     parentId : false,
42     
43     parent: function() {
44         // returns the parent component..
45         return Roo.ComponentMgr.get(this.parentId)
46         
47         
48     },
49     
50     // private
51     onRender : function(ct, position)
52     {
53         Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
54         if(this.el){
55             
56             if (this.el.attr('xtype')) {
57                 this.el.dom.removeAttribute('xtype');
58                 this.initEvents();
59             }
60             
61             return;
62         }
63         
64          
65         
66         var cfg = Roo.apply({},  this.getAutoCreate());
67         cfg.id = Roo.id();
68         
69         // fill in the extra attributes 
70         if (this.xattr && typeof(this.xattr) =='object') {
71             for (var i in this.xattr) {
72                 cfg[i] = this.xattr[i];
73             }
74         }
75         
76         if (this.cls) {
77             cfg.cls += ' ' + this.cls;
78         }
79         if (this.style) { // fixme needs to support more complex style data.
80             cfg.style = this.style;
81         }
82         this.el = ct.createChild(cfg, position);
83         if(this.tabIndex !== undefined){
84             this.el.dom.setAttribute('tabIndex', this.tabIndex);
85         }
86         this.initEvents();
87         
88         
89     },
90     
91     getChildContainer : function()
92     {
93         return this.el;
94     },
95     
96     addxtype : function (tree, cntr) {
97         var cn = this;
98         cntr = typeof(cntr == 'undefined' ) ? 'getChildContainer' : cntr;
99         
100         // render the element if it's not BODY.
101         if (tree.xtype != 'Body') {
102             
103             cn = Roo.factory(tree);
104             
105             cn.parentType = this.xtype; //??
106             cn.parentId = this.id;
107             
108             // does the container contain child eleemnts with 'xtype' attributes.
109             // that match this xtype..
110             // note - when we render we create these as well..
111             // so we should check to see if body has xtype set.
112             if (Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body') {
113             
114                 var echild = Roo.get(this[cntr]()).child('*[xtype]');
115                 if (echild) {
116                     cn.el = echild;
117                     //echild.dom.removeAttribute('xtype');
118                 }
119             }
120             cn.render(this[cntr]());
121             // then add the element..
122         }
123         
124         
125         
126         
127         var nitems = [];
128         if (typeof (tree.menu) != 'undefined') {
129             tree.menu.parentType = cn.xtype;
130             tree.menu.triggerEl = cn.el;
131             nitems.push(cn.addxtype(Roo.apply({}, tree.menu)));
132             
133         }
134         if (typeof (tree.buttons) != 'undefined' && typeof(cn.getButtonContainer) == 'function') {
135             
136             for(var i =0;i < tree.buttons.length;i++) {
137                 nitems.push(cn.addxtype(Roo.apply({}, tree.buttons[i]), 'getButtonContainer'));
138             }
139             
140             
141         }
142         if (!tree.items || !tree.items.length) {
143             this.items = nitems;
144             return cn;
145         }
146         var items = tree.items;
147         delete tree.items;
148         
149         //Roo.log(items.length);
150             // add the items..
151         for(var i =0;i < items.length;i++) {
152             nitems.push(cn.addxtype(Roo.apply({}, items[i])));
153         }
154         
155         this.items = nitems;
156         
157         
158         return cn;
159     }
160     
161     
162     
163     
164 });
165
166  /*
167  * - LGPL
168  *
169  * page container.
170  * 
171  */ 
172 Roo.bootstrap.Body = function(config){
173     Roo.bootstrap.Body.superclass.constructor.call(this, config);
174     this.el = Roo.get(document.body);
175 };
176
177 Roo.extend(Roo.bootstrap.Body, Roo.bootstrap.Component,  {
178       
179         autoCreate : {
180         cls: 'container'
181     },
182     onRender : function(ct, position){
183         
184         
185         //this.el.addClass([this.fieldClass, this.cls]);
186         
187     }
188     
189     
190  
191    
192 });
193
194  /*
195  * - LGPL
196  *
197  * button group
198  * 
199  */
200
201
202 /**
203  * @class Roo.bootstrap.ButtonGroup
204  * @extends Roo.bootstrap.Component
205  * Bootstrap ButtonGroup class
206  * @cfg {String} size lg | sm | xs (default empty normal)
207  * @cfg {String} align vertical | justified  (default none)
208  * @cfg {String} direction up | down (default down)
209  * @cfg {Boolean} toolbar false | true
210  * @cfg {Boolean} btn true | false
211  * 
212  * 
213  * @constructor
214  * Create a new Input
215  * @param {Object} config The config object
216  */
217
218 Roo.bootstrap.ButtonGroup = function(config){
219     Roo.bootstrap.ButtonGroup.superclass.constructor.call(this, config);
220 };
221
222 Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component,  {
223     
224     size: '',
225     align: '',
226     direction: '',
227     toolbar: false,
228     btn: true,
229
230     getAutoCreate : function(){
231         var cfg = {
232             cls: 'btn-group',
233             html : null
234         }
235         
236         cfg.html = this.html || cfg.html;
237         
238         if (this.toolbar) {
239             cfg = {
240                 cls: 'btn-toolbar',
241                 html: null
242             }
243             
244             return cfg;
245         }
246         
247         if (['vertical','justified'].indexOf(this.align)!==-1) {
248             cfg.cls = 'btn-group-' + this.align;
249             
250             if (this.align == 'justified') {
251                 console.log(this.items);
252             }
253         }
254         
255         if (['lg','sm','xs'].indexOf(this.size)!==-1) {
256             cfg.cls += ' btn-group-' + this.size;
257         }
258         
259         if (this.direction == 'up') {
260             cfg.cls += ' dropup' ;
261         }
262         
263         return cfg;
264     }
265    
266 });
267
268  /*
269  * - LGPL
270  *
271  * button
272  * 
273  */
274
275 /**
276  * @class Roo.bootstrap.Button
277  * @extends Roo.bootstrap.Component
278  * Bootstrap Button class
279  * @cfg {String} html The button content
280  * @cfg {String} weight default (or empty) | primary | success | info | warning | danger
281  * @cfg {String} size empty | lg | sm | xs
282  * @cfg {String} tag empty | a | input | submit
283  * @cfg {String} href empty or href
284  * @cfg {Boolean} disabled false | true
285  * @cfg {Boolean} isClose false | true
286  * @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
287  * @cfg {String} badge text for badge
288  * @cfg {String} theme default (or empty) | glow
289  * @cfg {Boolean} inverse false | true
290  * @cfg {Boolean} toggle false | true
291  * @cfg {String} ontext text for on toggle state
292  * @cfg {String} offtext text for off toggle state
293  * @cfg {Boolean} defaulton true | false
294  * 
295  * @constructor
296  * Create a new button
297  * @param {Object} config The config object
298  */
299
300
301 Roo.bootstrap.Button = function(config){
302     Roo.bootstrap.Button.superclass.constructor.call(this, config);
303     this.addEvents({
304         // raw events
305         /**
306          * @event click
307          * The raw click event for the entire grid.
308          * @param {Roo.EventObject} e
309          */
310         "click" : true
311     });
312 };
313
314 Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
315     html: false,
316     active: false,
317     weight: '',
318     size: '',
319     tag: 'button',
320     href: '',
321     disabled: false,
322     isClose: false,
323     glyphicon: '',
324     badge: '',
325     theme: 'default',
326     inverse: false,
327     
328     toggle: false,
329     ontext: 'ON',
330     offtext: 'OFF',
331     defaulton: true,
332     
333     getAutoCreate : function(){
334         
335         var cfg = {
336             tag : 'button',
337             cls : 'roo-button',
338             html: 'hello'
339         };
340         
341         if (['a', 'button', 'input', 'submit'].indexOf(this.tag) < 0) {
342             throw "Invalid value for tag: " + this.tag + ". must be a, button, input or submit.";
343             this.tag = 'button';
344         } else {
345             cfg.tag = this.tag;
346         }
347         cfg.html = this.html || cfg.html;
348         
349         if (this.toggle===true) {
350             cfg={
351                 tag: 'div',
352                 cls: 'slider-frame roo-button',
353                 cn: [
354                     {
355                         tag: 'span',
356                         'data-on-text':'ON',
357                         'data-off-text':'OFF',
358                         cls: 'slider-button',
359                         html: this.offtext
360                     }
361                 ]
362             };
363             
364             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
365                 cfg.cls += ' '+this.weight;
366             }
367             
368             return cfg;
369         }
370         
371         if (this.isClose) {
372             cfg.cls += ' close';
373             
374             cfg["aria-hidden"] = true;
375             
376             cfg.html = "&times;";
377             
378             return cfg;
379         }
380         
381          
382         if (this.theme==='default') {
383             cfg.cls = 'btn roo-button';
384             
385             if (this.parentType != 'Navbar') {
386                 this.weight = this.weight.length ?  this.weight : 'default';
387             }
388             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
389                 
390                 cfg.cls += ' btn-' + this.weight;
391             }
392         } else if (this.theme==='glow') {
393             
394             cfg.tag = 'a';
395             cfg.cls = 'btn-glow roo-button';
396             
397             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
398                 
399                 cfg.cls += ' ' + this.weight;
400             }
401         }
402    
403         
404         if (this.inverse) {
405             this.cls += ' inverse';
406         }
407         
408         
409         if (this.active) {
410             cfg.cls += ' active';
411         }
412         
413         cfg.cls += this.size.length ? (' btn-' + this.size) : '';
414          
415         //gsRoo.log(this.parentType);
416         if (this.parentType === 'Navbar') {
417             cfg.tag = 'li';
418             
419             cfg.cls = '';
420             cfg.cn =  [{
421                 tag : 'a',
422                 cls : 'roo-button',
423                 html : this.html,
424                 href : this.href || '#'
425             }];
426             if (this.menu) {
427                 cfg.cn[0].html = this.html  + ' <span class="caret"></span>';
428                 cfg.cls += ' dropdown';
429             }   
430             
431             delete cfg.html;
432             
433         } else if (this.menu) {
434             cfg.tag = 'a';
435             cfg.cls += ' dropdown test';
436         }
437         
438         
439         
440         if (this.disabled) {
441             cfg.disabled = 'disabled';
442         }
443         //????
444         if (this.items) {
445             Roo.log('changing to ul' );
446             cfg.tag = 'ul';
447             this.glyphicon = 'caret';
448         }
449         
450         if (this.glyphicon) {
451             cfg.html = ' ' + cfg.html;
452             
453             cfg.cn = [
454                 {
455                     tag: 'span',
456                     cls: 'glyphicon glyphicon-' + this.glyphicon
457                 }
458             ];
459         }
460         
461         if (this.badge) {
462             cfg.html += ' ';
463             
464             cfg.tag = 'a';
465             
466             cfg.cls='btn roo-button';
467             
468             cfg.href=this.href;
469             
470             cfg.cn = [
471                 cfg.html,
472                 {
473                     tag: 'span',
474                     cls: 'badge',
475                     html: this.badge
476                 }
477             ];
478             
479             cfg.html='';
480         }
481         
482         if (cfg.tag !== 'a' && this.href !== '') {
483             throw "Tag must be a to set href.";
484         } else if (this.href.length > 0) {
485             cfg.href = this.href;
486         }
487         
488         return cfg;
489     },
490     initEvents: function() {
491        // Roo.log('init events?');
492        // Roo.log(this.el.dom);
493        if (this.el.hasClass('roo-button')) {
494             this.el.on('click', this.onClick, this);
495        } else {
496             this.el.select('.roo-button').on('click', this.onClick, this);
497        }
498        
499        
500         
501     },
502     onClick : function(e)
503     {
504         Roo.log('button on click ');
505         e.preventDefault();
506         this.fireEvent('click', this, e);
507     }
508     
509     
510 });
511
512  /*
513  * - LGPL
514  *
515  * column
516  * 
517  */
518
519 /**
520  * @class Roo.bootstrap.Column
521  * @extends Roo.bootstrap.Component
522  * Bootstrap Column class
523  * @cfg {Number} xs colspan out of 12 for mobile-sized screens
524  * @cfg {Number} sm colspan out of 12 for tablet-sized screens
525  * @cfg {Number} md colspan out of 12 for computer-sized screens
526  * @cfg {Number} lg colspan out of 12 for large computer-sized screens
527  * @cfg {String} html content of column.
528  * 
529  * @constructor
530  * Create a new Column
531  * @param {Object} config The config object
532  */
533
534 Roo.bootstrap.Column = function(config){
535     Roo.bootstrap.Column.superclass.constructor.call(this, config);
536 };
537
538 Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
539     
540     xs: null,
541     sm: null,
542     md: null,
543     lg: null,
544     html: '',
545     offset: 0,
546     
547     getAutoCreate : function(){
548         var cfg = Roo.apply({}, Roo.bootstrap.Column.superclass.getAutoCreate.call(this));
549         
550         cfg = {
551             tag: 'div',
552             cls: 'column'
553         };
554         
555         var settings=this;
556         ['xs','sm','md','lg'].map(function(size){
557             if (settings[size]) {
558                 cfg.cls += ' col-' + size + '-' + settings[size];
559             }
560         });
561         if (this.html.length) {
562             cfg.html = this.html;
563         }
564         
565         return cfg;
566     }
567    
568 });
569
570  
571
572  /*
573  * - LGPL
574  *
575  * page container.
576  * 
577  */
578
579
580 /**
581  * @class Roo.bootstrap.Container
582  * @extends Roo.bootstrap.Component
583  * Bootstrap Container class
584  * @cfg {Boolean} jumbotron is it a jumbotron element
585  * @cfg {String} html content of element
586  * @cfg {String} well (lg|sm|md) a well, large, small or medium.
587  * @cfg {String} panel (primary|success|info|warning|danger) render as a panel.
588  * @cfg {String} header content of header (for panel)
589  * @cfg {String} footer content of footer (for panel)
590  * @cfg {String} sticky (footer|wrap|push) block to use as footer or body- needs css-bootstrap/sticky-footer.css
591  *     
592  * @constructor
593  * Create a new Container
594  * @param {Object} config The config object
595  */
596
597 Roo.bootstrap.Container = function(config){
598     Roo.bootstrap.Container.superclass.constructor.call(this, config);
599 };
600
601 Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
602     
603     jumbotron : false,
604     well: '',
605     panel : '',
606     header: '',
607     footer : '',
608     sticky: '',
609   
610      
611     getChildContainer : function() {
612         if (this.panel.length) {
613             return this.el.select('.panel-body',true).first();
614         }
615         
616         return this.el;
617     },
618     
619     
620     getAutoCreate : function(){
621         
622         var cfg = {
623             html : '',
624             cls : ''
625         };
626         if (this.jumbotron) {
627             cfg.cls = 'jumbotron';
628         }
629         if (this.cls) {
630             cfg.cls = this.cls + '';
631         }
632         
633         if (this.sticky.length) {
634             var bd = Roo.get(document.body);
635             if (!bd.hasClass('bootstrap-sticky')) {
636                 bd.addClass('bootstrap-sticky');
637                 Roo.select('html',true).setStyle('height', '100%');
638             }
639              
640             cfg.cls += 'bootstrap-sticky-' + this.sticky;
641         }
642         
643         
644         if (this.well.length) {
645             switch (this.well) {
646                 case 'lg':
647                 case 'sm':
648                     cfg.cls +=' well well-' +this.well;
649                     break;
650                 default:
651                     cfg.cls +=' well';
652                     break;
653             }
654         }
655         
656         var body = cfg;
657         
658         if (this.panel.length) {
659             cfg.cls += 'panel panel-' + this.panel;
660             cfg.cn = [];
661             if (this.header.length) {
662                 cfg.cn.push({
663                     
664                     cls : 'panel-heading',
665                     cn : [{
666                         tag: 'h3',
667                         cls : 'panel-title',
668                         html : this.header
669                     }]
670                     
671                 });
672             }
673             body = false;
674             cfg.cn.push({
675                 cls : 'panel-body',
676                 html : this.html
677             });
678             
679             
680             if (this.footer.length) {
681                 cfg.cn.push({
682                     cls : 'panel-footer',
683                     html : this.footer
684                     
685                 });
686             }
687             
688         }
689         if (body) {
690             body.html = this.html || cfg.html;
691         }
692         if (!cfg.cls.length) {
693             cfg.cls =  'container';
694         }
695         
696         return cfg;
697     }
698    
699 });
700
701  /*
702  * - LGPL
703  *
704  * image
705  * 
706  */
707
708
709 /**
710  * @class Roo.bootstrap.Img
711  * @extends Roo.bootstrap.Component
712  * Bootstrap Img class
713  * @cfg {Boolean} imgResponsive false | true
714  * @cfg {String} border rounded | circle | thumbnail
715  * @cfg {String} src image source
716  * @cfg {String} alt image alternative text
717  * 
718  * @constructor
719  * Create a new Input
720  * @param {Object} config The config object
721  */
722
723 Roo.bootstrap.Img = function(config){
724     Roo.bootstrap.Img.superclass.constructor.call(this, config);
725 };
726
727 Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
728     
729     imgResponsive: true,
730     border: '',
731     src: '',
732
733     getAutoCreate : function(){
734         
735         cfg = {
736             tag: 'img',
737             cls: 'img-responsive',
738             html : null
739         }
740         
741         cfg.html = this.html || cfg.html;
742         
743         cfg.src = this.src || cfg.src;
744         
745         if (['rounded','circle','thumbnail'].indexOf(this.border)>-1) {
746             cfg.cls += ' img-' + this.border;
747         }
748         
749         if(this.alt){
750             cfg.alt = this.alt;
751         }
752         
753         return cfg;
754     }
755    
756 });
757
758  /*
759  * - LGPL
760  *
761  * header
762  * 
763  */
764
765 /**
766  * @class Roo.bootstrap.Header
767  * @extends Roo.bootstrap.Component
768  * Bootstrap Header class
769  * @cfg {String} html content of header
770  * @cfg {Number} level (1|2|3|4|5|6) default 1
771  * 
772  * @constructor
773  * Create a new Header
774  * @param {Object} config The config object
775  */
776
777
778 Roo.bootstrap.Header  = function(config){
779     Roo.bootstrap.Header.superclass.constructor.call(this, config);
780 };
781
782 Roo.extend(Roo.bootstrap.Header, Roo.bootstrap.Component,  {
783     
784     //href : false,
785     html : false,
786     level : 1,
787     
788     
789     
790     getAutoCreate : function(){
791         
792         var cfg = {
793             tag: 'h' + (1 *this.level),
794             html: this.html || 'fill in html'
795         } ;
796         
797         return cfg;
798     }
799    
800 });
801
802  
803
804  /*
805  * - LGPL
806  *
807  * menu
808  * 
809  */
810
811 /**
812  * @class Roo.bootstrap.Menu
813  * @extends Roo.bootstrap.Component
814  * Bootstrap Menu class - container for MenuItems
815  * @cfg {String} type type of menu
816  * 
817  * @constructor
818  * Create a new Menu
819  * @param {Object} config The config object
820  */
821
822
823 Roo.bootstrap.Menu = function(config){
824     Roo.bootstrap.Menu.superclass.constructor.call(this, config);
825 };
826
827 Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
828     
829    /// html : false,
830     //align : '',
831     triggerEl : false,
832     type: false,
833     
834     
835     getChildContainer : function() {
836         return this.el;  
837     },
838     
839     getAutoCreate : function(){
840          
841         //if (['right'].indexOf(this.align)!==-1) {
842         //    cfg.cn[1].cls += ' pull-right'
843         //}
844         var cfg = {
845             tag : 'ul',
846             cls : 'dropdown-menu' 
847             
848         }
849         
850         if (this.type==='submenu') {
851             cfg.cls='submenu active'
852         }
853         
854         return cfg;
855     },
856     initEvents : function() {
857        // Roo.log("ADD event");
858        // Roo.log(this.triggerEl.dom);
859         this.triggerEl.on('click', this.toggle, this);
860         this.triggerEl.addClass('dropdown-toggle');
861         
862     },
863     toggle  : function(e)
864     {
865         //Roo.log(e.getTarget());
866        // Roo.log(this.triggerEl.dom);
867         if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
868             return;
869         }
870         var isActive = this.triggerEl.hasClass('open');
871         // if disabled.. ingore
872         this.clearMenus(e);
873         //if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
874          // if mobile we use a backdrop because click events don't delegate
875         // $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
876         // }
877  
878        //var relatedTarget = { relatedTarget: this }
879        //$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
880  
881        //if (e.isDefaultPrevented()) return;
882         
883        this.triggerEl[isActive ? 'removeClass' : 'addClass']('open');
884        
885        //  .trigger('shown.bs.dropdown', relatedTarget)
886  
887        this.triggerEl.focus();
888        Roo.log(e);
889        e.preventDefault(); 
890         
891         
892     },
893     clearMenus : function()
894     {
895         //$(backdrop).remove()
896         Roo.select('.dropdown-toggle',true).each(function(aa) {
897             if (!aa.hasClass('open')) {
898                 return;
899             }
900             // triger close...
901             aa.removeClass('open');
902           //var parent = getParent($(this))
903           //var relatedTarget = { relatedTarget: this }
904           
905            //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
906           //if (e.isDefaultPrevented()) return
907            //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
908         })
909     }
910     
911    
912 });
913
914  
915
916  /*
917  * - LGPL
918  *
919  * menu item
920  * 
921  */
922
923
924 /**
925  * @class Roo.bootstrap.MenuItem
926  * @extends Roo.bootstrap.Component
927  * Bootstrap MenuItem class
928  * @cfg {String} html the menu label
929  * @cfg {String} href the link
930  * 
931  * 
932  * @constructor
933  * Create a new MenuItem
934  * @param {Object} config The config object
935  */
936
937
938 Roo.bootstrap.MenuItem = function(config){
939     Roo.bootstrap.MenuItem.superclass.constructor.call(this, config);
940 };
941
942 Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component,  {
943     
944     href : false,
945     html : false,
946     
947     getAutoCreate : function(){
948         var cfg= {
949             tag: 'li',
950             cn: [
951                 {
952                     tag : 'a',
953                     href : '#',
954                     html : 'Link'
955                 }
956             ]
957         };
958         
959         cfg.cn[0].href = this.href || cfg.cn[0].href ;
960         cfg.cn[0].html = this.html || cfg.cn[0].html ;
961         return cfg;
962     }
963    
964 });
965
966  
967
968  /*
969  * - LGPL
970  *
971  * menu separator
972  * 
973  */
974
975
976 /**
977  * @class Roo.bootstrap.MenuSeparator
978  * @extends Roo.bootstrap.Component
979  * Bootstrap MenuSeparator class
980  * 
981  * @constructor
982  * Create a new MenuItem
983  * @param {Object} config The config object
984  */
985
986
987 Roo.bootstrap.MenuSeparator = function(config){
988     Roo.bootstrap.MenuSeparator.superclass.constructor.call(this, config);
989 };
990
991 Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component,  {
992     
993     getAutoCreate : function(){
994         var cfg = {
995             cls: 'divider',
996             tag : 'li'
997         };
998         
999         return cfg;
1000     }
1001    
1002 });
1003
1004  
1005
1006  
1007 /*
1008 <div class="modal fade">
1009   <div class="modal-dialog">
1010     <div class="modal-content">
1011       <div class="modal-header">
1012         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1013         <h4 class="modal-title">Modal title</h4>
1014       </div>
1015       <div class="modal-body">
1016         <p>One fine body&hellip;</p>
1017       </div>
1018       <div class="modal-footer">
1019         <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
1020         <button type="button" class="btn btn-primary">Save changes</button>
1021       </div>
1022     </div><!-- /.modal-content -->
1023   </div><!-- /.modal-dialog -->
1024 </div><!-- /.modal -->
1025 */
1026 /*
1027  * - LGPL
1028  *
1029  * page contgainer.
1030  * 
1031  */
1032
1033 /**
1034  * @class Roo.bootstrap.Modal
1035  * @extends Roo.bootstrap.Component
1036  * Bootstrap Modal class
1037  * @cfg {String} title Title of dialog
1038  * @cfg {Array} buttons Array of buttons
1039  * 
1040  * @constructor
1041  * Create a new Modal Dialog
1042  * @param {Object} config The config object
1043  */
1044
1045 Roo.bootstrap.Modal = function(config){
1046     Roo.bootstrap.Modal.superclass.constructor.call(this, config);
1047 };
1048
1049 Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
1050     
1051     title : 'test dialog',
1052    
1053     buttons : false,
1054
1055     onRender : function(ct, position)
1056     {
1057         Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
1058         if(!this.el){
1059             var cfg = Roo.apply({},  this.getAutoCreate());
1060             cfg.id = Roo.id();
1061             //if(!cfg.name){
1062             //    cfg.name = typeof(this.name) == 'undefined' ? this.id : this.name;
1063             //}
1064             //if (!cfg.name.length) {
1065             //    delete cfg.name;
1066            // }
1067             if (this.cls) {
1068                 cfg.cls += ' ' + this.cls;
1069             }
1070             if (this.style) {
1071                 cfg.style = this.style;
1072             }
1073             this.el = Roo.get(document.body).createChild(cfg, position);
1074         }
1075         //var type = this.el.dom.type;
1076          
1077         if(this.tabIndex !== undefined){
1078             this.el.dom.setAttribute('tabIndex', this.tabIndex);
1079         }
1080         this.initEvents();
1081         //this.el.addClass([this.fieldClass, this.cls]);
1082         
1083     },
1084     getAutoCreate : function(){
1085         
1086         return {
1087             cls: "modal fade",
1088             cn : [
1089                 {
1090                     cls: "modal-dialog",
1091                     cn : [
1092                         {
1093                             cls : "modal-content",
1094                             cn : [
1095                                 {
1096                                     cls : 'modal-header',
1097                                     cn : [
1098                                         {
1099                                             tag: 'button',
1100                                             cls : 'close',
1101                                             html : '&times'
1102                                         },
1103                                         {
1104                                             tag: 'h4',
1105                                             cls : 'modal-title',
1106                                             html : this.title
1107                                         }
1108                                     
1109                                     ]
1110                                 },
1111                                 {
1112                                     cls : 'modal-body'
1113                                  
1114                                 },
1115                                  {
1116                                     cls : 'modal-footer'
1117                                     /*
1118                                     cn : [
1119                                         {
1120                                             tag: 'button',
1121                                             cls : 'btn btn-default',
1122                                             html : 'Close'
1123                                         },
1124                                         {
1125                                             tag: 'button',
1126                                             cls : 'btn btn-primary',
1127                                             html : 'Save'
1128                                         }
1129                                     
1130                                     ]
1131                                     */
1132                                 }
1133                                 
1134                                 
1135                             ]
1136                             
1137                         }
1138                     ]
1139                         
1140                 }
1141             ]
1142             
1143             
1144         };
1145           
1146     },
1147     getChildContainer : function() {
1148          
1149          return this.el.select('.modal-body',true).first();
1150         
1151     },
1152     getButtonContainer : function() {
1153          return this.el.select('.modal-footer',true).first();
1154         
1155     },
1156     initEvents : function()
1157     {
1158         this.el.select('.modal-header .close').on('click', this.hide, this);
1159     },
1160     show : function() {
1161         this.el.addClass('on');
1162         this.el.removeClass('fade');
1163         this.el.setStyle('display', 'block');
1164     },
1165     hide : function() {
1166         this.el.removeClass('on');
1167         this.el.addClass('fade');
1168         this.el.setStyle('display', 'none');
1169     }
1170 });
1171
1172  /*
1173  * - LGPL
1174  *
1175  * navbar
1176  * 
1177  */
1178
1179 /**
1180  * @class Roo.bootstrap.Navbar
1181  * @extends Roo.bootstrap.Component
1182  * Bootstrap Navbar class
1183  * @cfg {Boolean} sidebar has side bar
1184  * @cfg {Boolean} bar is a bar?
1185  * @cfg {String} position (fixed-top|fixed-bottom|static-top) position
1186  * @cfg {String} brand what is brand
1187  * @cfg {Boolean} inverse is inverted color
1188  * @cfg {String} type (nav | pills | tabs)
1189  * @cfg {Boolean} arrangement stacked | justified
1190  * @cfg {String} align (left | right) alignment
1191  *
1192  * 
1193  * @constructor
1194  * Create a new Navbar
1195  * @param {Object} config The config object
1196  */
1197
1198
1199 Roo.bootstrap.Navbar = function(config){
1200     Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
1201 };
1202
1203 Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
1204     
1205     sidebar: false,
1206     
1207     bar: false,
1208     brand: '',
1209     inverse: false,
1210     position: '',
1211     align : false,
1212     type: 'nav',
1213     arrangement: '',
1214     
1215     getAutoCreate : function(){
1216         var cfg = {
1217             cls : 'navbar'
1218         };
1219         
1220         if (this.sidebar === true) {
1221             cfg = {
1222                 tag: 'div',
1223                 cls: 'sidebar-nav'
1224             };
1225             return cfg;
1226         }
1227         
1228         if (this.bar === true) {
1229             cfg = {
1230                 tag: 'nav',
1231                 cls: 'navbar',
1232                 role: 'navigation',
1233                 cn: [
1234                     {
1235                         tag: 'div',
1236                         cls: 'navbar-header',
1237                         cn: [
1238                             {
1239                             tag: 'button',
1240                             type: 'button',
1241                             cls: 'navbar-toggle',
1242                             'data-toggle': 'collapse',
1243                             cn: [
1244                                 {
1245                                     tag: 'span',
1246                                     cls: 'sr-only',
1247                                     html: 'Toggle navigation'
1248                                 },
1249                                 {
1250                                     tag: 'span',
1251                                     cls: 'icon-bar'
1252                                 },
1253                                 {
1254                                     tag: 'span',
1255                                     cls: 'icon-bar'
1256                                 },
1257                                 {
1258                                     tag: 'span',
1259                                     cls: 'icon-bar'
1260                                 }
1261                             ]
1262                             }
1263                         ]
1264                     },
1265                     {
1266                     tag: 'div',
1267                     cls: 'collapse navbar-collapse'
1268                     }
1269                 ]
1270             };
1271             
1272             cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
1273             
1274             if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
1275             cfg.cls += ' navbar-' + this.position;
1276             cfg.tag = this.position  == 'fixed-bottom' ? 'footer' : 'header';
1277             }
1278             
1279             if (this.brand !== '') {
1280                 cfg.cn[0].cn.push({
1281                     tag: 'a',
1282                     href: '#',
1283                     cls: 'navbar-brand',
1284                     cn: [
1285                     this.brand
1286                     ]
1287                 });
1288             }
1289             
1290             return cfg;
1291         
1292         } else if (this.bar === false) {
1293             
1294         } else {
1295             Roo.log('Property \'bar\' in of Navbar must be either true or false')
1296         }
1297         
1298         cfg.cn = [
1299             {
1300                 cls: 'nav',
1301                 tag : 'ul'
1302             }
1303         ];
1304         
1305         if (['tabs','pills'].indexOf(this.type)!==-1) {
1306             cfg.cn[0].cls += ' nav-' + this.type
1307         } else {
1308             if (this.type!=='nav') {
1309             Roo.log('nav type must be nav/tabs/pills')
1310             }
1311             cfg.cn[0].cls += ' navbar-nav'
1312         }
1313         
1314         if (['stacked','justified'].indexOf(this.arrangement)!==-1) {
1315             cfg.cn[0].cls += ' nav-' + this.arrangement;
1316         }
1317         
1318         if (this.align === 'right') {
1319             cfg.cn[0].cls += ' navbar-right';
1320         }
1321         if (this.inverse) {
1322             cfg.cls += ' navbar-inverse';
1323             
1324         }
1325         
1326         
1327         return cfg;
1328     },
1329     
1330     getChildContainer : function() {
1331         if (this.bar === true) {
1332             return this.el.select('.collapse',true).first();
1333         }
1334         console.log(this);
1335         return this.el;
1336     }
1337    
1338 });
1339
1340  
1341
1342  /*
1343  * - LGPL
1344  *
1345  * nav group
1346  * 
1347  */
1348
1349 /**
1350  * @class Roo.bootstrap.NavGroup
1351  * @extends Roo.bootstrap.Component
1352  * Bootstrap NavGroup class
1353  * @cfg {String} align left | right
1354  * @cfg {Boolean} inverse false | true
1355  * 
1356  * @constructor
1357  * Create a new nav group
1358  * @param {Object} config The config object
1359  */
1360
1361 Roo.bootstrap.NavGroup = function(config){
1362     Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
1363 };
1364
1365 Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
1366     
1367     align: '',
1368     inverse: false,
1369     form: false,
1370     
1371     getAutoCreate : function(){
1372         var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
1373         
1374         cfg = {
1375             tag : 'ul',
1376             cls: 'nav navbar-nav' 
1377         }
1378         
1379         if (this.parent().sidebar === true) {
1380             cfg = {
1381                 tag: 'ul',
1382                 cls: 'dashboard-menu'
1383             }
1384             
1385             return cfg;
1386         }
1387         
1388         if (this.form === true) {
1389             cfg = {
1390                 tag: 'form',
1391                 cls: 'navbar-form'
1392             }
1393             
1394             if (this.align === 'right') {
1395                 cfg.cls += ' navbar-right';
1396             } else {
1397                 cfg.cls += ' navbar-left';
1398             }
1399         }
1400         
1401         
1402         if (this.align === 'right') {
1403             cfg.cls += ' navbar-right';
1404         }
1405         
1406         if (this.inverse) {
1407             cfg.cls += ' navbar-inverse';
1408             
1409         }
1410         
1411         
1412         return cfg;
1413     }
1414    
1415 });
1416
1417  
1418
1419  /*
1420  * - LGPL
1421  *
1422  * row
1423  * 
1424  */
1425 /**
1426  * @class Roo.bootstrap.Navbar.Button
1427  * @extends Roo.bootstrap.Component
1428  * Bootstrap Navbar.Button class
1429  * @cfg {String} href  link to
1430  * @cfg {String} html content of button
1431     
1432  * @constructor
1433  * Create a new Navbar Button
1434  * @param {Object} config The config object
1435  */
1436
1437
1438 Roo.bootstrap.Navbar.Button = function(config){
1439     Roo.bootstrap.Navbar.Button.superclass.constructor.call(this, config);
1440 };
1441
1442 Roo.extend(Roo.bootstrap.Navbar.Button, Roo.bootstrap.Component,  {
1443     
1444     href : false,
1445     html : false,
1446     
1447     autoCreate : {
1448         cls: 'btn',
1449         tag : 'button',
1450         html: 'hello'
1451     },
1452     
1453     getAutoCreate : function(){
1454         
1455         var cfg = {
1456             cls: 'btn',
1457             tag : 'button',
1458             html: 'hello',
1459             cn : []
1460             
1461         } ;
1462         cfg.cn.push({
1463             html : this.html || ''
1464             //href : this.
1465              //       )
1466         });
1467         cfg.cn.push({
1468             tag: 'span',
1469             cls : 'carat'
1470         });
1471         
1472         return cfg;
1473     }
1474    
1475 });
1476
1477  
1478
1479  /*
1480  * - LGPL
1481  *
1482  * row
1483  * 
1484  */
1485
1486 /**
1487  * @class Roo.bootstrap.Navbar.Item
1488  * @extends Roo.bootstrap.Component
1489  * Bootstrap Navbar.Button class
1490  * @cfg {String} href  link to
1491  * @cfg {String} html content of button
1492  * @cfg {String} badge text inside badge
1493  * @cfg {String} glyphicon name of glyphicon
1494   
1495  * @constructor
1496  * Create a new Navbar Button
1497  * @param {Object} config The config object
1498  */
1499 Roo.bootstrap.Navbar.Item = function(config){
1500     Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
1501 };
1502
1503 Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component,  {
1504     
1505     href: false,
1506     html: '',
1507     badge: '',
1508     icon: false,
1509     glyphicon: false,
1510     
1511     getAutoCreate : function(){
1512         
1513         var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
1514         
1515         if (this.parent().parent().sidebar === true) {
1516             cfg = {
1517                 tag: 'li',
1518                 cls: '',
1519                 cn: [
1520                     {
1521                         tag: 'p',
1522                         cls: ''
1523                     }
1524                 ]
1525             }
1526             
1527             if (this.html) {
1528                 cfg.cn[0].html = this.html;
1529             }
1530             
1531             if (this.active) {
1532                 this.cls += ' active';
1533             }
1534             
1535             if (this.menu) {
1536                 cfg.cn[0].cls += ' dropdown-toggle';
1537                 cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
1538             }
1539             
1540             if (this.href) {
1541                 cfg.cn[0].tag = 'a',
1542                 cfg.cn[0].href = this.href;
1543             }
1544             
1545             if (this.glyphicon) {
1546                 cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
1547             }
1548             
1549             return cfg;
1550         }
1551         
1552         cfg = {
1553             tag: 'li'
1554         }
1555         cfg.cn = [
1556             {
1557                 tag: 'p',
1558                 html: 'Text'
1559             }
1560         ];
1561         
1562         if (this.glyphicon) {
1563             if(cfg.html){cfg.html = ' ' + this.html};
1564             cfg.cn=[
1565                 {
1566                     tag: 'span',
1567                     cls: 'glyphicon glyphicon-' + this.glyphicon
1568                 }
1569             ];
1570         }
1571         
1572         cfg.cn[0].html = this.html || cfg.cn[0].html ;
1573         if (this.menu) {
1574             cfg.cn[0].tag='a';
1575             cfg.cn[0].href='#';
1576             cfg.cn[0].html += " <span class='caret'></span>";
1577         //}else if (!this.href) {
1578         //    cfg.cn[0].tag='p';
1579         //    cfg.cn[0].cls='navbar-text';
1580         } else {
1581             cfg.cn[0].tag='a';
1582             cfg.cn[0].href=this.href||'#';
1583             cfg.cn[0].html=this.html;
1584         }
1585         
1586         if (this.badge !== '') {
1587             
1588             cfg.cn[0].cn=[
1589                 cfg.cn[0].html + ' ',
1590                 {
1591                     tag: 'span',
1592                     cls: 'badge',
1593                     html: this.badge
1594                 }
1595             ];
1596             cfg.cn[0].html=''
1597         }
1598          
1599         
1600         return cfg;
1601     },
1602     initEvents: function() {
1603        // Roo.log('init events?');
1604        // Roo.log(this.el.dom);
1605         this.el.select('a',true).on('click',
1606                 function(e) {
1607                     this.fireEvent('click', this);
1608                 },
1609                 this
1610         );
1611     }
1612    
1613 });
1614  
1615
1616  /*
1617  * - LGPL
1618  *
1619  * row
1620  * 
1621  */
1622
1623 /**
1624  * @class Roo.bootstrap.Row
1625  * @extends Roo.bootstrap.Component
1626  * Bootstrap Row class (contains columns...)
1627  * 
1628  * @constructor
1629  * Create a new Row
1630  * @param {Object} config The config object
1631  */
1632
1633 Roo.bootstrap.Row = function(config){
1634     Roo.bootstrap.Row.superclass.constructor.call(this, config);
1635 };
1636
1637 Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component,  {
1638     
1639     autoCreate: {
1640         cls: 'row clearfix'
1641     }
1642     
1643     
1644 });
1645
1646  
1647
1648  /*
1649  * - LGPL
1650  *
1651  * element
1652  * 
1653  */
1654
1655 /**
1656  * @class Roo.bootstrap.Element
1657  * @extends Roo.bootstrap.Component
1658  * Bootstrap Element class
1659  * @cfg {String} html contents of the element
1660  * @cfg {String} tag tag of the element
1661  * @cfg {String} cls class of the element
1662  * 
1663  * @constructor
1664  * Create a new Element
1665  * @param {Object} config The config object
1666  */
1667
1668 Roo.bootstrap.Element = function(config){
1669     Roo.bootstrap.Element.superclass.constructor.call(this, config);
1670 };
1671
1672 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component,  {
1673     
1674     tag: 'div',
1675     cls: '',
1676     html: '',
1677     
1678     
1679     
1680     getAutoCreate : function(){
1681         var cfg = Roo.apply({}, Roo.bootstrap.Element.superclass.getAutoCreate.call(this));
1682         
1683         cfg = {
1684             tag: this.tag,
1685             cls: '',
1686             html: this.html
1687         }
1688         
1689         return cfg;
1690     }
1691    
1692 });
1693
1694  
1695
1696  /*
1697  * - LGPL
1698  *
1699  * pagination
1700  * 
1701  */
1702
1703 /**
1704  * @class Roo.bootstrap.Pagination
1705  * @extends Roo.bootstrap.Component
1706  * Bootstrap Pagination class
1707  * @cfg {String} size xs | sm | md | lg
1708  * @cfg {Boolean} inverse false | true
1709  * @cfg {Number} from pagination starting number
1710  * @cfg {Number} to pagination ending number
1711  * @cfg {String} align empty or left | right
1712  * @cfg {Number} active active page number
1713  * 
1714  * @constructor
1715  * Create a new Pagination
1716  * @param {Object} config The config object
1717  */
1718
1719 Roo.bootstrap.Pagination = function(config){
1720     Roo.bootstrap.Pagination.superclass.constructor.call(this, config);
1721 };
1722
1723 Roo.extend(Roo.bootstrap.Pagination, Roo.bootstrap.Component,  {
1724     
1725     cls: false,
1726     size: false,
1727     inverse: false,
1728     from: 1,
1729     to: 4,
1730     align: false,
1731     active: 1,
1732     
1733     getAutoCreate : function(){
1734         cfg = {
1735             tag: 'ul',
1736                 cls: 'pagination',
1737                 cn: []
1738         };
1739         if (this.inverse) {
1740             cfg.cls += ' inverse';
1741         }
1742         if (this.html) {
1743             cfg.html=this.html;
1744         }
1745         if (this.cls) {
1746             cfg.cls=this.cls;
1747         }
1748         cfg.cn[0]={
1749             tag: 'li',
1750             cn: [
1751                 {
1752                     tag: 'a',
1753                     href:'#',
1754                     html: '&laquo;'
1755                 }
1756             ]
1757         };
1758         var from=this.from>0?this.from:1;
1759         var to=this.to-from<=10?this.to:from+10;
1760         var active=this.active>=from&&this.active<=to?this.active:null;
1761         for (var i=from;i<=to;i++) {
1762             cfg.cn.push(
1763                 {
1764                     tag: 'li',
1765                     cls: active===i?'active':'',
1766                     cn: [
1767                         {
1768                             tag: 'a',
1769                             href: '#',
1770                             html: i
1771                         }
1772                     ]
1773                 }
1774             );
1775         }
1776         
1777         cfg.cn.push(
1778             {
1779                 tag: 'li',
1780                 cn: [
1781                     {
1782                        tag: 'a',
1783                        href: '#',
1784                        html: '&raquo;'
1785                     }
1786                 ]
1787             }
1788         );
1789         
1790         return cfg;
1791     }
1792    
1793 });
1794
1795  
1796
1797  /*
1798  * - LGPL
1799  *
1800  * slider
1801  * 
1802  */
1803
1804
1805 /**
1806  * @class Roo.bootstrap.Slider
1807  * @extends Roo.bootstrap.Component
1808  * Bootstrap Slider class
1809  *    
1810  * @constructor
1811  * Create a new Slider
1812  * @param {Object} config The config object
1813  */
1814
1815 Roo.bootstrap.Slider = function(config){
1816     Roo.bootstrap.Slider.superclass.constructor.call(this, config);
1817 };
1818
1819 Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component,  {
1820     
1821     getAutoCreate : function(){
1822         
1823         var cfg = {
1824             tag: 'div',
1825             cls: 'slider slider-sample1 vertical-handler ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all',
1826             cn: [
1827                 {
1828                     tag: 'a',
1829                     cls: 'ui-slider-handle ui-state-default ui-corner-all'
1830                 }
1831             ]
1832         }
1833         
1834         return cfg;
1835     }
1836    
1837 });
1838
1839  /*
1840  * - LGPL
1841  *
1842  * table
1843  * 
1844  */
1845
1846 /**
1847  * @class Roo.bootstrap.Table
1848  * @extends Roo.bootstrap.Component
1849  * Bootstrap Table class
1850  * 
1851  * @constructor
1852  * Create a new Table
1853  * @param {Object} config The config object
1854  */
1855
1856 Roo.bootstrap.Table = function(config){
1857     Roo.bootstrap.Table.superclass.constructor.call(this, config);
1858 };
1859
1860 Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
1861     
1862     html: false,
1863     cls: false,
1864     
1865     getAutoCreate : function(){
1866         var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
1867         
1868         cfg = {
1869             tag: 'table',
1870             cn: [
1871                 {
1872                     tag: 'tbody'
1873                 }
1874             ]
1875         }
1876         if (this.html) {
1877             cfg.html=this.html
1878         }
1879         if (this.cls) {
1880             cfg.cls=this.cls
1881         }
1882         
1883         return cfg;
1884     }
1885    
1886 });
1887
1888  
1889
1890  /*
1891  * - LGPL
1892  *
1893  * table cell
1894  * 
1895  */
1896
1897 /**
1898  * @class Roo.bootstrap.TableCell
1899  * @extends Roo.bootstrap.Component
1900  * Bootstrap TableCell class
1901  * 
1902  * @constructor
1903  * Create a new TableCell
1904  * @param {Object} config The config object
1905  */
1906
1907 Roo.bootstrap.TableCell = function(config){
1908     Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
1909 };
1910
1911 Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component,  {
1912     
1913     getAutoCreate : function(){
1914         var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
1915         
1916         cfg = {
1917             tag: 'td'
1918         }
1919         if (this.html) {
1920             cfg.html=this.html
1921         }
1922         if (this.cls) {
1923             cfg.cls=this.cls
1924         }
1925         
1926         return cfg;
1927     }
1928    
1929 });
1930
1931  
1932
1933  /*
1934  * - LGPL
1935  *
1936  * table row
1937  * 
1938  */
1939
1940 /**
1941  * @class Roo.bootstrap.TableRow
1942  * @extends Roo.bootstrap.Component
1943  * Bootstrap TableRow class
1944  * 
1945  * @constructor
1946  * Create a new TableRow
1947  * @param {Object} config The config object
1948  */
1949
1950 Roo.bootstrap.TableRow = function(config){
1951     Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
1952 };
1953
1954 Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component,  {
1955     
1956     getAutoCreate : function(){
1957         var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
1958         
1959         cfg = {
1960             tag: 'tr'
1961         }
1962         
1963         return cfg;
1964     }
1965    
1966 });
1967
1968  
1969
1970  /*
1971  * - LGPL
1972  *
1973  * form
1974  * 
1975  */
1976
1977 /**
1978  * @class Roo.bootstrap.Form
1979  * @extends Roo.bootstrap.Component
1980  * Bootstrap Form class
1981  * @cfg {String} method  GET | POST (default POST)
1982  * @cfg {String} labelAlign top | left (default top)
1983  * 
1984  * @constructor
1985  * Create a new Form
1986  * @param {Object} config The config object
1987  */
1988
1989
1990 Roo.bootstrap.Form = function(config){
1991     Roo.bootstrap.Form.superclass.constructor.call(this, config);
1992     this.addEvents({
1993         /**
1994          * @event clientvalidation
1995          * If the monitorValid config option is true, this event fires repetitively to notify of valid state
1996          * @param {Form} this
1997          * @param {Boolean} valid true if the form has passed client-side validation
1998          */
1999         clientvalidation: true,
2000         /**
2001          * @event beforeaction
2002          * Fires before any action is performed. Return false to cancel the action.
2003          * @param {Form} this
2004          * @param {Action} action The action to be performed
2005          */
2006         beforeaction: true,
2007         /**
2008          * @event actionfailed
2009          * Fires when an action fails.
2010          * @param {Form} this
2011          * @param {Action} action The action that failed
2012          */
2013         actionfailed : true,
2014         /**
2015          * @event actioncomplete
2016          * Fires when an action is completed.
2017          * @param {Form} this
2018          * @param {Action} action The action that completed
2019          */
2020         actioncomplete : true
2021     });
2022     
2023 };
2024
2025 Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
2026       
2027      /**
2028      * @cfg {String} method
2029      * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
2030      */
2031     method : 'POST',
2032     /**
2033      * @cfg {String} url
2034      * The URL to use for form actions if one isn't supplied in the action options.
2035      */
2036     /**
2037      * @cfg {Boolean} fileUpload
2038      * Set to true if this form is a file upload.
2039      */
2040      
2041     /**
2042      * @cfg {Object} baseParams
2043      * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
2044      */
2045       
2046     /**
2047      * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
2048      */
2049     timeout: 30,
2050
2051     // private
2052     activeAction : null,
2053  
2054     /**
2055      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2056      * element by passing it or its id or mask the form itself by passing in true.
2057      * @type Mixed
2058      */
2059     waitMsgTarget : false,
2060     
2061      
2062     
2063     /**
2064      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2065      * element by passing it or its id or mask the form itself by passing in true.
2066      * @type Mixed
2067      */
2068     
2069     getAutoCreate : function(){
2070         
2071         var cfg = {
2072             tag: 'form',
2073             method : this.method || 'POST',
2074             id : this.id || Roo.id(),
2075             cls : ''
2076         }
2077         
2078         if (this.labelAlign == 'left' ) {
2079             cfg.cls += ' form-horizontal';
2080         }
2081         return cfg;
2082     },
2083     initEvents : function()
2084     {
2085         this.el.on('submit', this.onSubmit, this);
2086         
2087         
2088     },
2089     // private
2090     onSubmit : function(e){
2091         e.stopEvent();
2092     },
2093     
2094      /**
2095      * Returns true if client-side validation on the form is successful.
2096      * @return Boolean
2097      */
2098     isValid : function(){
2099         var items = this.getItems();
2100         var valid = true;
2101         items.each(function(f){
2102            if(!f.validate()){
2103                valid = false;
2104                
2105            }
2106         });
2107         return valid;
2108     },
2109     /**
2110      * Returns true if any fields in this form have changed since their original load.
2111      * @return Boolean
2112      */
2113     isDirty : function(){
2114         var dirty = false;
2115         var items = this.getItems();
2116         items.each(function(f){
2117            if(f.isDirty()){
2118                dirty = true;
2119                return false;
2120            }
2121            return true;
2122         });
2123         return dirty;
2124     },
2125      /**
2126      * Performs a predefined action (submit or load) or custom actions you define on this form.
2127      * @param {String} actionName The name of the action type
2128      * @param {Object} options (optional) The options to pass to the action.  All of the config options listed
2129      * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
2130      * accept other config options):
2131      * <pre>
2132 Property          Type             Description
2133 ----------------  ---------------  ----------------------------------------------------------------------------------
2134 url               String           The url for the action (defaults to the form's url)
2135 method            String           The form method to use (defaults to the form's method, or POST if not defined)
2136 params            String/Object    The params to pass (defaults to the form's baseParams, or none if not defined)
2137 clientValidation  Boolean          Applies to submit only.  Pass true to call form.isValid() prior to posting to
2138                                    validate the form on the client (defaults to false)
2139      * </pre>
2140      * @return {BasicForm} this
2141      */
2142     doAction : function(action, options){
2143         if(typeof action == 'string'){
2144             action = new Roo.form.Action.ACTION_TYPES[action](this, options);
2145         }
2146         if(this.fireEvent('beforeaction', this, action) !== false){
2147             this.beforeAction(action);
2148             action.run.defer(100, action);
2149         }
2150         return this;
2151     },
2152     
2153     // private
2154     beforeAction : function(action){
2155         var o = action.options;
2156         
2157         // not really supported yet.. ??
2158         
2159         //if(this.waitMsgTarget === true){
2160             this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
2161         //}else if(this.waitMsgTarget){
2162         //    this.waitMsgTarget = Roo.get(this.waitMsgTarget);
2163         //    this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
2164         //}else {
2165         //    Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
2166        // }
2167          
2168     },
2169
2170     // private
2171     afterAction : function(action, success){
2172         this.activeAction = null;
2173         var o = action.options;
2174         
2175         //if(this.waitMsgTarget === true){
2176             this.el.unmask();
2177         //}else if(this.waitMsgTarget){
2178         //    this.waitMsgTarget.unmask();
2179         //}else{
2180         //    Roo.MessageBox.updateProgress(1);
2181         //    Roo.MessageBox.hide();
2182        // }
2183         // 
2184         if(success){
2185             if(o.reset){
2186                 this.reset();
2187             }
2188             Roo.callback(o.success, o.scope, [this, action]);
2189             this.fireEvent('actioncomplete', this, action);
2190             
2191         }else{
2192             
2193             // failure condition..
2194             // we have a scenario where updates need confirming.
2195             // eg. if a locking scenario exists..
2196             // we look for { errors : { needs_confirm : true }} in the response.
2197             if (
2198                 (typeof(action.result) != 'undefined')  &&
2199                 (typeof(action.result.errors) != 'undefined')  &&
2200                 (typeof(action.result.errors.needs_confirm) != 'undefined')
2201            ){
2202                 var _t = this;
2203                 Roo.log("not supported yet");
2204                  /*
2205                 
2206                 Roo.MessageBox.confirm(
2207                     "Change requires confirmation",
2208                     action.result.errorMsg,
2209                     function(r) {
2210                         if (r != 'yes') {
2211                             return;
2212                         }
2213                         _t.doAction('submit', { params :  { _submit_confirmed : 1 } }  );
2214                     }
2215                     
2216                 );
2217                 */
2218                 
2219                 
2220                 return;
2221             }
2222             
2223             Roo.callback(o.failure, o.scope, [this, action]);
2224             // show an error message if no failed handler is set..
2225             if (!this.hasListener('actionfailed')) {
2226                 Roo.log("need to add dialog support");
2227                 /*
2228                 Roo.MessageBox.alert("Error",
2229                     (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
2230                         action.result.errorMsg :
2231                         "Saving Failed, please check your entries or try again"
2232                 );
2233                 */
2234             }
2235             
2236             this.fireEvent('actionfailed', this, action);
2237         }
2238         
2239     },
2240     /**
2241      * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
2242      * @param {String} id The value to search for
2243      * @return Field
2244      */
2245     findField : function(id){
2246         var items = this.getItems();
2247         var field = items.get(id);
2248         if(!field){
2249             this.items.each(function(f){
2250                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
2251                     field = f;
2252                     return false;
2253                 }
2254                 return true;
2255             });
2256         }
2257         return field || null;
2258     },
2259      /**
2260      * Mark fields in this form invalid in bulk.
2261      * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
2262      * @return {BasicForm} this
2263      */
2264     markInvalid : function(errors){
2265         if(errors instanceof Array){
2266             for(var i = 0, len = errors.length; i < len; i++){
2267                 var fieldError = errors[i];
2268                 var f = this.findField(fieldError.id);
2269                 if(f){
2270                     f.markInvalid(fieldError.msg);
2271                 }
2272             }
2273         }else{
2274             var field, id;
2275             for(id in errors){
2276                 if(typeof errors[id] != 'function' && (field = this.findField(id))){
2277                     field.markInvalid(errors[id]);
2278                 }
2279             }
2280         }
2281         //Roo.each(this.childForms || [], function (f) {
2282         //    f.markInvalid(errors);
2283         //});
2284         
2285         return this;
2286     },
2287
2288     /**
2289      * Set values for fields in this form in bulk.
2290      * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
2291      * @return {BasicForm} this
2292      */
2293     setValues : function(values){
2294         if(values instanceof Array){ // array of objects
2295             for(var i = 0, len = values.length; i < len; i++){
2296                 var v = values[i];
2297                 var f = this.findField(v.id);
2298                 if(f){
2299                     f.setValue(v.value);
2300                     if(this.trackResetOnLoad){
2301                         f.originalValue = f.getValue();
2302                     }
2303                 }
2304             }
2305         }else{ // object hash
2306             var field, id;
2307             for(id in values){
2308                 if(typeof values[id] != 'function' && (field = this.findField(id))){
2309                     
2310                     if (field.setFromData && 
2311                         field.valueField && 
2312                         field.displayField &&
2313                         // combos' with local stores can 
2314                         // be queried via setValue()
2315                         // to set their value..
2316                         (field.store && !field.store.isLocal)
2317                         ) {
2318                         // it's a combo
2319                         var sd = { };
2320                         sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
2321                         sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
2322                         field.setFromData(sd);
2323                         
2324                     } else {
2325                         field.setValue(values[id]);
2326                     }
2327                     
2328                     
2329                     if(this.trackResetOnLoad){
2330                         field.originalValue = field.getValue();
2331                     }
2332                 }
2333             }
2334         }
2335          
2336         //Roo.each(this.childForms || [], function (f) {
2337         //    f.setValues(values);
2338         //});
2339                 
2340         return this;
2341     },
2342
2343     /**
2344      * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
2345      * they are returned as an array.
2346      * @param {Boolean} asString
2347      * @return {Object}
2348      */
2349     getValues : function(asString){
2350         //if (this.childForms) {
2351             // copy values from the child forms
2352         //    Roo.each(this.childForms, function (f) {
2353         //        this.setValues(f.getValues());
2354         //    }, this);
2355         //}
2356         
2357         
2358         
2359         var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
2360         if(asString === true){
2361             return fs;
2362         }
2363         return Roo.urlDecode(fs);
2364     },
2365     
2366     /**
2367      * Returns the fields in this form as an object with key/value pairs. 
2368      * This differs from getValues as it calls getValue on each child item, rather than using dom data.
2369      * @return {Object}
2370      */
2371     getFieldValues : function(with_hidden)
2372     {
2373         var items = this.getItems();
2374         var ret = {};
2375         items.each(function(f){
2376             if (!f.getName()) {
2377                 return;
2378             }
2379             var v = f.getValue();
2380             if (f.inputType =='radio') {
2381                 if (typeof(ret[f.getName()]) == 'undefined') {
2382                     ret[f.getName()] = ''; // empty..
2383                 }
2384                 
2385                 if (!f.el.dom.checked) {
2386                     return;
2387                     
2388                 }
2389                 v = f.el.dom.value;
2390                 
2391             }
2392             
2393             // not sure if this supported any more..
2394             if ((typeof(v) == 'object') && f.getRawValue) {
2395                 v = f.getRawValue() ; // dates..
2396             }
2397             // combo boxes where name != hiddenName...
2398             if (f.name != f.getName()) {
2399                 ret[f.name] = f.getRawValue();
2400             }
2401             ret[f.getName()] = v;
2402         });
2403         
2404         return ret;
2405     },
2406
2407     /**
2408      * Clears all invalid messages in this form.
2409      * @return {BasicForm} this
2410      */
2411     clearInvalid : function(){
2412         var items = this.getItems();
2413         
2414         items.each(function(f){
2415            f.clearInvalid();
2416         });
2417         
2418         
2419         
2420         return this;
2421     },
2422
2423     /**
2424      * Resets this form.
2425      * @return {BasicForm} this
2426      */
2427     reset : function(){
2428         var items = this.getItems();
2429         items.each(function(f){
2430             f.reset();
2431         });
2432         
2433         Roo.each(this.childForms || [], function (f) {
2434             f.reset();
2435         });
2436        
2437         
2438         return this;
2439     },
2440     getItems : function()
2441     {
2442         
2443         var iter = function(el) {
2444             
2445             
2446             
2447         };
2448         
2449         
2450         
2451         
2452     }
2453     
2454 });
2455
2456  
2457 /*
2458  * Based on:
2459  * Ext JS Library 1.1.1
2460  * Copyright(c) 2006-2007, Ext JS, LLC.
2461  *
2462  * Originally Released Under LGPL - original licence link has changed is not relivant.
2463  *
2464  * Fork - LGPL
2465  * <script type="text/javascript">
2466  */
2467 /**
2468  * @class Roo.form.VTypes
2469  * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
2470  * @singleton
2471  */
2472 Roo.form.VTypes = function(){
2473     // closure these in so they are only created once.
2474     var alpha = /^[a-zA-Z_]+$/;
2475     var alphanum = /^[a-zA-Z0-9_]+$/;
2476     var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
2477     var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
2478
2479     // All these messages and functions are configurable
2480     return {
2481         /**
2482          * The function used to validate email addresses
2483          * @param {String} value The email address
2484          */
2485         'email' : function(v){
2486             return email.test(v);
2487         },
2488         /**
2489          * The error text to display when the email validation function returns false
2490          * @type String
2491          */
2492         'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
2493         /**
2494          * The keystroke filter mask to be applied on email input
2495          * @type RegExp
2496          */
2497         'emailMask' : /[a-z0-9_\.\-@]/i,
2498
2499         /**
2500          * The function used to validate URLs
2501          * @param {String} value The URL
2502          */
2503         'url' : function(v){
2504             return url.test(v);
2505         },
2506         /**
2507          * The error text to display when the url validation function returns false
2508          * @type String
2509          */
2510         'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
2511         
2512         /**
2513          * The function used to validate alpha values
2514          * @param {String} value The value
2515          */
2516         'alpha' : function(v){
2517             return alpha.test(v);
2518         },
2519         /**
2520          * The error text to display when the alpha validation function returns false
2521          * @type String
2522          */
2523         'alphaText' : 'This field should only contain letters and _',
2524         /**
2525          * The keystroke filter mask to be applied on alpha input
2526          * @type RegExp
2527          */
2528         'alphaMask' : /[a-z_]/i,
2529
2530         /**
2531          * The function used to validate alphanumeric values
2532          * @param {String} value The value
2533          */
2534         'alphanum' : function(v){
2535             return alphanum.test(v);
2536         },
2537         /**
2538          * The error text to display when the alphanumeric validation function returns false
2539          * @type String
2540          */
2541         'alphanumText' : 'This field should only contain letters, numbers and _',
2542         /**
2543          * The keystroke filter mask to be applied on alphanumeric input
2544          * @type RegExp
2545          */
2546         'alphanumMask' : /[a-z0-9_]/i
2547     };
2548 }();/*
2549  * - LGPL
2550  *
2551  * Input
2552  * 
2553  */
2554
2555 /**
2556  * @class Roo.bootstrap.Input
2557  * @extends Roo.bootstrap.Component
2558  * Bootstrap Input class
2559  * @cfg {Boolean} disabled is it disabled
2560  * @cfg {String} fieldLabel - the label associated
2561  * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
2562  * @cfg {String} name name of the input
2563  * @cfg {string} fieldLabel - the label associated
2564  * @cfg {string}  inputType - input / file submit ...
2565  * @cfg {string} placeholder - placeholder to put in text.
2566  * @cfg {string}  before - input group add on before
2567  * @cfg {string} after - input group add on after
2568  * 
2569  * 
2570  * @constructor
2571  * Create a new Input
2572  * @param {Object} config The config object
2573  */
2574
2575 Roo.bootstrap.Input = function(config){
2576     Roo.bootstrap.Input.superclass.constructor.call(this, config);
2577    
2578         this.addEvents({
2579             /**
2580              * @event focus
2581              * Fires when this field receives input focus.
2582              * @param {Roo.form.Field} this
2583              */
2584             focus : true,
2585             /**
2586              * @event blur
2587              * Fires when this field loses input focus.
2588              * @param {Roo.form.Field} this
2589              */
2590             blur : true,
2591             /**
2592              * @event specialkey
2593              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
2594              * {@link Roo.EventObject#getKey} to determine which key was pressed.
2595              * @param {Roo.form.Field} this
2596              * @param {Roo.EventObject} e The event object
2597              */
2598             specialkey : true,
2599             /**
2600              * @event change
2601              * Fires just before the field blurs if the field value has changed.
2602              * @param {Roo.form.Field} this
2603              * @param {Mixed} newValue The new value
2604              * @param {Mixed} oldValue The original value
2605              */
2606             change : true,
2607             /**
2608              * @event invalid
2609              * Fires after the field has been marked as invalid.
2610              * @param {Roo.form.Field} this
2611              * @param {String} msg The validation message
2612              */
2613             invalid : true,
2614             /**
2615              * @event valid
2616              * Fires after the field has been validated with no errors.
2617              * @param {Roo.form.Field} this
2618              */
2619             valid : true,
2620              /**
2621              * @event keyup
2622              * Fires after the key up
2623              * @param {Roo.form.Field} this
2624              * @param {Roo.EventObject}  e The event Object
2625              */
2626             keyup : true
2627         });
2628 };
2629
2630 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
2631      /**
2632      * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
2633       automatic validation (defaults to "keyup").
2634      */
2635     validationEvent : "keyup",
2636      /**
2637      * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
2638      */
2639     validateOnBlur : true,
2640     /**
2641      * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
2642      */
2643     validationDelay : 250,
2644      /**
2645      * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
2646      */
2647     focusClass : "x-form-focus",  // not needed???
2648     
2649        
2650     /**
2651      * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
2652      */
2653     invalidClass : "has-error",
2654     
2655     /**
2656      * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
2657      */
2658     selectOnFocus : false,
2659     
2660      /**
2661      * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
2662      */
2663     maskRe : null,
2664        /**
2665      * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
2666      */
2667     vtype : null,
2668     
2669       /**
2670      * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
2671      */
2672     disableKeyFilter : false,
2673     
2674        /**
2675      * @cfg {Boolean} disabled True to disable the field (defaults to false).
2676      */
2677     disabled : false,
2678      /**
2679      * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
2680      */
2681     allowBlank : true,
2682     /**
2683      * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
2684      */
2685     blankText : "This field is required",
2686     
2687      /**
2688      * @cfg {Number} minLength Minimum input field length required (defaults to 0)
2689      */
2690     minLength : 0,
2691     /**
2692      * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
2693      */
2694     maxLength : Number.MAX_VALUE,
2695     /**
2696      * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
2697      */
2698     minLengthText : "The minimum length for this field is {0}",
2699     /**
2700      * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
2701      */
2702     maxLengthText : "The maximum length for this field is {0}",
2703   
2704     
2705     /**
2706      * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
2707      * If available, this function will be called only after the basic validators all return true, and will be passed the
2708      * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
2709      */
2710     validator : null,
2711     /**
2712      * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
2713      * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
2714      * current field value.  If the test fails, the field will be marked invalid using {@link #regexText}.
2715      */
2716     regex : null,
2717     /**
2718      * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
2719      */
2720     regexText : "",
2721     
2722     
2723     
2724     fieldLabel : '',
2725     inputType : 'text',
2726     
2727     name : false,
2728     placeholder: false,
2729     before : false,
2730     after : false,
2731     
2732     // private
2733     hasFocus : false,
2734     preventMark: false,
2735     
2736     getAutoCreate : function(){
2737         
2738         var parent = this.parent();
2739         
2740         var align = parent.labelAlign;
2741         
2742         var id = Roo.id();
2743         
2744         var cfg = {
2745             cls: 'form-group' //input-group
2746         };
2747         
2748         var input =  {
2749             tag: 'input',
2750             id : id,
2751             type : this.inputType,
2752             cls : 'form-control',
2753             placeholder : this.placeholder || '' 
2754             
2755         };
2756         if (this.name) {
2757             input.name = name;
2758         }
2759         
2760         var inputblock = input;
2761         
2762         if (this.before || this.after) {
2763             
2764             inputblock = {
2765                 cls : 'input-group',
2766                 cn :  [] 
2767             };
2768             if (this.before) {
2769                 inputblock.cn.push({
2770                     tag :'span',
2771                     cls : 'input-group-addon',
2772                     html : this.before
2773                 });
2774             }
2775             inputblock.cn.push(input);
2776             if (this.after) {
2777                 inputblock.cn.push({
2778                     tag :'span',
2779                     cls : 'input-group-addon',
2780                     html : this.after
2781                 });
2782             }
2783             
2784         }
2785         
2786         Roo.log(align);
2787         Roo.log(this.fieldLabel.length);
2788         
2789         if (align ==='left' && this.fieldLabel.length) {
2790                 Roo.log("left and has label");
2791                 cfg.cn = [
2792                     
2793                     {
2794                         tag: 'label',
2795                         'for' :  id,
2796                         cls : 'col-sm-2 control-label',
2797                         html : this.fieldLabel
2798                         
2799                     },
2800                     {
2801                         cls : "col-sm-10", 
2802                         cn: [
2803                             inputblock
2804                         ]
2805                     }
2806                     
2807                 ];
2808         } else if ( this.fieldLabel.length) {
2809                 Roo.log(" label");
2810                  cfg.cn = [
2811                    
2812                     {
2813                         tag: 'label',
2814                         //cls : 'input-group-addon',
2815                         html : this.fieldLabel
2816                         
2817                     },
2818                     
2819                     inputblock
2820                     
2821                 ];
2822
2823         } else {
2824             
2825                    Roo.log(" no label && no align");
2826                 cfg.cn = [
2827                     
2828                         inputblock
2829                     
2830                 ];
2831                 
2832                 
2833         }
2834          
2835         
2836         
2837         
2838         if (this.disabled) {
2839             input.disabled=true;
2840         }
2841         return cfg;
2842         
2843     },
2844     /**
2845      * return the real input element.
2846      */
2847     inputEl: function ()
2848     {
2849         return this.el.select('input.form-control',true).first();
2850     },
2851     setDisabled : function(v)
2852     {
2853         var i  = this.inputEl().dom;
2854         if (v) {
2855             i.removeAttribute('disabled');
2856             return;
2857             
2858         }
2859         i.setAttribute('disabled','true');
2860     },
2861     initEvents : function()
2862     {
2863         
2864         this.inputEl().on("keydown" , this.fireKey,  this);
2865         this.inputEl().on("focus", this.onFocus,  this);
2866         this.inputEl().on("blur", this.onBlur,  this);
2867         this.inputEl().relayEvent('keyup', this);
2868
2869         // reference to original value for reset
2870         this.originalValue = this.getValue();
2871         //Roo.form.TextField.superclass.initEvents.call(this);
2872         if(this.validationEvent == 'keyup'){
2873             this.validationTask = new Roo.util.DelayedTask(this.validate, this);
2874             this.inputEl().on('keyup', this.filterValidation, this);
2875         }
2876         else if(this.validationEvent !== false){
2877             this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
2878         }
2879         
2880         if(this.selectOnFocus){
2881             this.on("focus", this.preFocus, this);
2882             
2883         }
2884         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
2885             this.inputEl().on("keypress", this.filterKeys, this);
2886         }
2887        /* if(this.grow){
2888             this.el.on("keyup", this.onKeyUp,  this, {buffer:50});
2889             this.el.on("click", this.autoSize,  this);
2890         }
2891         */
2892         if(this.inputEl().is('input[type=password]') && Roo.isSafari){
2893             this.inputEl().on('keydown', this.SafariOnKeyDown, this);
2894         }
2895         
2896     },
2897     filterValidation : function(e){
2898         if(!e.isNavKeyPress()){
2899             this.validationTask.delay(this.validationDelay);
2900         }
2901     },
2902      /**
2903      * Validates the field value
2904      * @return {Boolean} True if the value is valid, else false
2905      */
2906     validate : function(){
2907         //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
2908         if(this.disabled || this.validateValue(this.getRawValue())){
2909             this.clearInvalid();
2910             return true;
2911         }
2912         return false;
2913     },
2914     
2915     
2916     /**
2917      * Validates a value according to the field's validation rules and marks the field as invalid
2918      * if the validation fails
2919      * @param {Mixed} value The value to validate
2920      * @return {Boolean} True if the value is valid, else false
2921      */
2922     validateValue : function(value){
2923         if(value.length < 1)  { // if it's blank
2924              if(this.allowBlank){
2925                 this.clearInvalid();
2926                 return true;
2927              }else{
2928                 this.markInvalid(this.blankText);
2929                 return false;
2930              }
2931         }
2932         if(value.length < this.minLength){
2933             this.markInvalid(String.format(this.minLengthText, this.minLength));
2934             return false;
2935         }
2936         if(value.length > this.maxLength){
2937             this.markInvalid(String.format(this.maxLengthText, this.maxLength));
2938             return false;
2939         }
2940         if(this.vtype){
2941             var vt = Roo.form.VTypes;
2942             if(!vt[this.vtype](value, this)){
2943                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
2944                 return false;
2945             }
2946         }
2947         if(typeof this.validator == "function"){
2948             var msg = this.validator(value);
2949             if(msg !== true){
2950                 this.markInvalid(msg);
2951                 return false;
2952             }
2953         }
2954         if(this.regex && !this.regex.test(value)){
2955             this.markInvalid(this.regexText);
2956             return false;
2957         }
2958         return true;
2959     },
2960
2961     
2962     
2963      // private
2964     fireKey : function(e){
2965         //Roo.log('field ' + e.getKey());
2966         if(e.isNavKeyPress()){
2967             this.fireEvent("specialkey", this, e);
2968         }
2969     },
2970     onFocus : function(){
2971         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
2972            // this.el.addClass(this.focusClass);
2973         }
2974         if(!this.hasFocus){
2975             this.hasFocus = true;
2976             this.startValue = this.getValue();
2977             this.fireEvent("focus", this);
2978         }
2979     },
2980     
2981     beforeBlur : Roo.emptyFn,
2982
2983     
2984     // private
2985     onBlur : function(){
2986         this.beforeBlur();
2987         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
2988             //this.el.removeClass(this.focusClass);
2989         }
2990         this.hasFocus = false;
2991         if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
2992             this.validate();
2993         }
2994         var v = this.getValue();
2995         if(String(v) !== String(this.startValue)){
2996             this.fireEvent('change', this, v, this.startValue);
2997         }
2998         this.fireEvent("blur", this);
2999     },
3000      /**
3001      * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
3002      * @return {Mixed} value The field value
3003      */
3004     getValue : function(){
3005         var v = this.inputEl().getValue();
3006         return v;
3007     },
3008     /**
3009      * Returns the raw data value which may or may not be a valid, defined value.  To return a normalized value see {@link #getValue}.
3010      * @return {Mixed} value The field value
3011      */
3012     getRawValue : function(){
3013         var v = this.inputEl().getValue();
3014         
3015         return v;
3016     },
3017     /**
3018      * Sets a data value into the field and validates it.  To set the value directly without validation see {@link #setRawValue}.
3019      * @param {Mixed} value The value to set
3020      */
3021     setValue : function(v){
3022         this.value = v;
3023         if(this.rendered){
3024             this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
3025             this.validate();
3026         }
3027     },
3028     
3029     /*
3030     processValue : function(value){
3031         if(this.stripCharsRe){
3032             var newValue = value.replace(this.stripCharsRe, '');
3033             if(newValue !== value){
3034                 this.setRawValue(newValue);
3035                 return newValue;
3036             }
3037         }
3038         return value;
3039     },
3040   */
3041     preFocus : function(){
3042         
3043         if(this.selectOnFocus){
3044             this.inputEl().dom.select();
3045         }
3046     },
3047     filterKeys : function(e){
3048         var k = e.getKey();
3049         if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
3050             return;
3051         }
3052         var c = e.getCharCode(), cc = String.fromCharCode(c);
3053         if(Roo.isIE && (e.isSpecialKey() || !cc)){
3054             return;
3055         }
3056         if(!this.maskRe.test(cc)){
3057             e.stopEvent();
3058         }
3059     },
3060      /**
3061      * Clear any invalid styles/messages for this field
3062      */
3063     clearInvalid : function(){
3064         
3065         if(!this.el || this.preventMark){ // not rendered
3066             return;
3067         }
3068         this.el.removeClass(this.invalidClass);
3069         /*
3070         switch(this.msgTarget){
3071             case 'qtip':
3072                 this.el.dom.qtip = '';
3073                 break;
3074             case 'title':
3075                 this.el.dom.title = '';
3076                 break;
3077             case 'under':
3078                 if(this.errorEl){
3079                     Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
3080                 }
3081                 break;
3082             case 'side':
3083                 if(this.errorIcon){
3084                     this.errorIcon.dom.qtip = '';
3085                     this.errorIcon.hide();
3086                     this.un('resize', this.alignErrorIcon, this);
3087                 }
3088                 break;
3089             default:
3090                 var t = Roo.getDom(this.msgTarget);
3091                 t.innerHTML = '';
3092                 t.style.display = 'none';
3093                 break;
3094         }
3095         */
3096         this.fireEvent('valid', this);
3097     },
3098      /**
3099      * Mark this field as invalid
3100      * @param {String} msg The validation message
3101      */
3102     markInvalid : function(msg){
3103         if(!this.el  || this.preventMark){ // not rendered
3104             return;
3105         }
3106         this.el.addClass(this.invalidClass);
3107         /*
3108         msg = msg || this.invalidText;
3109         switch(this.msgTarget){
3110             case 'qtip':
3111                 this.el.dom.qtip = msg;
3112                 this.el.dom.qclass = 'x-form-invalid-tip';
3113                 if(Roo.QuickTips){ // fix for floating editors interacting with DND
3114                     Roo.QuickTips.enable();
3115                 }
3116                 break;
3117             case 'title':
3118                 this.el.dom.title = msg;
3119                 break;
3120             case 'under':
3121                 if(!this.errorEl){
3122                     var elp = this.el.findParent('.x-form-element', 5, true);
3123                     this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
3124                     this.errorEl.setWidth(elp.getWidth(true)-20);
3125                 }
3126                 this.errorEl.update(msg);
3127                 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
3128                 break;
3129             case 'side':
3130                 if(!this.errorIcon){
3131                     var elp = this.el.findParent('.x-form-element', 5, true);
3132                     this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
3133                 }
3134                 this.alignErrorIcon();
3135                 this.errorIcon.dom.qtip = msg;
3136                 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
3137                 this.errorIcon.show();
3138                 this.on('resize', this.alignErrorIcon, this);
3139                 break;
3140             default:
3141                 var t = Roo.getDom(this.msgTarget);
3142                 t.innerHTML = msg;
3143                 t.style.display = this.msgDisplay;
3144                 break;
3145         }
3146         */
3147         this.fireEvent('invalid', this, msg);
3148     },
3149     // private
3150     SafariOnKeyDown : function(event)
3151     {
3152         // this is a workaround for a password hang bug on chrome/ webkit.
3153         
3154         var isSelectAll = false;
3155         
3156         if(this.inputEl().dom.selectionEnd > 0){
3157             isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
3158         }
3159         if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
3160             event.preventDefault();
3161             this.setValue('');
3162             return;
3163         }
3164         
3165         if(isSelectAll){ // backspace and delete key
3166             
3167             event.preventDefault();
3168             // this is very hacky as keydown always get's upper case.
3169             //
3170             var cc = String.fromCharCode(event.getCharCode());
3171             this.setValue( event.shiftKey ?  cc : cc.toLowerCase());
3172             
3173         }
3174         
3175         
3176     }
3177 });
3178
3179