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