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