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         
143         if (!tree.items || !tree.items.length) {
144             cn.items = nitems;
145             return cn;
146         }
147         var items = tree.items;
148         delete tree.items;
149         
150         //Roo.log(items.length);
151             // add the items..
152         for(var i =0;i < items.length;i++) {
153             nitems.push(cn.addxtype(Roo.apply({}, items[i])));
154         }
155         
156         cn.items = nitems;
157         
158         
159         return cn;
160     }
161     
162     
163     
164     
165 });
166
167  /*
168  * - LGPL
169  *
170  * page container.
171  * 
172  */ 
173 Roo.bootstrap.Body = function(config){
174     Roo.bootstrap.Body.superclass.constructor.call(this, config);
175     this.el = Roo.get(document.body);
176 };
177
178 Roo.extend(Roo.bootstrap.Body, Roo.bootstrap.Component,  {
179       
180         autoCreate : {
181         cls: 'container'
182     },
183     onRender : function(ct, position){
184         
185         
186         //this.el.addClass([this.fieldClass, this.cls]);
187         
188     }
189     
190     
191  
192    
193 });
194
195  /*
196  * - LGPL
197  *
198  * button group
199  * 
200  */
201
202
203 /**
204  * @class Roo.bootstrap.ButtonGroup
205  * @extends Roo.bootstrap.Component
206  * Bootstrap ButtonGroup class
207  * @cfg {String} size lg | sm | xs (default empty normal)
208  * @cfg {String} align vertical | justified  (default none)
209  * @cfg {String} direction up | down (default down)
210  * @cfg {Boolean} toolbar false | true
211  * @cfg {Boolean} btn true | false
212  * 
213  * 
214  * @constructor
215  * Create a new Input
216  * @param {Object} config The config object
217  */
218
219 Roo.bootstrap.ButtonGroup = function(config){
220     Roo.bootstrap.ButtonGroup.superclass.constructor.call(this, config);
221 };
222
223 Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component,  {
224     
225     size: '',
226     align: '',
227     direction: '',
228     toolbar: false,
229     btn: true,
230
231     getAutoCreate : function(){
232         var cfg = {
233             cls: 'btn-group',
234             html : null
235         }
236         
237         cfg.html = this.html || cfg.html;
238         
239         if (this.toolbar) {
240             cfg = {
241                 cls: 'btn-toolbar',
242                 html: null
243             }
244             
245             return cfg;
246         }
247         
248         if (['vertical','justified'].indexOf(this.align)!==-1) {
249             cfg.cls = 'btn-group-' + this.align;
250             
251             if (this.align == 'justified') {
252                 console.log(this.items);
253             }
254         }
255         
256         if (['lg','sm','xs'].indexOf(this.size)!==-1) {
257             cfg.cls += ' btn-group-' + this.size;
258         }
259         
260         if (this.direction == 'up') {
261             cfg.cls += ' dropup' ;
262         }
263         
264         return cfg;
265     }
266    
267 });
268
269  /*
270  * - LGPL
271  *
272  * button
273  * 
274  */
275
276 /**
277  * @class Roo.bootstrap.Button
278  * @extends Roo.bootstrap.Component
279  * Bootstrap Button class
280  * @cfg {String} html The button content
281  * @cfg {String} weight default (or empty) | primary | success | info | warning | danger
282  * @cfg {String} size empty | lg | sm | xs
283  * @cfg {String} tag empty | a | input | submit
284  * @cfg {String} href empty or href
285  * @cfg {Boolean} disabled false | true
286  * @cfg {Boolean} isClose false | true
287  * @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
288  * @cfg {String} badge text for badge
289  * @cfg {String} theme default (or empty) | glow
290  * @cfg {Boolean} inverse false | true
291  * @cfg {Boolean} toggle false | true
292  * @cfg {String} ontext text for on toggle state
293  * @cfg {String} offtext text for off toggle state
294  * @cfg {Boolean} defaulton true | false
295  * 
296  * @constructor
297  * Create a new button
298  * @param {Object} config The config object
299  */
300
301
302 Roo.bootstrap.Button = function(config){
303     Roo.bootstrap.Button.superclass.constructor.call(this, config);
304     this.addEvents({
305         // raw events
306         /**
307          * @event click
308          * The raw click event for the entire grid.
309          * @param {Roo.EventObject} e
310          */
311         "click" : true
312     });
313 };
314
315 Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component,  {
316     html: false,
317     active: false,
318     weight: '',
319     size: '',
320     tag: 'button',
321     href: '',
322     disabled: false,
323     isClose: false,
324     glyphicon: '',
325     badge: '',
326     theme: 'default',
327     inverse: false,
328     
329     toggle: false,
330     ontext: 'ON',
331     offtext: 'OFF',
332     defaulton: true,
333     
334     getAutoCreate : function(){
335         
336         var cfg = {
337             tag : 'button',
338             cls : 'roo-button',
339             html: 'hello'
340         };
341         
342         if (['a', 'button', 'input', 'submit'].indexOf(this.tag) < 0) {
343             throw "Invalid value for tag: " + this.tag + ". must be a, button, input or submit.";
344             this.tag = 'button';
345         } else {
346             cfg.tag = this.tag;
347         }
348         cfg.html = this.html || cfg.html;
349         
350         if (this.toggle===true) {
351             cfg={
352                 tag: 'div',
353                 cls: 'slider-frame roo-button',
354                 cn: [
355                     {
356                         tag: 'span',
357                         'data-on-text':'ON',
358                         'data-off-text':'OFF',
359                         cls: 'slider-button',
360                         html: this.offtext
361                     }
362                 ]
363             };
364             
365             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
366                 cfg.cls += ' '+this.weight;
367             }
368             
369             return cfg;
370         }
371         
372         if (this.isClose) {
373             cfg.cls += ' close';
374             
375             cfg["aria-hidden"] = true;
376             
377             cfg.html = "&times;";
378             
379             return cfg;
380         }
381         
382          
383         if (this.theme==='default') {
384             cfg.cls = 'btn roo-button';
385             
386             if (this.parentType != 'Navbar') {
387                 this.weight = this.weight.length ?  this.weight : 'default';
388             }
389             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
390                 
391                 cfg.cls += ' btn-' + this.weight;
392             }
393         } else if (this.theme==='glow') {
394             
395             cfg.tag = 'a';
396             cfg.cls = 'btn-glow roo-button';
397             
398             if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
399                 
400                 cfg.cls += ' ' + this.weight;
401             }
402         }
403    
404         
405         if (this.inverse) {
406             this.cls += ' inverse';
407         }
408         
409         
410         if (this.active) {
411             cfg.cls += ' active';
412         }
413         
414         cfg.cls += this.size.length ? (' btn-' + this.size) : '';
415          
416         //gsRoo.log(this.parentType);
417         if (this.parentType === 'Navbar') {
418             cfg.tag = 'li';
419             
420             cfg.cls = '';
421             cfg.cn =  [{
422                 tag : 'a',
423                 cls : 'roo-button',
424                 html : this.html,
425                 href : this.href || '#'
426             }];
427             if (this.menu) {
428                 cfg.cn[0].html = this.html  + ' <span class="caret"></span>';
429                 cfg.cls += ' dropdown';
430             }   
431             
432             delete cfg.html;
433             
434         } else if (this.menu) {
435             cfg.tag = 'a';
436             cfg.cls += ' dropdown test';
437         }
438         
439         
440         
441         if (this.disabled) {
442             cfg.disabled = 'disabled';
443         }
444         //????
445         if (this.items) {
446             Roo.log('changing to ul' );
447             cfg.tag = 'ul';
448             this.glyphicon = 'caret';
449         }
450         
451         if (this.glyphicon) {
452             cfg.html = ' ' + cfg.html;
453             
454             cfg.cn = [
455                 {
456                     tag: 'span',
457                     cls: 'glyphicon glyphicon-' + this.glyphicon
458                 }
459             ];
460         }
461         
462         if (this.badge) {
463             cfg.html += ' ';
464             
465             cfg.tag = 'a';
466             
467             cfg.cls='btn roo-button';
468             
469             cfg.href=this.href;
470             
471             cfg.cn = [
472                 cfg.html,
473                 {
474                     tag: 'span',
475                     cls: 'badge',
476                     html: this.badge
477                 }
478             ];
479             
480             cfg.html='';
481         }
482         
483         if (cfg.tag !== 'a' && this.href !== '') {
484             throw "Tag must be a to set href.";
485         } else if (this.href.length > 0) {
486             cfg.href = this.href;
487         }
488         
489         return cfg;
490     },
491     initEvents: function() {
492        // Roo.log('init events?');
493        // Roo.log(this.el.dom);
494        if (this.el.hasClass('roo-button')) {
495             this.el.on('click', this.onClick, this);
496        } else {
497             this.el.select('.roo-button').on('click', this.onClick, this);
498        }
499        
500        
501         
502     },
503     onClick : function(e)
504     {
505         Roo.log('button on click ');
506         e.preventDefault();
507         this.fireEvent('click', this, e);
508     }
509     
510     
511 });
512
513  /*
514  * - LGPL
515  *
516  * column
517  * 
518  */
519
520 /**
521  * @class Roo.bootstrap.Column
522  * @extends Roo.bootstrap.Component
523  * Bootstrap Column class
524  * @cfg {Number} xs colspan out of 12 for mobile-sized screens
525  * @cfg {Number} sm colspan out of 12 for tablet-sized screens
526  * @cfg {Number} md colspan out of 12 for computer-sized screens
527  * @cfg {Number} lg colspan out of 12 for large computer-sized screens
528  * @cfg {String} html content of column.
529  * 
530  * @constructor
531  * Create a new Column
532  * @param {Object} config The config object
533  */
534
535 Roo.bootstrap.Column = function(config){
536     Roo.bootstrap.Column.superclass.constructor.call(this, config);
537 };
538
539 Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
540     
541     xs: null,
542     sm: null,
543     md: null,
544     lg: null,
545     html: '',
546     offset: 0,
547     
548     getAutoCreate : function(){
549         var cfg = Roo.apply({}, Roo.bootstrap.Column.superclass.getAutoCreate.call(this));
550         
551         cfg = {
552             tag: 'div',
553             cls: 'column'
554         };
555         
556         var settings=this;
557         ['xs','sm','md','lg'].map(function(size){
558             if (settings[size]) {
559                 cfg.cls += ' col-' + size + '-' + settings[size];
560             }
561         });
562         if (this.html.length) {
563             cfg.html = this.html;
564         }
565         
566         return cfg;
567     }
568    
569 });
570
571  
572
573  /*
574  * - LGPL
575  *
576  * page container.
577  * 
578  */
579
580
581 /**
582  * @class Roo.bootstrap.Container
583  * @extends Roo.bootstrap.Component
584  * Bootstrap Container class
585  * @cfg {Boolean} jumbotron is it a jumbotron element
586  * @cfg {String} html content of element
587  * @cfg {String} well (lg|sm|md) a well, large, small or medium.
588  * @cfg {String} panel (primary|success|info|warning|danger) render as a panel.
589  * @cfg {String} header content of header (for panel)
590  * @cfg {String} footer content of footer (for panel)
591  * @cfg {String} sticky (footer|wrap|push) block to use as footer or body- needs css-bootstrap/sticky-footer.css
592  *     
593  * @constructor
594  * Create a new Container
595  * @param {Object} config The config object
596  */
597
598 Roo.bootstrap.Container = function(config){
599     Roo.bootstrap.Container.superclass.constructor.call(this, config);
600 };
601
602 Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
603     
604     jumbotron : false,
605     well: '',
606     panel : '',
607     header: '',
608     footer : '',
609     sticky: '',
610   
611      
612     getChildContainer : function() {
613         if (this.panel.length) {
614             return this.el.select('.panel-body',true).first();
615         }
616         
617         return this.el;
618     },
619     
620     
621     getAutoCreate : function(){
622         
623         var cfg = {
624             html : '',
625             cls : ''
626         };
627         if (this.jumbotron) {
628             cfg.cls = 'jumbotron';
629         }
630         if (this.cls) {
631             cfg.cls = this.cls + '';
632         }
633         
634         if (this.sticky.length) {
635             var bd = Roo.get(document.body);
636             if (!bd.hasClass('bootstrap-sticky')) {
637                 bd.addClass('bootstrap-sticky');
638                 Roo.select('html',true).setStyle('height', '100%');
639             }
640              
641             cfg.cls += 'bootstrap-sticky-' + this.sticky;
642         }
643         
644         
645         if (this.well.length) {
646             switch (this.well) {
647                 case 'lg':
648                 case 'sm':
649                     cfg.cls +=' well well-' +this.well;
650                     break;
651                 default:
652                     cfg.cls +=' well';
653                     break;
654             }
655         }
656         
657         var body = cfg;
658         
659         if (this.panel.length) {
660             cfg.cls += 'panel panel-' + this.panel;
661             cfg.cn = [];
662             if (this.header.length) {
663                 cfg.cn.push({
664                     
665                     cls : 'panel-heading',
666                     cn : [{
667                         tag: 'h3',
668                         cls : 'panel-title',
669                         html : this.header
670                     }]
671                     
672                 });
673             }
674             body = false;
675             cfg.cn.push({
676                 cls : 'panel-body',
677                 html : this.html
678             });
679             
680             
681             if (this.footer.length) {
682                 cfg.cn.push({
683                     cls : 'panel-footer',
684                     html : this.footer
685                     
686                 });
687             }
688             
689         }
690         if (body) {
691             body.html = this.html || cfg.html;
692         }
693         if (!cfg.cls.length) {
694             cfg.cls =  'container';
695         }
696         
697         return cfg;
698     }
699    
700 });
701
702  /*
703  * - LGPL
704  *
705  * image
706  * 
707  */
708
709
710 /**
711  * @class Roo.bootstrap.Img
712  * @extends Roo.bootstrap.Component
713  * Bootstrap Img class
714  * @cfg {Boolean} imgResponsive false | true
715  * @cfg {String} border rounded | circle | thumbnail
716  * @cfg {String} src image source
717  * @cfg {String} alt image alternative text
718  * 
719  * @constructor
720  * Create a new Input
721  * @param {Object} config The config object
722  */
723
724 Roo.bootstrap.Img = function(config){
725     Roo.bootstrap.Img.superclass.constructor.call(this, config);
726 };
727
728 Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component,  {
729     
730     imgResponsive: true,
731     border: '',
732     src: '',
733
734     getAutoCreate : function(){
735         
736         cfg = {
737             tag: 'img',
738             cls: 'img-responsive',
739             html : null
740         }
741         
742         cfg.html = this.html || cfg.html;
743         
744         cfg.src = this.src || cfg.src;
745         
746         if (['rounded','circle','thumbnail'].indexOf(this.border)>-1) {
747             cfg.cls += ' img-' + this.border;
748         }
749         
750         if(this.alt){
751             cfg.alt = this.alt;
752         }
753         
754         return cfg;
755     }
756    
757 });
758
759  /*
760  * - LGPL
761  *
762  * header
763  * 
764  */
765
766 /**
767  * @class Roo.bootstrap.Header
768  * @extends Roo.bootstrap.Component
769  * Bootstrap Header class
770  * @cfg {String} html content of header
771  * @cfg {Number} level (1|2|3|4|5|6) default 1
772  * 
773  * @constructor
774  * Create a new Header
775  * @param {Object} config The config object
776  */
777
778
779 Roo.bootstrap.Header  = function(config){
780     Roo.bootstrap.Header.superclass.constructor.call(this, config);
781 };
782
783 Roo.extend(Roo.bootstrap.Header, Roo.bootstrap.Component,  {
784     
785     //href : false,
786     html : false,
787     level : 1,
788     
789     
790     
791     getAutoCreate : function(){
792         
793         var cfg = {
794             tag: 'h' + (1 *this.level),
795             html: this.html || 'fill in html'
796         } ;
797         
798         return cfg;
799     }
800    
801 });
802
803  
804
805  /*
806  * - LGPL
807  *
808  * menu
809  * 
810  */
811
812 /**
813  * @class Roo.bootstrap.Menu
814  * @extends Roo.bootstrap.Component
815  * Bootstrap Menu class - container for MenuItems
816  * @cfg {String} type type of menu
817  * 
818  * @constructor
819  * Create a new Menu
820  * @param {Object} config The config object
821  */
822
823
824 Roo.bootstrap.Menu = function(config){
825     Roo.bootstrap.Menu.superclass.constructor.call(this, config);
826 };
827
828 Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component,  {
829     
830    /// html : false,
831     //align : '',
832     triggerEl : false,
833     type: false,
834     
835     
836     getChildContainer : function() {
837         return this.el;  
838     },
839     
840     getAutoCreate : function(){
841          
842         //if (['right'].indexOf(this.align)!==-1) {
843         //    cfg.cn[1].cls += ' pull-right'
844         //}
845         var cfg = {
846             tag : 'ul',
847             cls : 'dropdown-menu' 
848             
849         }
850         
851         if (this.type==='submenu') {
852             cfg.cls='submenu active'
853         }
854         
855         return cfg;
856     },
857     initEvents : function() {
858        // Roo.log("ADD event");
859        // Roo.log(this.triggerEl.dom);
860         this.triggerEl.on('click', this.toggle, this);
861         this.triggerEl.addClass('dropdown-toggle');
862         
863     },
864     toggle  : function(e)
865     {
866         //Roo.log(e.getTarget());
867        // Roo.log(this.triggerEl.dom);
868         if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
869             return;
870         }
871         var isActive = this.triggerEl.hasClass('open');
872         // if disabled.. ingore
873         this.clearMenus(e);
874         //if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
875          // if mobile we use a backdrop because click events don't delegate
876         // $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
877         // }
878  
879        //var relatedTarget = { relatedTarget: this }
880        //$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
881  
882        //if (e.isDefaultPrevented()) return;
883         
884        this.triggerEl[isActive ? 'removeClass' : 'addClass']('open');
885        
886        //  .trigger('shown.bs.dropdown', relatedTarget)
887  
888        this.triggerEl.focus();
889        Roo.log(e);
890        e.preventDefault(); 
891         
892         
893     },
894     clearMenus : function()
895     {
896         //$(backdrop).remove()
897         Roo.select('.dropdown-toggle',true).each(function(aa) {
898             if (!aa.hasClass('open')) {
899                 return;
900             }
901             // triger close...
902             aa.removeClass('open');
903           //var parent = getParent($(this))
904           //var relatedTarget = { relatedTarget: this }
905           
906            //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
907           //if (e.isDefaultPrevented()) return
908            //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
909         })
910     }
911     
912    
913 });
914
915  
916
917  /*
918  * - LGPL
919  *
920  * menu item
921  * 
922  */
923
924
925 /**
926  * @class Roo.bootstrap.MenuItem
927  * @extends Roo.bootstrap.Component
928  * Bootstrap MenuItem class
929  * @cfg {String} html the menu label
930  * @cfg {String} href the link
931  * 
932  * 
933  * @constructor
934  * Create a new MenuItem
935  * @param {Object} config The config object
936  */
937
938
939 Roo.bootstrap.MenuItem = function(config){
940     Roo.bootstrap.MenuItem.superclass.constructor.call(this, config);
941 };
942
943 Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component,  {
944     
945     href : false,
946     html : false,
947     
948     getAutoCreate : function(){
949         var cfg= {
950             tag: 'li',
951             cn: [
952                 {
953                     tag : 'a',
954                     href : '#',
955                     html : 'Link'
956                 }
957             ]
958         };
959         
960         cfg.cn[0].href = this.href || cfg.cn[0].href ;
961         cfg.cn[0].html = this.html || cfg.cn[0].html ;
962         return cfg;
963     }
964    
965 });
966
967  
968
969  /*
970  * - LGPL
971  *
972  * menu separator
973  * 
974  */
975
976
977 /**
978  * @class Roo.bootstrap.MenuSeparator
979  * @extends Roo.bootstrap.Component
980  * Bootstrap MenuSeparator class
981  * 
982  * @constructor
983  * Create a new MenuItem
984  * @param {Object} config The config object
985  */
986
987
988 Roo.bootstrap.MenuSeparator = function(config){
989     Roo.bootstrap.MenuSeparator.superclass.constructor.call(this, config);
990 };
991
992 Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component,  {
993     
994     getAutoCreate : function(){
995         var cfg = {
996             cls: 'divider',
997             tag : 'li'
998         };
999         
1000         return cfg;
1001     }
1002    
1003 });
1004
1005  
1006
1007  
1008 /*
1009 <div class="modal fade">
1010   <div class="modal-dialog">
1011     <div class="modal-content">
1012       <div class="modal-header">
1013         <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1014         <h4 class="modal-title">Modal title</h4>
1015       </div>
1016       <div class="modal-body">
1017         <p>One fine body&hellip;</p>
1018       </div>
1019       <div class="modal-footer">
1020         <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
1021         <button type="button" class="btn btn-primary">Save changes</button>
1022       </div>
1023     </div><!-- /.modal-content -->
1024   </div><!-- /.modal-dialog -->
1025 </div><!-- /.modal -->
1026 */
1027 /*
1028  * - LGPL
1029  *
1030  * page contgainer.
1031  * 
1032  */
1033
1034 /**
1035  * @class Roo.bootstrap.Modal
1036  * @extends Roo.bootstrap.Component
1037  * Bootstrap Modal class
1038  * @cfg {String} title Title of dialog
1039  * @cfg {Array} buttons Array of buttons or standard button set..
1040  * 
1041  * @constructor
1042  * Create a new Modal Dialog
1043  * @param {Object} config The config object
1044  */
1045
1046 Roo.bootstrap.Modal = function(config){
1047     Roo.bootstrap.Modal.superclass.constructor.call(this, config);
1048     this.addEvents({
1049         // raw events
1050         /**
1051          * @event click
1052          * The raw click event for the entire grid.
1053          * @param {Roo.EventObject} e
1054          */
1055         "btnclick" : true
1056     });
1057 };
1058
1059 Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
1060     
1061     title : 'test dialog',
1062    
1063     buttons : false,
1064
1065     onRender : function(ct, position)
1066     {
1067         Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
1068         if(!this.el){
1069             var cfg = Roo.apply({},  this.getAutoCreate());
1070             cfg.id = Roo.id();
1071             //if(!cfg.name){
1072             //    cfg.name = typeof(this.name) == 'undefined' ? this.id : this.name;
1073             //}
1074             //if (!cfg.name.length) {
1075             //    delete cfg.name;
1076            // }
1077             if (this.cls) {
1078                 cfg.cls += ' ' + this.cls;
1079             }
1080             if (this.style) {
1081                 cfg.style = this.style;
1082             }
1083             this.el = Roo.get(document.body).createChild(cfg, position);
1084         }
1085         //var type = this.el.dom.type;
1086          
1087         if(this.tabIndex !== undefined){
1088             this.el.dom.setAttribute('tabIndex', this.tabIndex);
1089         }
1090         
1091         
1092         
1093         this.maskEl = Roo.DomHelper.append(document.body, {tag: "div", cls:"x-dlg-mask"}, true);
1094         this.maskEl.enableDisplayMode("block");
1095         this.maskEl.hide();
1096         //this.el.addClass("x-dlg-modal");
1097     
1098         
1099         if (this.buttons) {
1100             Roo.each(this.buttons, function(bb) {
1101                 b = Roo.apply({}, bb);
1102                 b.xns = b.xns || Roo.bootstrap;
1103                 b.xtype = b.xtype || 'Button';
1104                 if (typeof(b.listeners) == 'undefined') {
1105                     b.listeners = { click : this.onButtonClick.createDelegate(this)  };
1106                 }
1107                 
1108                 var btn = Roo.factory(b);
1109                 
1110                 btn.onRender(this.el.select('.modal-footer').first());
1111                 
1112             },this);
1113         }
1114         
1115         
1116         
1117         this.initEvents();
1118         //this.el.addClass([this.fieldClass, this.cls]);
1119         
1120     },
1121     getAutoCreate : function(){
1122         
1123         
1124         var bdy = {
1125                 cls : 'modal-body',
1126                 html : this.html || ''
1127         };
1128         
1129          
1130         return {
1131             cls: "modal fade",
1132             cn : [
1133                 {
1134                     cls: "modal-dialog",
1135                     cn : [
1136                         {
1137                             cls : "modal-content",
1138                             cn : [
1139                                 {
1140                                     cls : 'modal-header',
1141                                     cn : [
1142                                         {
1143                                             tag: 'button',
1144                                             cls : 'close',
1145                                             html : '&times'
1146                                         },
1147                                         {
1148                                             tag: 'h4',
1149                                             cls : 'modal-title',
1150                                             html : this.title
1151                                         }
1152                                     
1153                                     ]
1154                                 },
1155                                 bdy,
1156                                 {
1157                                     cls : 'modal-footer' 
1158                                 }
1159                                 
1160                                 
1161                             ]
1162                             
1163                         }
1164                     ]
1165                         
1166                 }
1167             ]
1168             
1169             
1170         };
1171           
1172     },
1173     getChildContainer : function() {
1174          
1175          return this.el.select('.modal-body',true).first();
1176         
1177     },
1178     getButtonContainer : function() {
1179          return this.el.select('.modal-footer',true).first();
1180         
1181     },
1182     initEvents : function()
1183     {
1184         this.el.select('.modal-header .close').on('click', this.hide, this);
1185     },
1186     show : function() {
1187         if (!this.rendered) {
1188             this.render();
1189         }
1190        
1191         this.el.addClass('on');
1192         this.el.removeClass('fade');
1193         this.el.setStyle('display', 'block');
1194         Roo.get(document.body).addClass("x-body-masked");
1195         this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
1196         this.maskEl.show();
1197         this.el.setStyle('zIndex', '10001');
1198         
1199         
1200     },
1201     hide : function()
1202     {
1203         this.maskEl.hide();
1204         this.el.removeClass('on');
1205         this.el.addClass('fade');
1206         this.el.setStyle('display', 'none');
1207     },
1208     onButtonClick: function(btn,e)
1209     {
1210         //Roo.log([a,b,c]);
1211         this.fireEvent('btnclick', btn.name, e);
1212     }
1213 });
1214
1215
1216 Roo.apply(Roo.bootstrap.Modal,  {
1217     /**
1218          * Button config that displays a single OK button
1219          * @type Object
1220          */
1221         OK :  [{
1222             name : 'ok',
1223             weight : 'primary',
1224             html : 'OK'
1225         }], 
1226         /**
1227          * Button config that displays Yes and No buttons
1228          * @type Object
1229          */
1230         YESNO : [
1231             {
1232                 name  :'yes',
1233                 weight : 'primary',
1234                 html : 'Yes'
1235             },
1236             {
1237                 name  : 'no',
1238                 html : 'No'
1239             }
1240         ],
1241         
1242         /**
1243          * Button config that displays OK and Cancel buttons
1244          * @type Object
1245          */
1246         OKCANCEL : [
1247             {
1248                 name : 'ok',
1249                 weight : 'primary',
1250                 html : 'OK'
1251             },
1252             {
1253                name : 'cancel',
1254                 html : 'Cancel'
1255             }
1256         ],
1257         /**
1258          * Button config that displays Yes, No and Cancel buttons
1259          * @type Object
1260          */
1261         YESNOCANCEL : [
1262             {
1263                 name : 'yes',
1264                 weight : 'primary',
1265                 html : 'Yes'
1266             },
1267             {
1268                 name : 'no',
1269                 html : 'No'
1270             },
1271             {
1272                 name : 'cancel',
1273                 html : 'Cancel'
1274             }
1275         ]
1276 });
1277
1278  /*
1279  * - LGPL
1280  *
1281  * navbar
1282  * 
1283  */
1284
1285 /**
1286  * @class Roo.bootstrap.Navbar
1287  * @extends Roo.bootstrap.Component
1288  * Bootstrap Navbar class
1289  * @cfg {Boolean} sidebar has side bar
1290  * @cfg {Boolean} bar is a bar?
1291  * @cfg {String} position (fixed-top|fixed-bottom|static-top) position
1292  * @cfg {String} brand what is brand
1293  * @cfg {Boolean} inverse is inverted color
1294  * @cfg {String} type (nav | pills | tabs)
1295  * @cfg {Boolean} arrangement stacked | justified
1296  * @cfg {String} align (left | right) alignment
1297  *
1298  * 
1299  * @constructor
1300  * Create a new Navbar
1301  * @param {Object} config The config object
1302  */
1303
1304
1305 Roo.bootstrap.Navbar = function(config){
1306     Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
1307 };
1308
1309 Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
1310     
1311     sidebar: false,
1312     
1313     bar: false,
1314     brand: '',
1315     inverse: false,
1316     position: '',
1317     align : false,
1318     type: 'nav',
1319     arrangement: '',
1320     
1321     getAutoCreate : function(){
1322         var cfg = {
1323             cls : 'navbar'
1324         };
1325         
1326         if (this.sidebar === true) {
1327             cfg = {
1328                 tag: 'div',
1329                 cls: 'sidebar-nav'
1330             };
1331             return cfg;
1332         }
1333         
1334         if (this.bar === true) {
1335             cfg = {
1336                 tag: 'nav',
1337                 cls: 'navbar',
1338                 role: 'navigation',
1339                 cn: [
1340                     {
1341                         tag: 'div',
1342                         cls: 'navbar-header',
1343                         cn: [
1344                             {
1345                             tag: 'button',
1346                             type: 'button',
1347                             cls: 'navbar-toggle',
1348                             'data-toggle': 'collapse',
1349                             cn: [
1350                                 {
1351                                     tag: 'span',
1352                                     cls: 'sr-only',
1353                                     html: 'Toggle navigation'
1354                                 },
1355                                 {
1356                                     tag: 'span',
1357                                     cls: 'icon-bar'
1358                                 },
1359                                 {
1360                                     tag: 'span',
1361                                     cls: 'icon-bar'
1362                                 },
1363                                 {
1364                                     tag: 'span',
1365                                     cls: 'icon-bar'
1366                                 }
1367                             ]
1368                             }
1369                         ]
1370                     },
1371                     {
1372                     tag: 'div',
1373                     cls: 'collapse navbar-collapse'
1374                     }
1375                 ]
1376             };
1377             
1378             cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
1379             
1380             if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
1381             cfg.cls += ' navbar-' + this.position;
1382             cfg.tag = this.position  == 'fixed-bottom' ? 'footer' : 'header';
1383             }
1384             
1385             if (this.brand !== '') {
1386                 cfg.cn[0].cn.push({
1387                     tag: 'a',
1388                     href: '#',
1389                     cls: 'navbar-brand',
1390                     cn: [
1391                     this.brand
1392                     ]
1393                 });
1394             }
1395             
1396             return cfg;
1397         
1398         } else if (this.bar === false) {
1399             
1400         } else {
1401             Roo.log('Property \'bar\' in of Navbar must be either true or false')
1402         }
1403         
1404         cfg.cn = [
1405             {
1406                 cls: 'nav',
1407                 tag : 'ul'
1408             }
1409         ];
1410         
1411         if (['tabs','pills'].indexOf(this.type)!==-1) {
1412             cfg.cn[0].cls += ' nav-' + this.type
1413         } else {
1414             if (this.type!=='nav') {
1415             Roo.log('nav type must be nav/tabs/pills')
1416             }
1417             cfg.cn[0].cls += ' navbar-nav'
1418         }
1419         
1420         if (['stacked','justified'].indexOf(this.arrangement)!==-1) {
1421             cfg.cn[0].cls += ' nav-' + this.arrangement;
1422         }
1423         
1424         if (this.align === 'right') {
1425             cfg.cn[0].cls += ' navbar-right';
1426         }
1427         if (this.inverse) {
1428             cfg.cls += ' navbar-inverse';
1429             
1430         }
1431         
1432         
1433         return cfg;
1434     },
1435     
1436     getChildContainer : function() {
1437         if (this.bar === true) {
1438             return this.el.select('.collapse',true).first();
1439         }
1440         console.log(this);
1441         return this.el;
1442     }
1443    
1444 });
1445
1446  
1447
1448  /*
1449  * - LGPL
1450  *
1451  * nav group
1452  * 
1453  */
1454
1455 /**
1456  * @class Roo.bootstrap.NavGroup
1457  * @extends Roo.bootstrap.Component
1458  * Bootstrap NavGroup class
1459  * @cfg {String} align left | right
1460  * @cfg {Boolean} inverse false | true
1461  * 
1462  * @constructor
1463  * Create a new nav group
1464  * @param {Object} config The config object
1465  */
1466
1467 Roo.bootstrap.NavGroup = function(config){
1468     Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
1469 };
1470
1471 Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
1472     
1473     align: '',
1474     inverse: false,
1475     form: false,
1476     
1477     getAutoCreate : function(){
1478         var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
1479         
1480         cfg = {
1481             tag : 'ul',
1482             cls: 'nav navbar-nav' 
1483         }
1484         
1485         if (this.parent().sidebar === true) {
1486             cfg = {
1487                 tag: 'ul',
1488                 cls: 'dashboard-menu'
1489             }
1490             
1491             return cfg;
1492         }
1493         
1494         if (this.form === true) {
1495             cfg = {
1496                 tag: 'form',
1497                 cls: 'navbar-form'
1498             }
1499             
1500             if (this.align === 'right') {
1501                 cfg.cls += ' navbar-right';
1502             } else {
1503                 cfg.cls += ' navbar-left';
1504             }
1505         }
1506         
1507         
1508         if (this.align === 'right') {
1509             cfg.cls += ' navbar-right';
1510         }
1511         
1512         if (this.inverse) {
1513             cfg.cls += ' navbar-inverse';
1514             
1515         }
1516         
1517         
1518         return cfg;
1519     }
1520    
1521 });
1522
1523  
1524
1525  /*
1526  * - LGPL
1527  *
1528  * row
1529  * 
1530  */
1531 /**
1532  * @class Roo.bootstrap.Navbar.Button
1533  * @extends Roo.bootstrap.Component
1534  * Bootstrap Navbar.Button class
1535  * @cfg {String} href  link to
1536  * @cfg {String} html content of button
1537     
1538  * @constructor
1539  * Create a new Navbar Button
1540  * @param {Object} config The config object
1541  */
1542
1543
1544 Roo.bootstrap.Navbar.Button = function(config){
1545     Roo.bootstrap.Navbar.Button.superclass.constructor.call(this, config);
1546 };
1547
1548 Roo.extend(Roo.bootstrap.Navbar.Button, Roo.bootstrap.Component,  {
1549     
1550     href : false,
1551     html : false,
1552     
1553     autoCreate : {
1554         cls: 'btn',
1555         tag : 'button',
1556         html: 'hello'
1557     },
1558     
1559     getAutoCreate : function(){
1560         
1561         var cfg = {
1562             cls: 'btn',
1563             tag : 'button',
1564             html: 'hello',
1565             cn : []
1566             
1567         } ;
1568         cfg.cn.push({
1569             html : this.html || ''
1570             //href : this.
1571              //       )
1572         });
1573         cfg.cn.push({
1574             tag: 'span',
1575             cls : 'carat'
1576         });
1577         
1578         return cfg;
1579     }
1580    
1581 });
1582
1583  
1584
1585  /*
1586  * - LGPL
1587  *
1588  * row
1589  * 
1590  */
1591
1592 /**
1593  * @class Roo.bootstrap.Navbar.Item
1594  * @extends Roo.bootstrap.Component
1595  * Bootstrap Navbar.Button class
1596  * @cfg {String} href  link to
1597  * @cfg {String} html content of button
1598  * @cfg {String} badge text inside badge
1599  * @cfg {String} glyphicon name of glyphicon
1600   
1601  * @constructor
1602  * Create a new Navbar Button
1603  * @param {Object} config The config object
1604  */
1605 Roo.bootstrap.Navbar.Item = function(config){
1606     Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
1607 };
1608
1609 Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component,  {
1610     
1611     href: false,
1612     html: '',
1613     badge: '',
1614     icon: false,
1615     glyphicon: false,
1616     
1617     getAutoCreate : function(){
1618         
1619         var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
1620         
1621         if (this.parent().parent().sidebar === true) {
1622             cfg = {
1623                 tag: 'li',
1624                 cls: '',
1625                 cn: [
1626                     {
1627                         tag: 'p',
1628                         cls: ''
1629                     }
1630                 ]
1631             }
1632             
1633             if (this.html) {
1634                 cfg.cn[0].html = this.html;
1635             }
1636             
1637             if (this.active) {
1638                 this.cls += ' active';
1639             }
1640             
1641             if (this.menu) {
1642                 cfg.cn[0].cls += ' dropdown-toggle';
1643                 cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
1644             }
1645             
1646             if (this.href) {
1647                 cfg.cn[0].tag = 'a',
1648                 cfg.cn[0].href = this.href;
1649             }
1650             
1651             if (this.glyphicon) {
1652                 cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
1653             }
1654             
1655             return cfg;
1656         }
1657         
1658         cfg = {
1659             tag: 'li'
1660         }
1661         cfg.cn = [
1662             {
1663                 tag: 'p',
1664                 html: 'Text'
1665             }
1666         ];
1667         
1668         if (this.glyphicon) {
1669             if(cfg.html){cfg.html = ' ' + this.html};
1670             cfg.cn=[
1671                 {
1672                     tag: 'span',
1673                     cls: 'glyphicon glyphicon-' + this.glyphicon
1674                 }
1675             ];
1676         }
1677         
1678         cfg.cn[0].html = this.html || cfg.cn[0].html ;
1679         if (this.menu) {
1680             cfg.cn[0].tag='a';
1681             cfg.cn[0].href='#';
1682             cfg.cn[0].html += " <span class='caret'></span>";
1683         //}else if (!this.href) {
1684         //    cfg.cn[0].tag='p';
1685         //    cfg.cn[0].cls='navbar-text';
1686         } else {
1687             cfg.cn[0].tag='a';
1688             cfg.cn[0].href=this.href||'#';
1689             cfg.cn[0].html=this.html;
1690         }
1691         
1692         if (this.badge !== '') {
1693             
1694             cfg.cn[0].cn=[
1695                 cfg.cn[0].html + ' ',
1696                 {
1697                     tag: 'span',
1698                     cls: 'badge',
1699                     html: this.badge
1700                 }
1701             ];
1702             cfg.cn[0].html=''
1703         }
1704          
1705         
1706         return cfg;
1707     },
1708     initEvents: function() {
1709        // Roo.log('init events?');
1710        // Roo.log(this.el.dom);
1711         this.el.select('a',true).on('click',
1712                 function(e) {
1713                     this.fireEvent('click', this);
1714                 },
1715                 this
1716         );
1717     }
1718    
1719 });
1720  
1721
1722  /*
1723  * - LGPL
1724  *
1725  * row
1726  * 
1727  */
1728
1729 /**
1730  * @class Roo.bootstrap.Row
1731  * @extends Roo.bootstrap.Component
1732  * Bootstrap Row class (contains columns...)
1733  * 
1734  * @constructor
1735  * Create a new Row
1736  * @param {Object} config The config object
1737  */
1738
1739 Roo.bootstrap.Row = function(config){
1740     Roo.bootstrap.Row.superclass.constructor.call(this, config);
1741 };
1742
1743 Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component,  {
1744     
1745     autoCreate: {
1746         cls: 'row clearfix'
1747     }
1748     
1749     
1750 });
1751
1752  
1753
1754  /*
1755  * - LGPL
1756  *
1757  * element
1758  * 
1759  */
1760
1761 /**
1762  * @class Roo.bootstrap.Element
1763  * @extends Roo.bootstrap.Component
1764  * Bootstrap Element class
1765  * @cfg {String} html contents of the element
1766  * @cfg {String} tag tag of the element
1767  * @cfg {String} cls class of the element
1768  * 
1769  * @constructor
1770  * Create a new Element
1771  * @param {Object} config The config object
1772  */
1773
1774 Roo.bootstrap.Element = function(config){
1775     Roo.bootstrap.Element.superclass.constructor.call(this, config);
1776 };
1777
1778 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component,  {
1779     
1780     tag: 'div',
1781     cls: '',
1782     html: '',
1783     
1784     
1785     
1786     getAutoCreate : function(){
1787         var cfg = Roo.apply({}, Roo.bootstrap.Element.superclass.getAutoCreate.call(this));
1788         
1789         cfg = {
1790             tag: this.tag,
1791             cls: '',
1792             html: this.html
1793         }
1794         
1795         return cfg;
1796     }
1797    
1798 });
1799
1800  
1801
1802  /*
1803  * - LGPL
1804  *
1805  * pagination
1806  * 
1807  */
1808
1809 /**
1810  * @class Roo.bootstrap.Pagination
1811  * @extends Roo.bootstrap.Component
1812  * Bootstrap Pagination class
1813  * @cfg {String} size xs | sm | md | lg
1814  * @cfg {Boolean} inverse false | true
1815  * @cfg {Number} from pagination starting number
1816  * @cfg {Number} to pagination ending number
1817  * @cfg {String} align empty or left | right
1818  * @cfg {Number} active active page number
1819  * 
1820  * @constructor
1821  * Create a new Pagination
1822  * @param {Object} config The config object
1823  */
1824
1825 Roo.bootstrap.Pagination = function(config){
1826     Roo.bootstrap.Pagination.superclass.constructor.call(this, config);
1827 };
1828
1829 Roo.extend(Roo.bootstrap.Pagination, Roo.bootstrap.Component,  {
1830     
1831     cls: false,
1832     size: false,
1833     inverse: false,
1834     from: 1,
1835     to: 4,
1836     align: false,
1837     active: 1,
1838     
1839     getAutoCreate : function(){
1840         cfg = {
1841             tag: 'ul',
1842                 cls: 'pagination',
1843                 cn: []
1844         };
1845         if (this.inverse) {
1846             cfg.cls += ' inverse';
1847         }
1848         if (this.html) {
1849             cfg.html=this.html;
1850         }
1851         if (this.cls) {
1852             cfg.cls=this.cls;
1853         }
1854         cfg.cn[0]={
1855             tag: 'li',
1856             cn: [
1857                 {
1858                     tag: 'a',
1859                     href:'#',
1860                     html: '&laquo;'
1861                 }
1862             ]
1863         };
1864         var from=this.from>0?this.from:1;
1865         var to=this.to-from<=10?this.to:from+10;
1866         var active=this.active>=from&&this.active<=to?this.active:null;
1867         for (var i=from;i<=to;i++) {
1868             cfg.cn.push(
1869                 {
1870                     tag: 'li',
1871                     cls: active===i?'active':'',
1872                     cn: [
1873                         {
1874                             tag: 'a',
1875                             href: '#',
1876                             html: i
1877                         }
1878                     ]
1879                 }
1880             );
1881         }
1882         
1883         cfg.cn.push(
1884             {
1885                 tag: 'li',
1886                 cn: [
1887                     {
1888                        tag: 'a',
1889                        href: '#',
1890                        html: '&raquo;'
1891                     }
1892                 ]
1893             }
1894         );
1895         
1896         return cfg;
1897     }
1898    
1899 });
1900
1901  
1902
1903  /*
1904  * - LGPL
1905  *
1906  * slider
1907  * 
1908  */
1909
1910
1911 /**
1912  * @class Roo.bootstrap.Slider
1913  * @extends Roo.bootstrap.Component
1914  * Bootstrap Slider class
1915  *    
1916  * @constructor
1917  * Create a new Slider
1918  * @param {Object} config The config object
1919  */
1920
1921 Roo.bootstrap.Slider = function(config){
1922     Roo.bootstrap.Slider.superclass.constructor.call(this, config);
1923 };
1924
1925 Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component,  {
1926     
1927     getAutoCreate : function(){
1928         
1929         var cfg = {
1930             tag: 'div',
1931             cls: 'slider slider-sample1 vertical-handler ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all',
1932             cn: [
1933                 {
1934                     tag: 'a',
1935                     cls: 'ui-slider-handle ui-state-default ui-corner-all'
1936                 }
1937             ]
1938         }
1939         
1940         return cfg;
1941     }
1942    
1943 });
1944
1945  /*
1946  * - LGPL
1947  *
1948  * table
1949  * 
1950  */
1951
1952 /**
1953  * @class Roo.bootstrap.Table
1954  * @extends Roo.bootstrap.Component
1955  * Bootstrap Table class
1956  * 
1957  * @constructor
1958  * Create a new Table
1959  * @param {Object} config The config object
1960  */
1961
1962 Roo.bootstrap.Table = function(config){
1963     Roo.bootstrap.Table.superclass.constructor.call(this, config);
1964 };
1965
1966 Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
1967     
1968     html: false,
1969     cls: false,
1970     
1971     getAutoCreate : function(){
1972         var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
1973         
1974         cfg = {
1975             tag: 'table',
1976             cn: [
1977                 {
1978                     tag: 'tbody'
1979                 }
1980             ]
1981         }
1982         if (this.html) {
1983             cfg.html=this.html
1984         }
1985         if (this.cls) {
1986             cfg.cls=this.cls
1987         }
1988         
1989         return cfg;
1990     }
1991    
1992 });
1993
1994  
1995
1996  /*
1997  * - LGPL
1998  *
1999  * table cell
2000  * 
2001  */
2002
2003 /**
2004  * @class Roo.bootstrap.TableCell
2005  * @extends Roo.bootstrap.Component
2006  * Bootstrap TableCell class
2007  * 
2008  * @constructor
2009  * Create a new TableCell
2010  * @param {Object} config The config object
2011  */
2012
2013 Roo.bootstrap.TableCell = function(config){
2014     Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
2015 };
2016
2017 Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component,  {
2018     
2019     getAutoCreate : function(){
2020         var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
2021         
2022         cfg = {
2023             tag: 'td'
2024         }
2025         if (this.html) {
2026             cfg.html=this.html
2027         }
2028         if (this.cls) {
2029             cfg.cls=this.cls
2030         }
2031         
2032         return cfg;
2033     }
2034    
2035 });
2036
2037  
2038
2039  /*
2040  * - LGPL
2041  *
2042  * table row
2043  * 
2044  */
2045
2046 /**
2047  * @class Roo.bootstrap.TableRow
2048  * @extends Roo.bootstrap.Component
2049  * Bootstrap TableRow class
2050  * 
2051  * @constructor
2052  * Create a new TableRow
2053  * @param {Object} config The config object
2054  */
2055
2056 Roo.bootstrap.TableRow = function(config){
2057     Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
2058 };
2059
2060 Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component,  {
2061     
2062     getAutoCreate : function(){
2063         var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
2064         
2065         cfg = {
2066             tag: 'tr'
2067         }
2068         
2069         return cfg;
2070     }
2071    
2072 });
2073
2074  
2075
2076  /*
2077  * Based on:
2078  * Ext JS Library 1.1.1
2079  * Copyright(c) 2006-2007, Ext JS, LLC.
2080  *
2081  * Originally Released Under LGPL - original licence link has changed is not relivant.
2082  *
2083  * Fork - LGPL
2084  * <script type="text/javascript">
2085  */
2086
2087 // as we use this in bootstrap.
2088 Roo.namespace('Roo.form');
2089  /**
2090  * @class Roo.form.Action
2091  * Internal Class used to handle form actions
2092  * @constructor
2093  * @param {Roo.form.BasicForm} el The form element or its id
2094  * @param {Object} config Configuration options
2095  */
2096
2097  
2098  
2099 // define the action interface
2100 Roo.form.Action = function(form, options){
2101     this.form = form;
2102     this.options = options || {};
2103 };
2104 /**
2105  * Client Validation Failed
2106  * @const 
2107  */
2108 Roo.form.Action.CLIENT_INVALID = 'client';
2109 /**
2110  * Server Validation Failed
2111  * @const 
2112  */
2113 Roo.form.Action.SERVER_INVALID = 'server';
2114  /**
2115  * Connect to Server Failed
2116  * @const 
2117  */
2118 Roo.form.Action.CONNECT_FAILURE = 'connect';
2119 /**
2120  * Reading Data from Server Failed
2121  * @const 
2122  */
2123 Roo.form.Action.LOAD_FAILURE = 'load';
2124
2125 Roo.form.Action.prototype = {
2126     type : 'default',
2127     failureType : undefined,
2128     response : undefined,
2129     result : undefined,
2130
2131     // interface method
2132     run : function(options){
2133
2134     },
2135
2136     // interface method
2137     success : function(response){
2138
2139     },
2140
2141     // interface method
2142     handleResponse : function(response){
2143
2144     },
2145
2146     // default connection failure
2147     failure : function(response){
2148         
2149         this.response = response;
2150         this.failureType = Roo.form.Action.CONNECT_FAILURE;
2151         this.form.afterAction(this, false);
2152     },
2153
2154     processResponse : function(response){
2155         this.response = response;
2156         if(!response.responseText){
2157             return true;
2158         }
2159         this.result = this.handleResponse(response);
2160         return this.result;
2161     },
2162
2163     // utility functions used internally
2164     getUrl : function(appendParams){
2165         var url = this.options.url || this.form.url || this.form.el.dom.action;
2166         if(appendParams){
2167             var p = this.getParams();
2168             if(p){
2169                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
2170             }
2171         }
2172         return url;
2173     },
2174
2175     getMethod : function(){
2176         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
2177     },
2178
2179     getParams : function(){
2180         var bp = this.form.baseParams;
2181         var p = this.options.params;
2182         if(p){
2183             if(typeof p == "object"){
2184                 p = Roo.urlEncode(Roo.applyIf(p, bp));
2185             }else if(typeof p == 'string' && bp){
2186                 p += '&' + Roo.urlEncode(bp);
2187             }
2188         }else if(bp){
2189             p = Roo.urlEncode(bp);
2190         }
2191         return p;
2192     },
2193
2194     createCallback : function(){
2195         return {
2196             success: this.success,
2197             failure: this.failure,
2198             scope: this,
2199             timeout: (this.form.timeout*1000),
2200             upload: this.form.fileUpload ? this.success : undefined
2201         };
2202     }
2203 };
2204
2205 Roo.form.Action.Submit = function(form, options){
2206     Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
2207 };
2208
2209 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
2210     type : 'submit',
2211
2212     haveProgress : false,
2213     uploadComplete : false,
2214     
2215     // uploadProgress indicator.
2216     uploadProgress : function()
2217     {
2218         if (!this.form.progressUrl) {
2219             return;
2220         }
2221         
2222         if (!this.haveProgress) {
2223             Roo.MessageBox.progress("Uploading", "Uploading");
2224         }
2225         if (this.uploadComplete) {
2226            Roo.MessageBox.hide();
2227            return;
2228         }
2229         
2230         this.haveProgress = true;
2231    
2232         var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
2233         
2234         var c = new Roo.data.Connection();
2235         c.request({
2236             url : this.form.progressUrl,
2237             params: {
2238                 id : uid
2239             },
2240             method: 'GET',
2241             success : function(req){
2242                //console.log(data);
2243                 var rdata = false;
2244                 var edata;
2245                 try  {
2246                    rdata = Roo.decode(req.responseText)
2247                 } catch (e) {
2248                     Roo.log("Invalid data from server..");
2249                     Roo.log(edata);
2250                     return;
2251                 }
2252                 if (!rdata || !rdata.success) {
2253                     Roo.log(rdata);
2254                     Roo.MessageBox.alert(Roo.encode(rdata));
2255                     return;
2256                 }
2257                 var data = rdata.data;
2258                 
2259                 if (this.uploadComplete) {
2260                    Roo.MessageBox.hide();
2261                    return;
2262                 }
2263                    
2264                 if (data){
2265                     Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
2266                        Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
2267                     );
2268                 }
2269                 this.uploadProgress.defer(2000,this);
2270             },
2271        
2272             failure: function(data) {
2273                 Roo.log('progress url failed ');
2274                 Roo.log(data);
2275             },
2276             scope : this
2277         });
2278            
2279     },
2280     
2281     
2282     run : function()
2283     {
2284         // run get Values on the form, so it syncs any secondary forms.
2285         this.form.getValues();
2286         
2287         var o = this.options;
2288         var method = this.getMethod();
2289         var isPost = method == 'POST';
2290         if(o.clientValidation === false || this.form.isValid()){
2291             
2292             if (this.form.progressUrl) {
2293                 this.form.findField('UPLOAD_IDENTIFIER').setValue(
2294                     (new Date() * 1) + '' + Math.random());
2295                     
2296             } 
2297             
2298             
2299             Roo.Ajax.request(Roo.apply(this.createCallback(), {
2300                 form:this.form.el.dom,
2301                 url:this.getUrl(!isPost),
2302                 method: method,
2303                 params:isPost ? this.getParams() : null,
2304                 isUpload: this.form.fileUpload
2305             }));
2306             
2307             this.uploadProgress();
2308
2309         }else if (o.clientValidation !== false){ // client validation failed
2310             this.failureType = Roo.form.Action.CLIENT_INVALID;
2311             this.form.afterAction(this, false);
2312         }
2313     },
2314
2315     success : function(response)
2316     {
2317         this.uploadComplete= true;
2318         if (this.haveProgress) {
2319             Roo.MessageBox.hide();
2320         }
2321         
2322         
2323         var result = this.processResponse(response);
2324         if(result === true || result.success){
2325             this.form.afterAction(this, true);
2326             return;
2327         }
2328         if(result.errors){
2329             this.form.markInvalid(result.errors);
2330             this.failureType = Roo.form.Action.SERVER_INVALID;
2331         }
2332         this.form.afterAction(this, false);
2333     },
2334     failure : function(response)
2335     {
2336         this.uploadComplete= true;
2337         if (this.haveProgress) {
2338             Roo.MessageBox.hide();
2339         }
2340         
2341         this.response = response;
2342         this.failureType = Roo.form.Action.CONNECT_FAILURE;
2343         this.form.afterAction(this, false);
2344     },
2345     
2346     handleResponse : function(response){
2347         if(this.form.errorReader){
2348             var rs = this.form.errorReader.read(response);
2349             var errors = [];
2350             if(rs.records){
2351                 for(var i = 0, len = rs.records.length; i < len; i++) {
2352                     var r = rs.records[i];
2353                     errors[i] = r.data;
2354                 }
2355             }
2356             if(errors.length < 1){
2357                 errors = null;
2358             }
2359             return {
2360                 success : rs.success,
2361                 errors : errors
2362             };
2363         }
2364         var ret = false;
2365         try {
2366             ret = Roo.decode(response.responseText);
2367         } catch (e) {
2368             ret = {
2369                 success: false,
2370                 errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
2371                 errors : []
2372             };
2373         }
2374         return ret;
2375         
2376     }
2377 });
2378
2379
2380 Roo.form.Action.Load = function(form, options){
2381     Roo.form.Action.Load.superclass.constructor.call(this, form, options);
2382     this.reader = this.form.reader;
2383 };
2384
2385 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
2386     type : 'load',
2387
2388     run : function(){
2389         
2390         Roo.Ajax.request(Roo.apply(
2391                 this.createCallback(), {
2392                     method:this.getMethod(),
2393                     url:this.getUrl(false),
2394                     params:this.getParams()
2395         }));
2396     },
2397
2398     success : function(response){
2399         
2400         var result = this.processResponse(response);
2401         if(result === true || !result.success || !result.data){
2402             this.failureType = Roo.form.Action.LOAD_FAILURE;
2403             this.form.afterAction(this, false);
2404             return;
2405         }
2406         this.form.clearInvalid();
2407         this.form.setValues(result.data);
2408         this.form.afterAction(this, true);
2409     },
2410
2411     handleResponse : function(response){
2412         if(this.form.reader){
2413             var rs = this.form.reader.read(response);
2414             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
2415             return {
2416                 success : rs.success,
2417                 data : data
2418             };
2419         }
2420         return Roo.decode(response.responseText);
2421     }
2422 });
2423
2424 Roo.form.Action.ACTION_TYPES = {
2425     'load' : Roo.form.Action.Load,
2426     'submit' : Roo.form.Action.Submit
2427 };/*
2428  * - LGPL
2429  *
2430  * form
2431  * 
2432  */
2433
2434 /**
2435  * @class Roo.bootstrap.Form
2436  * @extends Roo.bootstrap.Component
2437  * Bootstrap Form class
2438  * @cfg {String} method  GET | POST (default POST)
2439  * @cfg {String} labelAlign top | left (default top)
2440   * @cfg {String} align left  | right - for navbars
2441
2442  * 
2443  * @constructor
2444  * Create a new Form
2445  * @param {Object} config The config object
2446  */
2447
2448
2449 Roo.bootstrap.Form = function(config){
2450     Roo.bootstrap.Form.superclass.constructor.call(this, config);
2451     this.addEvents({
2452         /**
2453          * @event clientvalidation
2454          * If the monitorValid config option is true, this event fires repetitively to notify of valid state
2455          * @param {Form} this
2456          * @param {Boolean} valid true if the form has passed client-side validation
2457          */
2458         clientvalidation: true,
2459         /**
2460          * @event beforeaction
2461          * Fires before any action is performed. Return false to cancel the action.
2462          * @param {Form} this
2463          * @param {Action} action The action to be performed
2464          */
2465         beforeaction: true,
2466         /**
2467          * @event actionfailed
2468          * Fires when an action fails.
2469          * @param {Form} this
2470          * @param {Action} action The action that failed
2471          */
2472         actionfailed : true,
2473         /**
2474          * @event actioncomplete
2475          * Fires when an action is completed.
2476          * @param {Form} this
2477          * @param {Action} action The action that completed
2478          */
2479         actioncomplete : true
2480     });
2481     
2482 };
2483
2484 Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
2485       
2486      /**
2487      * @cfg {String} method
2488      * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
2489      */
2490     method : 'POST',
2491     /**
2492      * @cfg {String} url
2493      * The URL to use for form actions if one isn't supplied in the action options.
2494      */
2495     /**
2496      * @cfg {Boolean} fileUpload
2497      * Set to true if this form is a file upload.
2498      */
2499      
2500     /**
2501      * @cfg {Object} baseParams
2502      * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
2503      */
2504       
2505     /**
2506      * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
2507      */
2508     timeout: 30,
2509     /**
2510      * @cfg {Sting} align (left|right) for navbar forms
2511      */
2512     align : 'left',
2513
2514     // private
2515     activeAction : null,
2516  
2517     /**
2518      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2519      * element by passing it or its id or mask the form itself by passing in true.
2520      * @type Mixed
2521      */
2522     waitMsgTarget : false,
2523     
2524      
2525     
2526     /**
2527      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2528      * element by passing it or its id or mask the form itself by passing in true.
2529      * @type Mixed
2530      */
2531     
2532     getAutoCreate : function(){
2533         
2534         var cfg = {
2535             tag: 'form',
2536             method : this.method || 'POST',
2537             id : this.id || Roo.id(),
2538             cls : ''
2539         }
2540         if (this.parent().xtype == 'Navbar') {
2541             cfg.cls = 'navbar-form navbar-' + this.align;
2542             
2543         }
2544         
2545         if (this.labelAlign == 'left' ) {
2546             cfg.cls += ' form-horizontal';
2547         }
2548         
2549         
2550         return cfg;
2551     },
2552     initEvents : function()
2553     {
2554         this.el.on('submit', this.onSubmit, this);
2555         
2556         
2557     },
2558     // private
2559     onSubmit : function(e){
2560         e.stopEvent();
2561     },
2562     
2563      /**
2564      * Returns true if client-side validation on the form is successful.
2565      * @return Boolean
2566      */
2567     isValid : function(){
2568         var items = this.getItems();
2569         var valid = true;
2570         items.each(function(f){
2571            if(!f.validate()){
2572                valid = false;
2573                
2574            }
2575         });
2576         return valid;
2577     },
2578     /**
2579      * Returns true if any fields in this form have changed since their original load.
2580      * @return Boolean
2581      */
2582     isDirty : function(){
2583         var dirty = false;
2584         var items = this.getItems();
2585         items.each(function(f){
2586            if(f.isDirty()){
2587                dirty = true;
2588                return false;
2589            }
2590            return true;
2591         });
2592         return dirty;
2593     },
2594      /**
2595      * Performs a predefined action (submit or load) or custom actions you define on this form.
2596      * @param {String} actionName The name of the action type
2597      * @param {Object} options (optional) The options to pass to the action.  All of the config options listed
2598      * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
2599      * accept other config options):
2600      * <pre>
2601 Property          Type             Description
2602 ----------------  ---------------  ----------------------------------------------------------------------------------
2603 url               String           The url for the action (defaults to the form's url)
2604 method            String           The form method to use (defaults to the form's method, or POST if not defined)
2605 params            String/Object    The params to pass (defaults to the form's baseParams, or none if not defined)
2606 clientValidation  Boolean          Applies to submit only.  Pass true to call form.isValid() prior to posting to
2607                                    validate the form on the client (defaults to false)
2608      * </pre>
2609      * @return {BasicForm} this
2610      */
2611     doAction : function(action, options){
2612         if(typeof action == 'string'){
2613             action = new Roo.form.Action.ACTION_TYPES[action](this, options);
2614         }
2615         if(this.fireEvent('beforeaction', this, action) !== false){
2616             this.beforeAction(action);
2617             action.run.defer(100, action);
2618         }
2619         return this;
2620     },
2621     
2622     // private
2623     beforeAction : function(action){
2624         var o = action.options;
2625         
2626         // not really supported yet.. ??
2627         
2628         //if(this.waitMsgTarget === true){
2629             this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
2630         //}else if(this.waitMsgTarget){
2631         //    this.waitMsgTarget = Roo.get(this.waitMsgTarget);
2632         //    this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
2633         //}else {
2634         //    Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
2635        // }
2636          
2637     },
2638
2639     // private
2640     afterAction : function(action, success){
2641         this.activeAction = null;
2642         var o = action.options;
2643         
2644         //if(this.waitMsgTarget === true){
2645             this.el.unmask();
2646         //}else if(this.waitMsgTarget){
2647         //    this.waitMsgTarget.unmask();
2648         //}else{
2649         //    Roo.MessageBox.updateProgress(1);
2650         //    Roo.MessageBox.hide();
2651        // }
2652         // 
2653         if(success){
2654             if(o.reset){
2655                 this.reset();
2656             }
2657             Roo.callback(o.success, o.scope, [this, action]);
2658             this.fireEvent('actioncomplete', this, action);
2659             
2660         }else{
2661             
2662             // failure condition..
2663             // we have a scenario where updates need confirming.
2664             // eg. if a locking scenario exists..
2665             // we look for { errors : { needs_confirm : true }} in the response.
2666             if (
2667                 (typeof(action.result) != 'undefined')  &&
2668                 (typeof(action.result.errors) != 'undefined')  &&
2669                 (typeof(action.result.errors.needs_confirm) != 'undefined')
2670            ){
2671                 var _t = this;
2672                 Roo.log("not supported yet");
2673                  /*
2674                 
2675                 Roo.MessageBox.confirm(
2676                     "Change requires confirmation",
2677                     action.result.errorMsg,
2678                     function(r) {
2679                         if (r != 'yes') {
2680                             return;
2681                         }
2682                         _t.doAction('submit', { params :  { _submit_confirmed : 1 } }  );
2683                     }
2684                     
2685                 );
2686                 */
2687                 
2688                 
2689                 return;
2690             }
2691             
2692             Roo.callback(o.failure, o.scope, [this, action]);
2693             // show an error message if no failed handler is set..
2694             if (!this.hasListener('actionfailed')) {
2695                 Roo.log("need to add dialog support");
2696                 /*
2697                 Roo.MessageBox.alert("Error",
2698                     (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
2699                         action.result.errorMsg :
2700                         "Saving Failed, please check your entries or try again"
2701                 );
2702                 */
2703             }
2704             
2705             this.fireEvent('actionfailed', this, action);
2706         }
2707         
2708     },
2709     /**
2710      * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
2711      * @param {String} id The value to search for
2712      * @return Field
2713      */
2714     findField : function(id){
2715         var items = this.getItems();
2716         var field = items.get(id);
2717         if(!field){
2718              items.each(function(f){
2719                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
2720                     field = f;
2721                     return false;
2722                 }
2723                 return true;
2724             });
2725         }
2726         return field || null;
2727     },
2728      /**
2729      * Mark fields in this form invalid in bulk.
2730      * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
2731      * @return {BasicForm} this
2732      */
2733     markInvalid : function(errors){
2734         if(errors instanceof Array){
2735             for(var i = 0, len = errors.length; i < len; i++){
2736                 var fieldError = errors[i];
2737                 var f = this.findField(fieldError.id);
2738                 if(f){
2739                     f.markInvalid(fieldError.msg);
2740                 }
2741             }
2742         }else{
2743             var field, id;
2744             for(id in errors){
2745                 if(typeof errors[id] != 'function' && (field = this.findField(id))){
2746                     field.markInvalid(errors[id]);
2747                 }
2748             }
2749         }
2750         //Roo.each(this.childForms || [], function (f) {
2751         //    f.markInvalid(errors);
2752         //});
2753         
2754         return this;
2755     },
2756
2757     /**
2758      * Set values for fields in this form in bulk.
2759      * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
2760      * @return {BasicForm} this
2761      */
2762     setValues : function(values){
2763         if(values instanceof Array){ // array of objects
2764             for(var i = 0, len = values.length; i < len; i++){
2765                 var v = values[i];
2766                 var f = this.findField(v.id);
2767                 if(f){
2768                     f.setValue(v.value);
2769                     if(this.trackResetOnLoad){
2770                         f.originalValue = f.getValue();
2771                     }
2772                 }
2773             }
2774         }else{ // object hash
2775             var field, id;
2776             for(id in values){
2777                 if(typeof values[id] != 'function' && (field = this.findField(id))){
2778                     
2779                     if (field.setFromData && 
2780                         field.valueField && 
2781                         field.displayField &&
2782                         // combos' with local stores can 
2783                         // be queried via setValue()
2784                         // to set their value..
2785                         (field.store && !field.store.isLocal)
2786                         ) {
2787                         // it's a combo
2788                         var sd = { };
2789                         sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
2790                         sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
2791                         field.setFromData(sd);
2792                         
2793                     } else {
2794                         field.setValue(values[id]);
2795                     }
2796                     
2797                     
2798                     if(this.trackResetOnLoad){
2799                         field.originalValue = field.getValue();
2800                     }
2801                 }
2802             }
2803         }
2804          
2805         //Roo.each(this.childForms || [], function (f) {
2806         //    f.setValues(values);
2807         //});
2808                 
2809         return this;
2810     },
2811
2812     /**
2813      * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
2814      * they are returned as an array.
2815      * @param {Boolean} asString
2816      * @return {Object}
2817      */
2818     getValues : function(asString){
2819         //if (this.childForms) {
2820             // copy values from the child forms
2821         //    Roo.each(this.childForms, function (f) {
2822         //        this.setValues(f.getValues());
2823         //    }, this);
2824         //}
2825         
2826         
2827         
2828         var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
2829         if(asString === true){
2830             return fs;
2831         }
2832         return Roo.urlDecode(fs);
2833     },
2834     
2835     /**
2836      * Returns the fields in this form as an object with key/value pairs. 
2837      * This differs from getValues as it calls getValue on each child item, rather than using dom data.
2838      * @return {Object}
2839      */
2840     getFieldValues : function(with_hidden)
2841     {
2842         var items = this.getItems();
2843         var ret = {};
2844         items.each(function(f){
2845             if (!f.getName()) {
2846                 return;
2847             }
2848             var v = f.getValue();
2849             if (f.inputType =='radio') {
2850                 if (typeof(ret[f.getName()]) == 'undefined') {
2851                     ret[f.getName()] = ''; // empty..
2852                 }
2853                 
2854                 if (!f.el.dom.checked) {
2855                     return;
2856                     
2857                 }
2858                 v = f.el.dom.value;
2859                 
2860             }
2861             
2862             // not sure if this supported any more..
2863             if ((typeof(v) == 'object') && f.getRawValue) {
2864                 v = f.getRawValue() ; // dates..
2865             }
2866             // combo boxes where name != hiddenName...
2867             if (f.name != f.getName()) {
2868                 ret[f.name] = f.getRawValue();
2869             }
2870             ret[f.getName()] = v;
2871         });
2872         
2873         return ret;
2874     },
2875
2876     /**
2877      * Clears all invalid messages in this form.
2878      * @return {BasicForm} this
2879      */
2880     clearInvalid : function(){
2881         var items = this.getItems();
2882         
2883         items.each(function(f){
2884            f.clearInvalid();
2885         });
2886         
2887         
2888         
2889         return this;
2890     },
2891
2892     /**
2893      * Resets this form.
2894      * @return {BasicForm} this
2895      */
2896     reset : function(){
2897         var items = this.getItems();
2898         items.each(function(f){
2899             f.reset();
2900         });
2901         
2902         Roo.each(this.childForms || [], function (f) {
2903             f.reset();
2904         });
2905        
2906         
2907         return this;
2908     },
2909     getItems : function()
2910     {
2911         var r=new Roo.util.MixedCollection(false, function(o){
2912             return o.id || (o.id = Roo.id());
2913         });
2914         var iter = function(el) {
2915             if (el.inputEl) {
2916                 r.add(el);
2917             }
2918             if (!el.items) {
2919                 return;
2920             }
2921             Roo.each(el.items,function(e) {
2922                 iter(e);
2923             });
2924             
2925             
2926         };
2927         iter(this);
2928         return r;
2929         
2930         
2931         
2932         
2933     }
2934     
2935 });
2936
2937  
2938 /*
2939  * Based on:
2940  * Ext JS Library 1.1.1
2941  * Copyright(c) 2006-2007, Ext JS, LLC.
2942  *
2943  * Originally Released Under LGPL - original licence link has changed is not relivant.
2944  *
2945  * Fork - LGPL
2946  * <script type="text/javascript">
2947  */
2948 /**
2949  * @class Roo.form.VTypes
2950  * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
2951  * @singleton
2952  */
2953 Roo.form.VTypes = function(){
2954     // closure these in so they are only created once.
2955     var alpha = /^[a-zA-Z_]+$/;
2956     var alphanum = /^[a-zA-Z0-9_]+$/;
2957     var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
2958     var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
2959
2960     // All these messages and functions are configurable
2961     return {
2962         /**
2963          * The function used to validate email addresses
2964          * @param {String} value The email address
2965          */
2966         'email' : function(v){
2967             return email.test(v);
2968         },
2969         /**
2970          * The error text to display when the email validation function returns false
2971          * @type String
2972          */
2973         'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
2974         /**
2975          * The keystroke filter mask to be applied on email input
2976          * @type RegExp
2977          */
2978         'emailMask' : /[a-z0-9_\.\-@]/i,
2979
2980         /**
2981          * The function used to validate URLs
2982          * @param {String} value The URL
2983          */
2984         'url' : function(v){
2985             return url.test(v);
2986         },
2987         /**
2988          * The error text to display when the url validation function returns false
2989          * @type String
2990          */
2991         'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
2992         
2993         /**
2994          * The function used to validate alpha values
2995          * @param {String} value The value
2996          */
2997         'alpha' : function(v){
2998             return alpha.test(v);
2999         },
3000         /**
3001          * The error text to display when the alpha validation function returns false
3002          * @type String
3003          */
3004         'alphaText' : 'This field should only contain letters and _',
3005         /**
3006          * The keystroke filter mask to be applied on alpha input
3007          * @type RegExp
3008          */
3009         'alphaMask' : /[a-z_]/i,
3010
3011         /**
3012          * The function used to validate alphanumeric values
3013          * @param {String} value The value
3014          */
3015         'alphanum' : function(v){
3016             return alphanum.test(v);
3017         },
3018         /**
3019          * The error text to display when the alphanumeric validation function returns false
3020          * @type String
3021          */
3022         'alphanumText' : 'This field should only contain letters, numbers and _',
3023         /**
3024          * The keystroke filter mask to be applied on alphanumeric input
3025          * @type RegExp
3026          */
3027         'alphanumMask' : /[a-z0-9_]/i
3028     };
3029 }();/*
3030  * - LGPL
3031  *
3032  * Input
3033  * 
3034  */
3035
3036 /**
3037  * @class Roo.bootstrap.Input
3038  * @extends Roo.bootstrap.Component
3039  * Bootstrap Input class
3040  * @cfg {Boolean} disabled is it disabled
3041  * @cfg {String} fieldLabel - the label associated
3042  * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
3043  * @cfg {String} name name of the input
3044  * @cfg {string} fieldLabel - the label associated
3045  * @cfg {string}  inputType - input / file submit ...
3046  * @cfg {string} placeholder - placeholder to put in text.
3047  * @cfg {string}  before - input group add on before
3048  * @cfg {string} after - input group add on after
3049  * @cfg {string} size - (lg|sm) or leave empty..
3050  * 
3051  * 
3052  * @constructor
3053  * Create a new Input
3054  * @param {Object} config The config object
3055  */
3056
3057 Roo.bootstrap.Input = function(config){
3058     Roo.bootstrap.Input.superclass.constructor.call(this, config);
3059    
3060         this.addEvents({
3061             /**
3062              * @event focus
3063              * Fires when this field receives input focus.
3064              * @param {Roo.form.Field} this
3065              */
3066             focus : true,
3067             /**
3068              * @event blur
3069              * Fires when this field loses input focus.
3070              * @param {Roo.form.Field} this
3071              */
3072             blur : true,
3073             /**
3074              * @event specialkey
3075              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
3076              * {@link Roo.EventObject#getKey} to determine which key was pressed.
3077              * @param {Roo.form.Field} this
3078              * @param {Roo.EventObject} e The event object
3079              */
3080             specialkey : true,
3081             /**
3082              * @event change
3083              * Fires just before the field blurs if the field value has changed.
3084              * @param {Roo.form.Field} this
3085              * @param {Mixed} newValue The new value
3086              * @param {Mixed} oldValue The original value
3087              */
3088             change : true,
3089             /**
3090              * @event invalid
3091              * Fires after the field has been marked as invalid.
3092              * @param {Roo.form.Field} this
3093              * @param {String} msg The validation message
3094              */
3095             invalid : true,
3096             /**
3097              * @event valid
3098              * Fires after the field has been validated with no errors.
3099              * @param {Roo.form.Field} this
3100              */
3101             valid : true,
3102              /**
3103              * @event keyup
3104              * Fires after the key up
3105              * @param {Roo.form.Field} this
3106              * @param {Roo.EventObject}  e The event Object
3107              */
3108             keyup : true
3109         });
3110 };
3111
3112 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
3113      /**
3114      * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
3115       automatic validation (defaults to "keyup").
3116      */
3117     validationEvent : "keyup",
3118      /**
3119      * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
3120      */
3121     validateOnBlur : true,
3122     /**
3123      * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
3124      */
3125     validationDelay : 250,
3126      /**
3127      * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
3128      */
3129     focusClass : "x-form-focus",  // not needed???
3130     
3131        
3132     /**
3133      * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
3134      */
3135     invalidClass : "has-error",
3136     
3137     /**
3138      * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
3139      */
3140     selectOnFocus : false,
3141     
3142      /**
3143      * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
3144      */
3145     maskRe : null,
3146        /**
3147      * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
3148      */
3149     vtype : null,
3150     
3151       /**
3152      * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
3153      */
3154     disableKeyFilter : false,
3155     
3156        /**
3157      * @cfg {Boolean} disabled True to disable the field (defaults to false).
3158      */
3159     disabled : false,
3160      /**
3161      * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
3162      */
3163     allowBlank : true,
3164     /**
3165      * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
3166      */
3167     blankText : "This field is required",
3168     
3169      /**
3170      * @cfg {Number} minLength Minimum input field length required (defaults to 0)
3171      */
3172     minLength : 0,
3173     /**
3174      * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
3175      */
3176     maxLength : Number.MAX_VALUE,
3177     /**
3178      * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
3179      */
3180     minLengthText : "The minimum length for this field is {0}",
3181     /**
3182      * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
3183      */
3184     maxLengthText : "The maximum length for this field is {0}",
3185   
3186     
3187     /**
3188      * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
3189      * If available, this function will be called only after the basic validators all return true, and will be passed the
3190      * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
3191      */
3192     validator : null,
3193     /**
3194      * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
3195      * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
3196      * current field value.  If the test fails, the field will be marked invalid using {@link #regexText}.
3197      */
3198     regex : null,
3199     /**
3200      * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
3201      */
3202     regexText : "",
3203     
3204     
3205     
3206     fieldLabel : '',
3207     inputType : 'text',
3208     
3209     name : false,
3210     placeholder: false,
3211     before : false,
3212     after : false,
3213     size : false,
3214     // private
3215     hasFocus : false,
3216     preventMark: false,
3217     isFormField : true,
3218     
3219     getAutoCreate : function(){
3220         
3221         var parent = this.parent();
3222         
3223         var align = parent.labelAlign;
3224         
3225         var id = Roo.id();
3226         
3227         var cfg = {
3228             cls: 'form-group' //input-group
3229         };
3230         
3231         var input =  {
3232             tag: 'input',
3233             id : id,
3234             type : this.inputType,
3235             cls : 'form-control',
3236             placeholder : this.placeholder || '' 
3237             
3238         };
3239         if (this.name) {
3240             input.name = this.name;
3241         }
3242         if (this.size) {
3243             input.cls += ' input-' + this.size;
3244         }
3245         
3246         var inputblock = input;
3247         
3248         if (this.before || this.after) {
3249             
3250             inputblock = {
3251                 cls : 'input-group',
3252                 cn :  [] 
3253             };
3254             if (this.before) {
3255                 inputblock.cn.push({
3256                     tag :'span',
3257                     cls : 'input-group-addon',
3258                     html : this.before
3259                 });
3260             }
3261             inputblock.cn.push(input);
3262             if (this.after) {
3263                 inputblock.cn.push({
3264                     tag :'span',
3265                     cls : 'input-group-addon',
3266                     html : this.after
3267                 });
3268             }
3269             
3270         }
3271         
3272         Roo.log(align);
3273         Roo.log(this.fieldLabel.length);
3274         
3275         if (align ==='left' && this.fieldLabel.length) {
3276                 Roo.log("left and has label");
3277                 cfg.cn = [
3278                     
3279                     {
3280                         tag: 'label',
3281                         'for' :  id,
3282                         cls : 'col-sm-2 control-label',
3283                         html : this.fieldLabel
3284                         
3285                     },
3286                     {
3287                         cls : "col-sm-10", 
3288                         cn: [
3289                             inputblock
3290                         ]
3291                     }
3292                     
3293                 ];
3294         } else if ( this.fieldLabel.length) {
3295                 Roo.log(" label");
3296                  cfg.cn = [
3297                    
3298                     {
3299                         tag: 'label',
3300                         //cls : 'input-group-addon',
3301                         html : this.fieldLabel
3302                         
3303                     },
3304                     
3305                     inputblock
3306                     
3307                 ];
3308
3309         } else {
3310             
3311                    Roo.log(" no label && no align");
3312                 cfg.cn = [
3313                     
3314                         inputblock
3315                     
3316                 ];
3317                 
3318                 
3319         }
3320          
3321         
3322         
3323         
3324         if (this.disabled) {
3325             input.disabled=true;
3326         }
3327         return cfg;
3328         
3329     },
3330     /**
3331      * return the real input element.
3332      */
3333     inputEl: function ()
3334     {
3335         return this.el.select('input.form-control',true).first();
3336     },
3337     setDisabled : function(v)
3338     {
3339         var i  = this.inputEl().dom;
3340         if (v) {
3341             i.removeAttribute('disabled');
3342             return;
3343             
3344         }
3345         i.setAttribute('disabled','true');
3346     },
3347     initEvents : function()
3348     {
3349         
3350         this.inputEl().on("keydown" , this.fireKey,  this);
3351         this.inputEl().on("focus", this.onFocus,  this);
3352         this.inputEl().on("blur", this.onBlur,  this);
3353         this.inputEl().relayEvent('keyup', this);
3354
3355         // reference to original value for reset
3356         this.originalValue = this.getValue();
3357         //Roo.form.TextField.superclass.initEvents.call(this);
3358         if(this.validationEvent == 'keyup'){
3359             this.validationTask = new Roo.util.DelayedTask(this.validate, this);
3360             this.inputEl().on('keyup', this.filterValidation, this);
3361         }
3362         else if(this.validationEvent !== false){
3363             this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
3364         }
3365         
3366         if(this.selectOnFocus){
3367             this.on("focus", this.preFocus, this);
3368             
3369         }
3370         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
3371             this.inputEl().on("keypress", this.filterKeys, this);
3372         }
3373        /* if(this.grow){
3374             this.el.on("keyup", this.onKeyUp,  this, {buffer:50});
3375             this.el.on("click", this.autoSize,  this);
3376         }
3377         */
3378         if(this.inputEl().is('input[type=password]') && Roo.isSafari){
3379             this.inputEl().on('keydown', this.SafariOnKeyDown, this);
3380         }
3381         
3382     },
3383     filterValidation : function(e){
3384         if(!e.isNavKeyPress()){
3385             this.validationTask.delay(this.validationDelay);
3386         }
3387     },
3388      /**
3389      * Validates the field value
3390      * @return {Boolean} True if the value is valid, else false
3391      */
3392     validate : function(){
3393         //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
3394         if(this.disabled || this.validateValue(this.getRawValue())){
3395             this.clearInvalid();
3396             return true;
3397         }
3398         return false;
3399     },
3400     
3401     
3402     /**
3403      * Validates a value according to the field's validation rules and marks the field as invalid
3404      * if the validation fails
3405      * @param {Mixed} value The value to validate
3406      * @return {Boolean} True if the value is valid, else false
3407      */
3408     validateValue : function(value){
3409         if(value.length < 1)  { // if it's blank
3410              if(this.allowBlank){
3411                 this.clearInvalid();
3412                 return true;
3413              }else{
3414                 this.markInvalid(this.blankText);
3415                 return false;
3416              }
3417         }
3418         if(value.length < this.minLength){
3419             this.markInvalid(String.format(this.minLengthText, this.minLength));
3420             return false;
3421         }
3422         if(value.length > this.maxLength){
3423             this.markInvalid(String.format(this.maxLengthText, this.maxLength));
3424             return false;
3425         }
3426         if(this.vtype){
3427             var vt = Roo.form.VTypes;
3428             if(!vt[this.vtype](value, this)){
3429                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
3430                 return false;
3431             }
3432         }
3433         if(typeof this.validator == "function"){
3434             var msg = this.validator(value);
3435             if(msg !== true){
3436                 this.markInvalid(msg);
3437                 return false;
3438             }
3439         }
3440         if(this.regex && !this.regex.test(value)){
3441             this.markInvalid(this.regexText);
3442             return false;
3443         }
3444         return true;
3445     },
3446
3447     
3448     
3449      // private
3450     fireKey : function(e){
3451         //Roo.log('field ' + e.getKey());
3452         if(e.isNavKeyPress()){
3453             this.fireEvent("specialkey", this, e);
3454         }
3455     },
3456     focus : function (selectText){
3457         if(this.rendered){
3458             this.inputEl().focus();
3459             if(selectText === true){
3460                 this.inputEl().dom.select();
3461             }
3462         }
3463         return this;
3464     } ,
3465     
3466     onFocus : function(){
3467         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3468            // this.el.addClass(this.focusClass);
3469         }
3470         if(!this.hasFocus){
3471             this.hasFocus = true;
3472             this.startValue = this.getValue();
3473             this.fireEvent("focus", this);
3474         }
3475     },
3476     
3477     beforeBlur : Roo.emptyFn,
3478
3479     
3480     // private
3481     onBlur : function(){
3482         this.beforeBlur();
3483         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3484             //this.el.removeClass(this.focusClass);
3485         }
3486         this.hasFocus = false;
3487         if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
3488             this.validate();
3489         }
3490         var v = this.getValue();
3491         if(String(v) !== String(this.startValue)){
3492             this.fireEvent('change', this, v, this.startValue);
3493         }
3494         this.fireEvent("blur", this);
3495     },
3496     
3497     /**
3498      * Resets the current field value to the originally loaded value and clears any validation messages
3499      */
3500     reset : function(){
3501         this.setValue(this.originalValue);
3502         this.clearInvalid();
3503     },
3504      /**
3505      * Returns the name of the field
3506      * @return {Mixed} name The name field
3507      */
3508     getName: function(){
3509         return this.name;
3510     },
3511      /**
3512      * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
3513      * @return {Mixed} value The field value
3514      */
3515     getValue : function(){
3516         var v = this.inputEl().getValue();
3517         return v;
3518     },
3519     /**
3520      * Returns the raw data value which may or may not be a valid, defined value.  To return a normalized value see {@link #getValue}.
3521      * @return {Mixed} value The field value
3522      */
3523     getRawValue : function(){
3524         var v = this.inputEl().getValue();
3525         
3526         return v;
3527     },
3528     /**
3529      * Sets a data value into the field and validates it.  To set the value directly without validation see {@link #setRawValue}.
3530      * @param {Mixed} value The value to set
3531      */
3532     setValue : function(v){
3533         this.value = v;
3534         if(this.rendered){
3535             this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
3536             this.validate();
3537         }
3538     },
3539     
3540     /*
3541     processValue : function(value){
3542         if(this.stripCharsRe){
3543             var newValue = value.replace(this.stripCharsRe, '');
3544             if(newValue !== value){
3545                 this.setRawValue(newValue);
3546                 return newValue;
3547             }
3548         }
3549         return value;
3550     },
3551   */
3552     preFocus : function(){
3553         
3554         if(this.selectOnFocus){
3555             this.inputEl().dom.select();
3556         }
3557     },
3558     filterKeys : function(e){
3559         var k = e.getKey();
3560         if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
3561             return;
3562         }
3563         var c = e.getCharCode(), cc = String.fromCharCode(c);
3564         if(Roo.isIE && (e.isSpecialKey() || !cc)){
3565             return;
3566         }
3567         if(!this.maskRe.test(cc)){
3568             e.stopEvent();
3569         }
3570     },
3571      /**
3572      * Clear any invalid styles/messages for this field
3573      */
3574     clearInvalid : function(){
3575         
3576         if(!this.el || this.preventMark){ // not rendered
3577             return;
3578         }
3579         this.el.removeClass(this.invalidClass);
3580         /*
3581         switch(this.msgTarget){
3582             case 'qtip':
3583                 this.el.dom.qtip = '';
3584                 break;
3585             case 'title':
3586                 this.el.dom.title = '';
3587                 break;
3588             case 'under':
3589                 if(this.errorEl){
3590                     Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
3591                 }
3592                 break;
3593             case 'side':
3594                 if(this.errorIcon){
3595                     this.errorIcon.dom.qtip = '';
3596                     this.errorIcon.hide();
3597                     this.un('resize', this.alignErrorIcon, this);
3598                 }
3599                 break;
3600             default:
3601                 var t = Roo.getDom(this.msgTarget);
3602                 t.innerHTML = '';
3603                 t.style.display = 'none';
3604                 break;
3605         }
3606         */
3607         this.fireEvent('valid', this);
3608     },
3609      /**
3610      * Mark this field as invalid
3611      * @param {String} msg The validation message
3612      */
3613     markInvalid : function(msg){
3614         if(!this.el  || this.preventMark){ // not rendered
3615             return;
3616         }
3617         this.el.addClass(this.invalidClass);
3618         /*
3619         msg = msg || this.invalidText;
3620         switch(this.msgTarget){
3621             case 'qtip':
3622                 this.el.dom.qtip = msg;
3623                 this.el.dom.qclass = 'x-form-invalid-tip';
3624                 if(Roo.QuickTips){ // fix for floating editors interacting with DND
3625                     Roo.QuickTips.enable();
3626                 }
3627                 break;
3628             case 'title':
3629                 this.el.dom.title = msg;
3630                 break;
3631             case 'under':
3632                 if(!this.errorEl){
3633                     var elp = this.el.findParent('.x-form-element', 5, true);
3634                     this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
3635                     this.errorEl.setWidth(elp.getWidth(true)-20);
3636                 }
3637                 this.errorEl.update(msg);
3638                 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
3639                 break;
3640             case 'side':
3641                 if(!this.errorIcon){
3642                     var elp = this.el.findParent('.x-form-element', 5, true);
3643                     this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
3644                 }
3645                 this.alignErrorIcon();
3646                 this.errorIcon.dom.qtip = msg;
3647                 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
3648                 this.errorIcon.show();
3649                 this.on('resize', this.alignErrorIcon, this);
3650                 break;
3651             default:
3652                 var t = Roo.getDom(this.msgTarget);
3653                 t.innerHTML = msg;
3654                 t.style.display = this.msgDisplay;
3655                 break;
3656         }
3657         */
3658         this.fireEvent('invalid', this, msg);
3659     },
3660     // private
3661     SafariOnKeyDown : function(event)
3662     {
3663         // this is a workaround for a password hang bug on chrome/ webkit.
3664         
3665         var isSelectAll = false;
3666         
3667         if(this.inputEl().dom.selectionEnd > 0){
3668             isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
3669         }
3670         if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
3671             event.preventDefault();
3672             this.setValue('');
3673             return;
3674         }
3675         
3676         if(isSelectAll){ // backspace and delete key
3677             
3678             event.preventDefault();
3679             // this is very hacky as keydown always get's upper case.
3680             //
3681             var cc = String.fromCharCode(event.getCharCode());
3682             this.setValue( event.shiftKey ?  cc : cc.toLowerCase());
3683             
3684         }
3685         
3686         
3687     }
3688 });
3689
3690  
3691 /*
3692  * - LGPL
3693  *
3694  * trigger field - base class for combo..
3695  * 
3696  */
3697  
3698 /**
3699  * @class Roo.bootstrap.TriggerField
3700  * @extends Roo.bootstrap.Input
3701  * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
3702  * The trigger has no default action, so you must assign a function to implement the trigger click handler by
3703  * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox
3704  * for which you can provide a custom implementation.  For example:
3705  * <pre><code>
3706 var trigger = new Roo.bootstrap.TriggerField();
3707 trigger.onTriggerClick = myTriggerFn;
3708 trigger.applyTo('my-field');
3709 </code></pre>
3710  *
3711  * However, in general you will most likely want to use TriggerField as the base class for a reusable component.
3712  * {@link Roo.bootstrap.DateField} and {@link Roo.bootstrap.ComboBox} are perfect examples of this.
3713  * @cfg {String} triggerClass An additional CSS class used to style the trigger button.  The trigger will always get the
3714  * class 'x-form-trigger' by default and triggerClass will be <b>appended</b> if specified.
3715  * @constructor
3716  * Create a new TriggerField.
3717  * @param {Object} config Configuration options (valid {@Roo.bootstrap.Input} config options will also be applied
3718  * to the base TextField)
3719  */
3720 Roo.bootstrap.TriggerField = function(config){
3721     this.mimicing = false;
3722     Roo.bootstrap.TriggerField.superclass.constructor.call(this, config);
3723 };
3724
3725 Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input,  {
3726     /**
3727      * @cfg {String} triggerClass A CSS class to apply to the trigger
3728      */
3729      /**
3730      * @cfg {Boolean} hideTrigger True to hide the trigger element and display only the base text field (defaults to false)
3731      */
3732     hideTrigger:false,
3733
3734     /** @cfg {Boolean} grow @hide */
3735     /** @cfg {Number} growMin @hide */
3736     /** @cfg {Number} growMax @hide */
3737
3738     /**
3739      * @hide 
3740      * @method
3741      */
3742     autoSize: Roo.emptyFn,
3743     // private
3744     monitorTab : true,
3745     // private
3746     deferHeight : true,
3747
3748     
3749     actionMode : 'wrap',
3750     
3751     
3752     
3753     getAutoCreate : function(){
3754        
3755         var parent = this.parent();
3756         
3757         var align = parent.labelAlign;
3758         
3759         var id = Roo.id();
3760         
3761         var cfg = {
3762             cls: 'form-group' //input-group
3763         };
3764         
3765         var input =  {
3766             tag: 'input',
3767             id : id,
3768             type : this.inputType,
3769             cls : 'form-control',
3770             autocomplete: 'off',
3771             placeholder : this.placeholder || '' 
3772             
3773         };
3774         if (this.name) {
3775             input.name = this.name;
3776         }
3777         if (this.size) {
3778             input.cls += ' input-' + this.size;
3779         }
3780         var inputblock = {
3781             cls: 'combobox-container input-group',
3782             cn: [
3783                 {
3784                     tag: 'input',
3785                     type : 'hidden',
3786                     cls: 'form-hidden-field'
3787                 },
3788                 input,
3789                 {
3790                     tag: 'ul',
3791                     cls : 'typeahead typeahead-long dropdown-menu',
3792                     style : 'display:none'
3793                 },
3794                 {
3795                     tag :'span',
3796                     cls : 'input-group-addon btn dropdown-toggle',
3797                     cn : [
3798                         {
3799                             tag: 'span',
3800                             cls: 'caret'
3801                         },
3802                         {
3803                             tag: 'span',
3804                             cls: 'combobox-clear',
3805                             cn  : [
3806                                 {
3807                                     tag : 'i',
3808                                     cls: 'icon-remove'
3809                                 }
3810                             ]
3811                         },
3812                     ]
3813                         
3814                 }
3815             ]
3816         };
3817         
3818         
3819         
3820         
3821         if (align ==='left' && this.fieldLabel.length) {
3822                 
3823             
3824             
3825                 Roo.log("left and has label");
3826                 cfg.cn = [
3827                     
3828                     {
3829                         tag: 'label',
3830                         'for' :  id,
3831                         cls : 'col-sm-2 control-label',
3832                         html : this.fieldLabel
3833                         
3834                     },
3835                     {
3836                         cls : "col-sm-10", 
3837                         cn: [
3838                             inputblock
3839                         ]
3840                     }
3841                     
3842                 ];
3843         } else if ( this.fieldLabel.length) {
3844                 Roo.log(" label");
3845                  cfg.cn = [
3846                    
3847                     {
3848                         tag: 'label',
3849                         //cls : 'input-group-addon',
3850                         html : this.fieldLabel
3851                         
3852                     },
3853                     
3854                     inputblock
3855                     
3856                 ];
3857
3858         } else {
3859             
3860                 Roo.log(" no label && no align");
3861                 cfg = inputblock
3862                      
3863                 
3864         }
3865          
3866         
3867         
3868         
3869         if (this.disabled) {
3870             input.disabled=true;
3871         }
3872         return cfg;
3873         
3874     },
3875     
3876     
3877     
3878     // private
3879     onResize : function(w, h){
3880         Roo.boostrap.TriggerField.superclass.onResize.apply(this, arguments);
3881         if(typeof w == 'number'){
3882             var x = w - this.trigger.getWidth();
3883             this.inputEl().setWidth(this.adjustWidth('input', x));
3884             this.trigger.setStyle('left', x+'px');
3885         }
3886     },
3887
3888     // private
3889     adjustSize : Roo.BoxComponent.prototype.adjustSize,
3890
3891     // private
3892     getResizeEl : function(){
3893         return this.inputEl();
3894     },
3895
3896     // private
3897     getPositionEl : function(){
3898         return this.inputEl();
3899     },
3900
3901     // private
3902     alignErrorIcon : function(){
3903         this.errorIcon.alignTo(this.inputEl(), 'tl-tr', [2, 0]);
3904     },
3905
3906     // private
3907     initEvents : function(){
3908         
3909         //this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
3910         
3911         this.trigger = this.el.select('span.dropdown-toggle',true).first();
3912         if(this.hideTrigger){
3913             this.trigger.setDisplayed(false);
3914         }
3915         this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});
3916         //this.trigger.addClassOnOver('x-form-trigger-over');
3917         //this.trigger.addClassOnClick('x-form-trigger-click');
3918         
3919         //if(!this.width){
3920         //    this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
3921         //}
3922     },
3923
3924     // private
3925     initTrigger : function(){
3926        
3927     },
3928
3929     // private
3930     onDestroy : function(){
3931         if(this.trigger){
3932             this.trigger.removeAllListeners();
3933           //  this.trigger.remove();
3934         }
3935         //if(this.wrap){
3936         //    this.wrap.remove();
3937         //}
3938         Roo.bootstrap.TriggerField.superclass.onDestroy.call(this);
3939     },
3940
3941     // private
3942     onFocus : function(){
3943         Roo.bootstrap.TriggerField.superclass.onFocus.call(this);
3944         /*
3945         if(!this.mimicing){
3946             this.wrap.addClass('x-trigger-wrap-focus');
3947             this.mimicing = true;
3948             Roo.get(Roo.isIE ? document.body : document).on("mousedown", this.mimicBlur, this);
3949             if(this.monitorTab){
3950                 this.el.on("keydown", this.checkTab, this);
3951             }
3952         }
3953         */
3954     },
3955
3956     // private
3957     checkTab : function(e){
3958         if(e.getKey() == e.TAB){
3959             this.triggerBlur();
3960         }
3961     },
3962
3963     // private
3964     onBlur : function(){
3965         // do nothing
3966     },
3967
3968     // private
3969     mimicBlur : function(e, t){
3970         /*
3971         if(!this.wrap.contains(t) && this.validateBlur()){
3972             this.triggerBlur();
3973         }
3974         */
3975     },
3976
3977     // private
3978     triggerBlur : function(){
3979         this.mimicing = false;
3980         Roo.get(Roo.isIE ? document.body : document).un("mousedown", this.mimicBlur);
3981         if(this.monitorTab){
3982             this.el.un("keydown", this.checkTab, this);
3983         }
3984         //this.wrap.removeClass('x-trigger-wrap-focus');
3985         Roo.bootstrap.TriggerField.superclass.onBlur.call(this);
3986     },
3987
3988     // private
3989     // This should be overriden by any subclass that needs to check whether or not the field can be blurred.
3990     validateBlur : function(e, t){
3991         return true;
3992     },
3993
3994     // private
3995     onDisable : function(){
3996         Roo.bootstrap.TriggerField.superclass.onDisable.call(this);
3997         //if(this.wrap){
3998         //    this.wrap.addClass('x-item-disabled');
3999         //}
4000     },
4001
4002     // private
4003     onEnable : function(){
4004         Roo.bootstrap.TriggerField.superclass.onEnable.call(this);
4005         //if(this.wrap){
4006         //    this.el.removeClass('x-item-disabled');
4007         //}
4008     },
4009
4010     // private
4011     onShow : function(){
4012         var ae = this.getActionEl();
4013         
4014         if(ae){
4015             ae.dom.style.display = '';
4016             ae.dom.style.visibility = 'visible';
4017         }
4018     },
4019
4020     // private
4021     
4022     onHide : function(){
4023         var ae = this.getActionEl();
4024         ae.dom.style.display = 'none';
4025     },
4026
4027     /**
4028      * The function that should handle the trigger's click event.  This method does nothing by default until overridden
4029      * by an implementing function.
4030      * @method
4031      * @param {EventObject} e
4032      */
4033     onTriggerClick : Roo.emptyFn
4034 });
4035