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         this.maskEl.show();
1189         
1190         
1191     },
1192     hide : function() {
1193         this.maskEl.hide();
1194         this.el.removeClass('on');
1195         this.el.addClass('fade');
1196         this.el.setStyle('display', 'none');
1197     }
1198 });
1199
1200  /*
1201  * - LGPL
1202  *
1203  * navbar
1204  * 
1205  */
1206
1207 /**
1208  * @class Roo.bootstrap.Navbar
1209  * @extends Roo.bootstrap.Component
1210  * Bootstrap Navbar class
1211  * @cfg {Boolean} sidebar has side bar
1212  * @cfg {Boolean} bar is a bar?
1213  * @cfg {String} position (fixed-top|fixed-bottom|static-top) position
1214  * @cfg {String} brand what is brand
1215  * @cfg {Boolean} inverse is inverted color
1216  * @cfg {String} type (nav | pills | tabs)
1217  * @cfg {Boolean} arrangement stacked | justified
1218  * @cfg {String} align (left | right) alignment
1219  *
1220  * 
1221  * @constructor
1222  * Create a new Navbar
1223  * @param {Object} config The config object
1224  */
1225
1226
1227 Roo.bootstrap.Navbar = function(config){
1228     Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
1229 };
1230
1231 Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component,  {
1232     
1233     sidebar: false,
1234     
1235     bar: false,
1236     brand: '',
1237     inverse: false,
1238     position: '',
1239     align : false,
1240     type: 'nav',
1241     arrangement: '',
1242     
1243     getAutoCreate : function(){
1244         var cfg = {
1245             cls : 'navbar'
1246         };
1247         
1248         if (this.sidebar === true) {
1249             cfg = {
1250                 tag: 'div',
1251                 cls: 'sidebar-nav'
1252             };
1253             return cfg;
1254         }
1255         
1256         if (this.bar === true) {
1257             cfg = {
1258                 tag: 'nav',
1259                 cls: 'navbar',
1260                 role: 'navigation',
1261                 cn: [
1262                     {
1263                         tag: 'div',
1264                         cls: 'navbar-header',
1265                         cn: [
1266                             {
1267                             tag: 'button',
1268                             type: 'button',
1269                             cls: 'navbar-toggle',
1270                             'data-toggle': 'collapse',
1271                             cn: [
1272                                 {
1273                                     tag: 'span',
1274                                     cls: 'sr-only',
1275                                     html: 'Toggle navigation'
1276                                 },
1277                                 {
1278                                     tag: 'span',
1279                                     cls: 'icon-bar'
1280                                 },
1281                                 {
1282                                     tag: 'span',
1283                                     cls: 'icon-bar'
1284                                 },
1285                                 {
1286                                     tag: 'span',
1287                                     cls: 'icon-bar'
1288                                 }
1289                             ]
1290                             }
1291                         ]
1292                     },
1293                     {
1294                     tag: 'div',
1295                     cls: 'collapse navbar-collapse'
1296                     }
1297                 ]
1298             };
1299             
1300             cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
1301             
1302             if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
1303             cfg.cls += ' navbar-' + this.position;
1304             cfg.tag = this.position  == 'fixed-bottom' ? 'footer' : 'header';
1305             }
1306             
1307             if (this.brand !== '') {
1308                 cfg.cn[0].cn.push({
1309                     tag: 'a',
1310                     href: '#',
1311                     cls: 'navbar-brand',
1312                     cn: [
1313                     this.brand
1314                     ]
1315                 });
1316             }
1317             
1318             return cfg;
1319         
1320         } else if (this.bar === false) {
1321             
1322         } else {
1323             Roo.log('Property \'bar\' in of Navbar must be either true or false')
1324         }
1325         
1326         cfg.cn = [
1327             {
1328                 cls: 'nav',
1329                 tag : 'ul'
1330             }
1331         ];
1332         
1333         if (['tabs','pills'].indexOf(this.type)!==-1) {
1334             cfg.cn[0].cls += ' nav-' + this.type
1335         } else {
1336             if (this.type!=='nav') {
1337             Roo.log('nav type must be nav/tabs/pills')
1338             }
1339             cfg.cn[0].cls += ' navbar-nav'
1340         }
1341         
1342         if (['stacked','justified'].indexOf(this.arrangement)!==-1) {
1343             cfg.cn[0].cls += ' nav-' + this.arrangement;
1344         }
1345         
1346         if (this.align === 'right') {
1347             cfg.cn[0].cls += ' navbar-right';
1348         }
1349         if (this.inverse) {
1350             cfg.cls += ' navbar-inverse';
1351             
1352         }
1353         
1354         
1355         return cfg;
1356     },
1357     
1358     getChildContainer : function() {
1359         if (this.bar === true) {
1360             return this.el.select('.collapse',true).first();
1361         }
1362         console.log(this);
1363         return this.el;
1364     }
1365    
1366 });
1367
1368  
1369
1370  /*
1371  * - LGPL
1372  *
1373  * nav group
1374  * 
1375  */
1376
1377 /**
1378  * @class Roo.bootstrap.NavGroup
1379  * @extends Roo.bootstrap.Component
1380  * Bootstrap NavGroup class
1381  * @cfg {String} align left | right
1382  * @cfg {Boolean} inverse false | true
1383  * 
1384  * @constructor
1385  * Create a new nav group
1386  * @param {Object} config The config object
1387  */
1388
1389 Roo.bootstrap.NavGroup = function(config){
1390     Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
1391 };
1392
1393 Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component,  {
1394     
1395     align: '',
1396     inverse: false,
1397     form: false,
1398     
1399     getAutoCreate : function(){
1400         var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
1401         
1402         cfg = {
1403             tag : 'ul',
1404             cls: 'nav navbar-nav' 
1405         }
1406         
1407         if (this.parent().sidebar === true) {
1408             cfg = {
1409                 tag: 'ul',
1410                 cls: 'dashboard-menu'
1411             }
1412             
1413             return cfg;
1414         }
1415         
1416         if (this.form === true) {
1417             cfg = {
1418                 tag: 'form',
1419                 cls: 'navbar-form'
1420             }
1421             
1422             if (this.align === 'right') {
1423                 cfg.cls += ' navbar-right';
1424             } else {
1425                 cfg.cls += ' navbar-left';
1426             }
1427         }
1428         
1429         
1430         if (this.align === 'right') {
1431             cfg.cls += ' navbar-right';
1432         }
1433         
1434         if (this.inverse) {
1435             cfg.cls += ' navbar-inverse';
1436             
1437         }
1438         
1439         
1440         return cfg;
1441     }
1442    
1443 });
1444
1445  
1446
1447  /*
1448  * - LGPL
1449  *
1450  * row
1451  * 
1452  */
1453 /**
1454  * @class Roo.bootstrap.Navbar.Button
1455  * @extends Roo.bootstrap.Component
1456  * Bootstrap Navbar.Button class
1457  * @cfg {String} href  link to
1458  * @cfg {String} html content of button
1459     
1460  * @constructor
1461  * Create a new Navbar Button
1462  * @param {Object} config The config object
1463  */
1464
1465
1466 Roo.bootstrap.Navbar.Button = function(config){
1467     Roo.bootstrap.Navbar.Button.superclass.constructor.call(this, config);
1468 };
1469
1470 Roo.extend(Roo.bootstrap.Navbar.Button, Roo.bootstrap.Component,  {
1471     
1472     href : false,
1473     html : false,
1474     
1475     autoCreate : {
1476         cls: 'btn',
1477         tag : 'button',
1478         html: 'hello'
1479     },
1480     
1481     getAutoCreate : function(){
1482         
1483         var cfg = {
1484             cls: 'btn',
1485             tag : 'button',
1486             html: 'hello',
1487             cn : []
1488             
1489         } ;
1490         cfg.cn.push({
1491             html : this.html || ''
1492             //href : this.
1493              //       )
1494         });
1495         cfg.cn.push({
1496             tag: 'span',
1497             cls : 'carat'
1498         });
1499         
1500         return cfg;
1501     }
1502    
1503 });
1504
1505  
1506
1507  /*
1508  * - LGPL
1509  *
1510  * row
1511  * 
1512  */
1513
1514 /**
1515  * @class Roo.bootstrap.Navbar.Item
1516  * @extends Roo.bootstrap.Component
1517  * Bootstrap Navbar.Button class
1518  * @cfg {String} href  link to
1519  * @cfg {String} html content of button
1520  * @cfg {String} badge text inside badge
1521  * @cfg {String} glyphicon name of glyphicon
1522   
1523  * @constructor
1524  * Create a new Navbar Button
1525  * @param {Object} config The config object
1526  */
1527 Roo.bootstrap.Navbar.Item = function(config){
1528     Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
1529 };
1530
1531 Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component,  {
1532     
1533     href: false,
1534     html: '',
1535     badge: '',
1536     icon: false,
1537     glyphicon: false,
1538     
1539     getAutoCreate : function(){
1540         
1541         var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
1542         
1543         if (this.parent().parent().sidebar === true) {
1544             cfg = {
1545                 tag: 'li',
1546                 cls: '',
1547                 cn: [
1548                     {
1549                         tag: 'p',
1550                         cls: ''
1551                     }
1552                 ]
1553             }
1554             
1555             if (this.html) {
1556                 cfg.cn[0].html = this.html;
1557             }
1558             
1559             if (this.active) {
1560                 this.cls += ' active';
1561             }
1562             
1563             if (this.menu) {
1564                 cfg.cn[0].cls += ' dropdown-toggle';
1565                 cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
1566             }
1567             
1568             if (this.href) {
1569                 cfg.cn[0].tag = 'a',
1570                 cfg.cn[0].href = this.href;
1571             }
1572             
1573             if (this.glyphicon) {
1574                 cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
1575             }
1576             
1577             return cfg;
1578         }
1579         
1580         cfg = {
1581             tag: 'li'
1582         }
1583         cfg.cn = [
1584             {
1585                 tag: 'p',
1586                 html: 'Text'
1587             }
1588         ];
1589         
1590         if (this.glyphicon) {
1591             if(cfg.html){cfg.html = ' ' + this.html};
1592             cfg.cn=[
1593                 {
1594                     tag: 'span',
1595                     cls: 'glyphicon glyphicon-' + this.glyphicon
1596                 }
1597             ];
1598         }
1599         
1600         cfg.cn[0].html = this.html || cfg.cn[0].html ;
1601         if (this.menu) {
1602             cfg.cn[0].tag='a';
1603             cfg.cn[0].href='#';
1604             cfg.cn[0].html += " <span class='caret'></span>";
1605         //}else if (!this.href) {
1606         //    cfg.cn[0].tag='p';
1607         //    cfg.cn[0].cls='navbar-text';
1608         } else {
1609             cfg.cn[0].tag='a';
1610             cfg.cn[0].href=this.href||'#';
1611             cfg.cn[0].html=this.html;
1612         }
1613         
1614         if (this.badge !== '') {
1615             
1616             cfg.cn[0].cn=[
1617                 cfg.cn[0].html + ' ',
1618                 {
1619                     tag: 'span',
1620                     cls: 'badge',
1621                     html: this.badge
1622                 }
1623             ];
1624             cfg.cn[0].html=''
1625         }
1626          
1627         
1628         return cfg;
1629     },
1630     initEvents: function() {
1631        // Roo.log('init events?');
1632        // Roo.log(this.el.dom);
1633         this.el.select('a',true).on('click',
1634                 function(e) {
1635                     this.fireEvent('click', this);
1636                 },
1637                 this
1638         );
1639     }
1640    
1641 });
1642  
1643
1644  /*
1645  * - LGPL
1646  *
1647  * row
1648  * 
1649  */
1650
1651 /**
1652  * @class Roo.bootstrap.Row
1653  * @extends Roo.bootstrap.Component
1654  * Bootstrap Row class (contains columns...)
1655  * 
1656  * @constructor
1657  * Create a new Row
1658  * @param {Object} config The config object
1659  */
1660
1661 Roo.bootstrap.Row = function(config){
1662     Roo.bootstrap.Row.superclass.constructor.call(this, config);
1663 };
1664
1665 Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component,  {
1666     
1667     autoCreate: {
1668         cls: 'row clearfix'
1669     }
1670     
1671     
1672 });
1673
1674  
1675
1676  /*
1677  * - LGPL
1678  *
1679  * element
1680  * 
1681  */
1682
1683 /**
1684  * @class Roo.bootstrap.Element
1685  * @extends Roo.bootstrap.Component
1686  * Bootstrap Element class
1687  * @cfg {String} html contents of the element
1688  * @cfg {String} tag tag of the element
1689  * @cfg {String} cls class of the element
1690  * 
1691  * @constructor
1692  * Create a new Element
1693  * @param {Object} config The config object
1694  */
1695
1696 Roo.bootstrap.Element = function(config){
1697     Roo.bootstrap.Element.superclass.constructor.call(this, config);
1698 };
1699
1700 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component,  {
1701     
1702     tag: 'div',
1703     cls: '',
1704     html: '',
1705     
1706     
1707     
1708     getAutoCreate : function(){
1709         var cfg = Roo.apply({}, Roo.bootstrap.Element.superclass.getAutoCreate.call(this));
1710         
1711         cfg = {
1712             tag: this.tag,
1713             cls: '',
1714             html: this.html
1715         }
1716         
1717         return cfg;
1718     }
1719    
1720 });
1721
1722  
1723
1724  /*
1725  * - LGPL
1726  *
1727  * pagination
1728  * 
1729  */
1730
1731 /**
1732  * @class Roo.bootstrap.Pagination
1733  * @extends Roo.bootstrap.Component
1734  * Bootstrap Pagination class
1735  * @cfg {String} size xs | sm | md | lg
1736  * @cfg {Boolean} inverse false | true
1737  * @cfg {Number} from pagination starting number
1738  * @cfg {Number} to pagination ending number
1739  * @cfg {String} align empty or left | right
1740  * @cfg {Number} active active page number
1741  * 
1742  * @constructor
1743  * Create a new Pagination
1744  * @param {Object} config The config object
1745  */
1746
1747 Roo.bootstrap.Pagination = function(config){
1748     Roo.bootstrap.Pagination.superclass.constructor.call(this, config);
1749 };
1750
1751 Roo.extend(Roo.bootstrap.Pagination, Roo.bootstrap.Component,  {
1752     
1753     cls: false,
1754     size: false,
1755     inverse: false,
1756     from: 1,
1757     to: 4,
1758     align: false,
1759     active: 1,
1760     
1761     getAutoCreate : function(){
1762         cfg = {
1763             tag: 'ul',
1764                 cls: 'pagination',
1765                 cn: []
1766         };
1767         if (this.inverse) {
1768             cfg.cls += ' inverse';
1769         }
1770         if (this.html) {
1771             cfg.html=this.html;
1772         }
1773         if (this.cls) {
1774             cfg.cls=this.cls;
1775         }
1776         cfg.cn[0]={
1777             tag: 'li',
1778             cn: [
1779                 {
1780                     tag: 'a',
1781                     href:'#',
1782                     html: '&laquo;'
1783                 }
1784             ]
1785         };
1786         var from=this.from>0?this.from:1;
1787         var to=this.to-from<=10?this.to:from+10;
1788         var active=this.active>=from&&this.active<=to?this.active:null;
1789         for (var i=from;i<=to;i++) {
1790             cfg.cn.push(
1791                 {
1792                     tag: 'li',
1793                     cls: active===i?'active':'',
1794                     cn: [
1795                         {
1796                             tag: 'a',
1797                             href: '#',
1798                             html: i
1799                         }
1800                     ]
1801                 }
1802             );
1803         }
1804         
1805         cfg.cn.push(
1806             {
1807                 tag: 'li',
1808                 cn: [
1809                     {
1810                        tag: 'a',
1811                        href: '#',
1812                        html: '&raquo;'
1813                     }
1814                 ]
1815             }
1816         );
1817         
1818         return cfg;
1819     }
1820    
1821 });
1822
1823  
1824
1825  /*
1826  * - LGPL
1827  *
1828  * slider
1829  * 
1830  */
1831
1832
1833 /**
1834  * @class Roo.bootstrap.Slider
1835  * @extends Roo.bootstrap.Component
1836  * Bootstrap Slider class
1837  *    
1838  * @constructor
1839  * Create a new Slider
1840  * @param {Object} config The config object
1841  */
1842
1843 Roo.bootstrap.Slider = function(config){
1844     Roo.bootstrap.Slider.superclass.constructor.call(this, config);
1845 };
1846
1847 Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component,  {
1848     
1849     getAutoCreate : function(){
1850         
1851         var cfg = {
1852             tag: 'div',
1853             cls: 'slider slider-sample1 vertical-handler ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all',
1854             cn: [
1855                 {
1856                     tag: 'a',
1857                     cls: 'ui-slider-handle ui-state-default ui-corner-all'
1858                 }
1859             ]
1860         }
1861         
1862         return cfg;
1863     }
1864    
1865 });
1866
1867  /*
1868  * - LGPL
1869  *
1870  * table
1871  * 
1872  */
1873
1874 /**
1875  * @class Roo.bootstrap.Table
1876  * @extends Roo.bootstrap.Component
1877  * Bootstrap Table class
1878  * 
1879  * @constructor
1880  * Create a new Table
1881  * @param {Object} config The config object
1882  */
1883
1884 Roo.bootstrap.Table = function(config){
1885     Roo.bootstrap.Table.superclass.constructor.call(this, config);
1886 };
1887
1888 Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component,  {
1889     
1890     html: false,
1891     cls: false,
1892     
1893     getAutoCreate : function(){
1894         var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
1895         
1896         cfg = {
1897             tag: 'table',
1898             cn: [
1899                 {
1900                     tag: 'tbody'
1901                 }
1902             ]
1903         }
1904         if (this.html) {
1905             cfg.html=this.html
1906         }
1907         if (this.cls) {
1908             cfg.cls=this.cls
1909         }
1910         
1911         return cfg;
1912     }
1913    
1914 });
1915
1916  
1917
1918  /*
1919  * - LGPL
1920  *
1921  * table cell
1922  * 
1923  */
1924
1925 /**
1926  * @class Roo.bootstrap.TableCell
1927  * @extends Roo.bootstrap.Component
1928  * Bootstrap TableCell class
1929  * 
1930  * @constructor
1931  * Create a new TableCell
1932  * @param {Object} config The config object
1933  */
1934
1935 Roo.bootstrap.TableCell = function(config){
1936     Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
1937 };
1938
1939 Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component,  {
1940     
1941     getAutoCreate : function(){
1942         var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
1943         
1944         cfg = {
1945             tag: 'td'
1946         }
1947         if (this.html) {
1948             cfg.html=this.html
1949         }
1950         if (this.cls) {
1951             cfg.cls=this.cls
1952         }
1953         
1954         return cfg;
1955     }
1956    
1957 });
1958
1959  
1960
1961  /*
1962  * - LGPL
1963  *
1964  * table row
1965  * 
1966  */
1967
1968 /**
1969  * @class Roo.bootstrap.TableRow
1970  * @extends Roo.bootstrap.Component
1971  * Bootstrap TableRow class
1972  * 
1973  * @constructor
1974  * Create a new TableRow
1975  * @param {Object} config The config object
1976  */
1977
1978 Roo.bootstrap.TableRow = function(config){
1979     Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
1980 };
1981
1982 Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component,  {
1983     
1984     getAutoCreate : function(){
1985         var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
1986         
1987         cfg = {
1988             tag: 'tr'
1989         }
1990         
1991         return cfg;
1992     }
1993    
1994 });
1995
1996  
1997
1998  /*
1999  * Based on:
2000  * Ext JS Library 1.1.1
2001  * Copyright(c) 2006-2007, Ext JS, LLC.
2002  *
2003  * Originally Released Under LGPL - original licence link has changed is not relivant.
2004  *
2005  * Fork - LGPL
2006  * <script type="text/javascript">
2007  */
2008
2009 // as we use this in bootstrap.
2010 Roo.namespace('Roo.form');
2011  /**
2012  * @class Roo.form.Action
2013  * Internal Class used to handle form actions
2014  * @constructor
2015  * @param {Roo.form.BasicForm} el The form element or its id
2016  * @param {Object} config Configuration options
2017  */
2018
2019  
2020  
2021 // define the action interface
2022 Roo.form.Action = function(form, options){
2023     this.form = form;
2024     this.options = options || {};
2025 };
2026 /**
2027  * Client Validation Failed
2028  * @const 
2029  */
2030 Roo.form.Action.CLIENT_INVALID = 'client';
2031 /**
2032  * Server Validation Failed
2033  * @const 
2034  */
2035 Roo.form.Action.SERVER_INVALID = 'server';
2036  /**
2037  * Connect to Server Failed
2038  * @const 
2039  */
2040 Roo.form.Action.CONNECT_FAILURE = 'connect';
2041 /**
2042  * Reading Data from Server Failed
2043  * @const 
2044  */
2045 Roo.form.Action.LOAD_FAILURE = 'load';
2046
2047 Roo.form.Action.prototype = {
2048     type : 'default',
2049     failureType : undefined,
2050     response : undefined,
2051     result : undefined,
2052
2053     // interface method
2054     run : function(options){
2055
2056     },
2057
2058     // interface method
2059     success : function(response){
2060
2061     },
2062
2063     // interface method
2064     handleResponse : function(response){
2065
2066     },
2067
2068     // default connection failure
2069     failure : function(response){
2070         
2071         this.response = response;
2072         this.failureType = Roo.form.Action.CONNECT_FAILURE;
2073         this.form.afterAction(this, false);
2074     },
2075
2076     processResponse : function(response){
2077         this.response = response;
2078         if(!response.responseText){
2079             return true;
2080         }
2081         this.result = this.handleResponse(response);
2082         return this.result;
2083     },
2084
2085     // utility functions used internally
2086     getUrl : function(appendParams){
2087         var url = this.options.url || this.form.url || this.form.el.dom.action;
2088         if(appendParams){
2089             var p = this.getParams();
2090             if(p){
2091                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
2092             }
2093         }
2094         return url;
2095     },
2096
2097     getMethod : function(){
2098         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
2099     },
2100
2101     getParams : function(){
2102         var bp = this.form.baseParams;
2103         var p = this.options.params;
2104         if(p){
2105             if(typeof p == "object"){
2106                 p = Roo.urlEncode(Roo.applyIf(p, bp));
2107             }else if(typeof p == 'string' && bp){
2108                 p += '&' + Roo.urlEncode(bp);
2109             }
2110         }else if(bp){
2111             p = Roo.urlEncode(bp);
2112         }
2113         return p;
2114     },
2115
2116     createCallback : function(){
2117         return {
2118             success: this.success,
2119             failure: this.failure,
2120             scope: this,
2121             timeout: (this.form.timeout*1000),
2122             upload: this.form.fileUpload ? this.success : undefined
2123         };
2124     }
2125 };
2126
2127 Roo.form.Action.Submit = function(form, options){
2128     Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
2129 };
2130
2131 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
2132     type : 'submit',
2133
2134     haveProgress : false,
2135     uploadComplete : false,
2136     
2137     // uploadProgress indicator.
2138     uploadProgress : function()
2139     {
2140         if (!this.form.progressUrl) {
2141             return;
2142         }
2143         
2144         if (!this.haveProgress) {
2145             Roo.MessageBox.progress("Uploading", "Uploading");
2146         }
2147         if (this.uploadComplete) {
2148            Roo.MessageBox.hide();
2149            return;
2150         }
2151         
2152         this.haveProgress = true;
2153    
2154         var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
2155         
2156         var c = new Roo.data.Connection();
2157         c.request({
2158             url : this.form.progressUrl,
2159             params: {
2160                 id : uid
2161             },
2162             method: 'GET',
2163             success : function(req){
2164                //console.log(data);
2165                 var rdata = false;
2166                 var edata;
2167                 try  {
2168                    rdata = Roo.decode(req.responseText)
2169                 } catch (e) {
2170                     Roo.log("Invalid data from server..");
2171                     Roo.log(edata);
2172                     return;
2173                 }
2174                 if (!rdata || !rdata.success) {
2175                     Roo.log(rdata);
2176                     Roo.MessageBox.alert(Roo.encode(rdata));
2177                     return;
2178                 }
2179                 var data = rdata.data;
2180                 
2181                 if (this.uploadComplete) {
2182                    Roo.MessageBox.hide();
2183                    return;
2184                 }
2185                    
2186                 if (data){
2187                     Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
2188                        Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
2189                     );
2190                 }
2191                 this.uploadProgress.defer(2000,this);
2192             },
2193        
2194             failure: function(data) {
2195                 Roo.log('progress url failed ');
2196                 Roo.log(data);
2197             },
2198             scope : this
2199         });
2200            
2201     },
2202     
2203     
2204     run : function()
2205     {
2206         // run get Values on the form, so it syncs any secondary forms.
2207         this.form.getValues();
2208         
2209         var o = this.options;
2210         var method = this.getMethod();
2211         var isPost = method == 'POST';
2212         if(o.clientValidation === false || this.form.isValid()){
2213             
2214             if (this.form.progressUrl) {
2215                 this.form.findField('UPLOAD_IDENTIFIER').setValue(
2216                     (new Date() * 1) + '' + Math.random());
2217                     
2218             } 
2219             
2220             
2221             Roo.Ajax.request(Roo.apply(this.createCallback(), {
2222                 form:this.form.el.dom,
2223                 url:this.getUrl(!isPost),
2224                 method: method,
2225                 params:isPost ? this.getParams() : null,
2226                 isUpload: this.form.fileUpload
2227             }));
2228             
2229             this.uploadProgress();
2230
2231         }else if (o.clientValidation !== false){ // client validation failed
2232             this.failureType = Roo.form.Action.CLIENT_INVALID;
2233             this.form.afterAction(this, false);
2234         }
2235     },
2236
2237     success : function(response)
2238     {
2239         this.uploadComplete= true;
2240         if (this.haveProgress) {
2241             Roo.MessageBox.hide();
2242         }
2243         
2244         
2245         var result = this.processResponse(response);
2246         if(result === true || result.success){
2247             this.form.afterAction(this, true);
2248             return;
2249         }
2250         if(result.errors){
2251             this.form.markInvalid(result.errors);
2252             this.failureType = Roo.form.Action.SERVER_INVALID;
2253         }
2254         this.form.afterAction(this, false);
2255     },
2256     failure : function(response)
2257     {
2258         this.uploadComplete= true;
2259         if (this.haveProgress) {
2260             Roo.MessageBox.hide();
2261         }
2262         
2263         this.response = response;
2264         this.failureType = Roo.form.Action.CONNECT_FAILURE;
2265         this.form.afterAction(this, false);
2266     },
2267     
2268     handleResponse : function(response){
2269         if(this.form.errorReader){
2270             var rs = this.form.errorReader.read(response);
2271             var errors = [];
2272             if(rs.records){
2273                 for(var i = 0, len = rs.records.length; i < len; i++) {
2274                     var r = rs.records[i];
2275                     errors[i] = r.data;
2276                 }
2277             }
2278             if(errors.length < 1){
2279                 errors = null;
2280             }
2281             return {
2282                 success : rs.success,
2283                 errors : errors
2284             };
2285         }
2286         var ret = false;
2287         try {
2288             ret = Roo.decode(response.responseText);
2289         } catch (e) {
2290             ret = {
2291                 success: false,
2292                 errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
2293                 errors : []
2294             };
2295         }
2296         return ret;
2297         
2298     }
2299 });
2300
2301
2302 Roo.form.Action.Load = function(form, options){
2303     Roo.form.Action.Load.superclass.constructor.call(this, form, options);
2304     this.reader = this.form.reader;
2305 };
2306
2307 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
2308     type : 'load',
2309
2310     run : function(){
2311         
2312         Roo.Ajax.request(Roo.apply(
2313                 this.createCallback(), {
2314                     method:this.getMethod(),
2315                     url:this.getUrl(false),
2316                     params:this.getParams()
2317         }));
2318     },
2319
2320     success : function(response){
2321         
2322         var result = this.processResponse(response);
2323         if(result === true || !result.success || !result.data){
2324             this.failureType = Roo.form.Action.LOAD_FAILURE;
2325             this.form.afterAction(this, false);
2326             return;
2327         }
2328         this.form.clearInvalid();
2329         this.form.setValues(result.data);
2330         this.form.afterAction(this, true);
2331     },
2332
2333     handleResponse : function(response){
2334         if(this.form.reader){
2335             var rs = this.form.reader.read(response);
2336             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
2337             return {
2338                 success : rs.success,
2339                 data : data
2340             };
2341         }
2342         return Roo.decode(response.responseText);
2343     }
2344 });
2345
2346 Roo.form.Action.ACTION_TYPES = {
2347     'load' : Roo.form.Action.Load,
2348     'submit' : Roo.form.Action.Submit
2349 };/*
2350  * - LGPL
2351  *
2352  * form
2353  * 
2354  */
2355
2356 /**
2357  * @class Roo.bootstrap.Form
2358  * @extends Roo.bootstrap.Component
2359  * Bootstrap Form class
2360  * @cfg {String} method  GET | POST (default POST)
2361  * @cfg {String} labelAlign top | left (default top)
2362  * 
2363  * @constructor
2364  * Create a new Form
2365  * @param {Object} config The config object
2366  */
2367
2368
2369 Roo.bootstrap.Form = function(config){
2370     Roo.bootstrap.Form.superclass.constructor.call(this, config);
2371     this.addEvents({
2372         /**
2373          * @event clientvalidation
2374          * If the monitorValid config option is true, this event fires repetitively to notify of valid state
2375          * @param {Form} this
2376          * @param {Boolean} valid true if the form has passed client-side validation
2377          */
2378         clientvalidation: true,
2379         /**
2380          * @event beforeaction
2381          * Fires before any action is performed. Return false to cancel the action.
2382          * @param {Form} this
2383          * @param {Action} action The action to be performed
2384          */
2385         beforeaction: true,
2386         /**
2387          * @event actionfailed
2388          * Fires when an action fails.
2389          * @param {Form} this
2390          * @param {Action} action The action that failed
2391          */
2392         actionfailed : true,
2393         /**
2394          * @event actioncomplete
2395          * Fires when an action is completed.
2396          * @param {Form} this
2397          * @param {Action} action The action that completed
2398          */
2399         actioncomplete : true
2400     });
2401     
2402 };
2403
2404 Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component,  {
2405       
2406      /**
2407      * @cfg {String} method
2408      * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
2409      */
2410     method : 'POST',
2411     /**
2412      * @cfg {String} url
2413      * The URL to use for form actions if one isn't supplied in the action options.
2414      */
2415     /**
2416      * @cfg {Boolean} fileUpload
2417      * Set to true if this form is a file upload.
2418      */
2419      
2420     /**
2421      * @cfg {Object} baseParams
2422      * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
2423      */
2424       
2425     /**
2426      * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
2427      */
2428     timeout: 30,
2429
2430     // private
2431     activeAction : null,
2432  
2433     /**
2434      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2435      * element by passing it or its id or mask the form itself by passing in true.
2436      * @type Mixed
2437      */
2438     waitMsgTarget : false,
2439     
2440      
2441     
2442     /**
2443      * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2444      * element by passing it or its id or mask the form itself by passing in true.
2445      * @type Mixed
2446      */
2447     
2448     getAutoCreate : function(){
2449         
2450         var cfg = {
2451             tag: 'form',
2452             method : this.method || 'POST',
2453             id : this.id || Roo.id(),
2454             cls : ''
2455         }
2456         
2457         if (this.labelAlign == 'left' ) {
2458             cfg.cls += ' form-horizontal';
2459         }
2460         return cfg;
2461     },
2462     initEvents : function()
2463     {
2464         this.el.on('submit', this.onSubmit, this);
2465         
2466         
2467     },
2468     // private
2469     onSubmit : function(e){
2470         e.stopEvent();
2471     },
2472     
2473      /**
2474      * Returns true if client-side validation on the form is successful.
2475      * @return Boolean
2476      */
2477     isValid : function(){
2478         var items = this.getItems();
2479         var valid = true;
2480         items.each(function(f){
2481            if(!f.validate()){
2482                valid = false;
2483                
2484            }
2485         });
2486         return valid;
2487     },
2488     /**
2489      * Returns true if any fields in this form have changed since their original load.
2490      * @return Boolean
2491      */
2492     isDirty : function(){
2493         var dirty = false;
2494         var items = this.getItems();
2495         items.each(function(f){
2496            if(f.isDirty()){
2497                dirty = true;
2498                return false;
2499            }
2500            return true;
2501         });
2502         return dirty;
2503     },
2504      /**
2505      * Performs a predefined action (submit or load) or custom actions you define on this form.
2506      * @param {String} actionName The name of the action type
2507      * @param {Object} options (optional) The options to pass to the action.  All of the config options listed
2508      * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
2509      * accept other config options):
2510      * <pre>
2511 Property          Type             Description
2512 ----------------  ---------------  ----------------------------------------------------------------------------------
2513 url               String           The url for the action (defaults to the form's url)
2514 method            String           The form method to use (defaults to the form's method, or POST if not defined)
2515 params            String/Object    The params to pass (defaults to the form's baseParams, or none if not defined)
2516 clientValidation  Boolean          Applies to submit only.  Pass true to call form.isValid() prior to posting to
2517                                    validate the form on the client (defaults to false)
2518      * </pre>
2519      * @return {BasicForm} this
2520      */
2521     doAction : function(action, options){
2522         if(typeof action == 'string'){
2523             action = new Roo.form.Action.ACTION_TYPES[action](this, options);
2524         }
2525         if(this.fireEvent('beforeaction', this, action) !== false){
2526             this.beforeAction(action);
2527             action.run.defer(100, action);
2528         }
2529         return this;
2530     },
2531     
2532     // private
2533     beforeAction : function(action){
2534         var o = action.options;
2535         
2536         // not really supported yet.. ??
2537         
2538         //if(this.waitMsgTarget === true){
2539             this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
2540         //}else if(this.waitMsgTarget){
2541         //    this.waitMsgTarget = Roo.get(this.waitMsgTarget);
2542         //    this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
2543         //}else {
2544         //    Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
2545        // }
2546          
2547     },
2548
2549     // private
2550     afterAction : function(action, success){
2551         this.activeAction = null;
2552         var o = action.options;
2553         
2554         //if(this.waitMsgTarget === true){
2555             this.el.unmask();
2556         //}else if(this.waitMsgTarget){
2557         //    this.waitMsgTarget.unmask();
2558         //}else{
2559         //    Roo.MessageBox.updateProgress(1);
2560         //    Roo.MessageBox.hide();
2561        // }
2562         // 
2563         if(success){
2564             if(o.reset){
2565                 this.reset();
2566             }
2567             Roo.callback(o.success, o.scope, [this, action]);
2568             this.fireEvent('actioncomplete', this, action);
2569             
2570         }else{
2571             
2572             // failure condition..
2573             // we have a scenario where updates need confirming.
2574             // eg. if a locking scenario exists..
2575             // we look for { errors : { needs_confirm : true }} in the response.
2576             if (
2577                 (typeof(action.result) != 'undefined')  &&
2578                 (typeof(action.result.errors) != 'undefined')  &&
2579                 (typeof(action.result.errors.needs_confirm) != 'undefined')
2580            ){
2581                 var _t = this;
2582                 Roo.log("not supported yet");
2583                  /*
2584                 
2585                 Roo.MessageBox.confirm(
2586                     "Change requires confirmation",
2587                     action.result.errorMsg,
2588                     function(r) {
2589                         if (r != 'yes') {
2590                             return;
2591                         }
2592                         _t.doAction('submit', { params :  { _submit_confirmed : 1 } }  );
2593                     }
2594                     
2595                 );
2596                 */
2597                 
2598                 
2599                 return;
2600             }
2601             
2602             Roo.callback(o.failure, o.scope, [this, action]);
2603             // show an error message if no failed handler is set..
2604             if (!this.hasListener('actionfailed')) {
2605                 Roo.log("need to add dialog support");
2606                 /*
2607                 Roo.MessageBox.alert("Error",
2608                     (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
2609                         action.result.errorMsg :
2610                         "Saving Failed, please check your entries or try again"
2611                 );
2612                 */
2613             }
2614             
2615             this.fireEvent('actionfailed', this, action);
2616         }
2617         
2618     },
2619     /**
2620      * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
2621      * @param {String} id The value to search for
2622      * @return Field
2623      */
2624     findField : function(id){
2625         var items = this.getItems();
2626         var field = items.get(id);
2627         if(!field){
2628              items.each(function(f){
2629                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
2630                     field = f;
2631                     return false;
2632                 }
2633                 return true;
2634             });
2635         }
2636         return field || null;
2637     },
2638      /**
2639      * Mark fields in this form invalid in bulk.
2640      * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
2641      * @return {BasicForm} this
2642      */
2643     markInvalid : function(errors){
2644         if(errors instanceof Array){
2645             for(var i = 0, len = errors.length; i < len; i++){
2646                 var fieldError = errors[i];
2647                 var f = this.findField(fieldError.id);
2648                 if(f){
2649                     f.markInvalid(fieldError.msg);
2650                 }
2651             }
2652         }else{
2653             var field, id;
2654             for(id in errors){
2655                 if(typeof errors[id] != 'function' && (field = this.findField(id))){
2656                     field.markInvalid(errors[id]);
2657                 }
2658             }
2659         }
2660         //Roo.each(this.childForms || [], function (f) {
2661         //    f.markInvalid(errors);
2662         //});
2663         
2664         return this;
2665     },
2666
2667     /**
2668      * Set values for fields in this form in bulk.
2669      * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
2670      * @return {BasicForm} this
2671      */
2672     setValues : function(values){
2673         if(values instanceof Array){ // array of objects
2674             for(var i = 0, len = values.length; i < len; i++){
2675                 var v = values[i];
2676                 var f = this.findField(v.id);
2677                 if(f){
2678                     f.setValue(v.value);
2679                     if(this.trackResetOnLoad){
2680                         f.originalValue = f.getValue();
2681                     }
2682                 }
2683             }
2684         }else{ // object hash
2685             var field, id;
2686             for(id in values){
2687                 if(typeof values[id] != 'function' && (field = this.findField(id))){
2688                     
2689                     if (field.setFromData && 
2690                         field.valueField && 
2691                         field.displayField &&
2692                         // combos' with local stores can 
2693                         // be queried via setValue()
2694                         // to set their value..
2695                         (field.store && !field.store.isLocal)
2696                         ) {
2697                         // it's a combo
2698                         var sd = { };
2699                         sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
2700                         sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
2701                         field.setFromData(sd);
2702                         
2703                     } else {
2704                         field.setValue(values[id]);
2705                     }
2706                     
2707                     
2708                     if(this.trackResetOnLoad){
2709                         field.originalValue = field.getValue();
2710                     }
2711                 }
2712             }
2713         }
2714          
2715         //Roo.each(this.childForms || [], function (f) {
2716         //    f.setValues(values);
2717         //});
2718                 
2719         return this;
2720     },
2721
2722     /**
2723      * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
2724      * they are returned as an array.
2725      * @param {Boolean} asString
2726      * @return {Object}
2727      */
2728     getValues : function(asString){
2729         //if (this.childForms) {
2730             // copy values from the child forms
2731         //    Roo.each(this.childForms, function (f) {
2732         //        this.setValues(f.getValues());
2733         //    }, this);
2734         //}
2735         
2736         
2737         
2738         var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
2739         if(asString === true){
2740             return fs;
2741         }
2742         return Roo.urlDecode(fs);
2743     },
2744     
2745     /**
2746      * Returns the fields in this form as an object with key/value pairs. 
2747      * This differs from getValues as it calls getValue on each child item, rather than using dom data.
2748      * @return {Object}
2749      */
2750     getFieldValues : function(with_hidden)
2751     {
2752         var items = this.getItems();
2753         var ret = {};
2754         items.each(function(f){
2755             if (!f.getName()) {
2756                 return;
2757             }
2758             var v = f.getValue();
2759             if (f.inputType =='radio') {
2760                 if (typeof(ret[f.getName()]) == 'undefined') {
2761                     ret[f.getName()] = ''; // empty..
2762                 }
2763                 
2764                 if (!f.el.dom.checked) {
2765                     return;
2766                     
2767                 }
2768                 v = f.el.dom.value;
2769                 
2770             }
2771             
2772             // not sure if this supported any more..
2773             if ((typeof(v) == 'object') && f.getRawValue) {
2774                 v = f.getRawValue() ; // dates..
2775             }
2776             // combo boxes where name != hiddenName...
2777             if (f.name != f.getName()) {
2778                 ret[f.name] = f.getRawValue();
2779             }
2780             ret[f.getName()] = v;
2781         });
2782         
2783         return ret;
2784     },
2785
2786     /**
2787      * Clears all invalid messages in this form.
2788      * @return {BasicForm} this
2789      */
2790     clearInvalid : function(){
2791         var items = this.getItems();
2792         
2793         items.each(function(f){
2794            f.clearInvalid();
2795         });
2796         
2797         
2798         
2799         return this;
2800     },
2801
2802     /**
2803      * Resets this form.
2804      * @return {BasicForm} this
2805      */
2806     reset : function(){
2807         var items = this.getItems();
2808         items.each(function(f){
2809             f.reset();
2810         });
2811         
2812         Roo.each(this.childForms || [], function (f) {
2813             f.reset();
2814         });
2815        
2816         
2817         return this;
2818     },
2819     getItems : function()
2820     {
2821         var r=new Roo.util.MixedCollection(false, function(o){
2822             return o.id || (o.id = Roo.id());
2823         });
2824         var iter = function(el) {
2825             if (el.inputEl) {
2826                 r.add(el);
2827             }
2828             if (!el.items) {
2829                 return;
2830             }
2831             Roo.each(el.items,function(e) {
2832                 iter(e);
2833             });
2834             
2835             
2836         };
2837         iter(this);
2838         return r;
2839         
2840         
2841         
2842         
2843     }
2844     
2845 });
2846
2847  
2848 /*
2849  * Based on:
2850  * Ext JS Library 1.1.1
2851  * Copyright(c) 2006-2007, Ext JS, LLC.
2852  *
2853  * Originally Released Under LGPL - original licence link has changed is not relivant.
2854  *
2855  * Fork - LGPL
2856  * <script type="text/javascript">
2857  */
2858 /**
2859  * @class Roo.form.VTypes
2860  * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
2861  * @singleton
2862  */
2863 Roo.form.VTypes = function(){
2864     // closure these in so they are only created once.
2865     var alpha = /^[a-zA-Z_]+$/;
2866     var alphanum = /^[a-zA-Z0-9_]+$/;
2867     var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
2868     var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
2869
2870     // All these messages and functions are configurable
2871     return {
2872         /**
2873          * The function used to validate email addresses
2874          * @param {String} value The email address
2875          */
2876         'email' : function(v){
2877             return email.test(v);
2878         },
2879         /**
2880          * The error text to display when the email validation function returns false
2881          * @type String
2882          */
2883         'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
2884         /**
2885          * The keystroke filter mask to be applied on email input
2886          * @type RegExp
2887          */
2888         'emailMask' : /[a-z0-9_\.\-@]/i,
2889
2890         /**
2891          * The function used to validate URLs
2892          * @param {String} value The URL
2893          */
2894         'url' : function(v){
2895             return url.test(v);
2896         },
2897         /**
2898          * The error text to display when the url validation function returns false
2899          * @type String
2900          */
2901         'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
2902         
2903         /**
2904          * The function used to validate alpha values
2905          * @param {String} value The value
2906          */
2907         'alpha' : function(v){
2908             return alpha.test(v);
2909         },
2910         /**
2911          * The error text to display when the alpha validation function returns false
2912          * @type String
2913          */
2914         'alphaText' : 'This field should only contain letters and _',
2915         /**
2916          * The keystroke filter mask to be applied on alpha input
2917          * @type RegExp
2918          */
2919         'alphaMask' : /[a-z_]/i,
2920
2921         /**
2922          * The function used to validate alphanumeric values
2923          * @param {String} value The value
2924          */
2925         'alphanum' : function(v){
2926             return alphanum.test(v);
2927         },
2928         /**
2929          * The error text to display when the alphanumeric validation function returns false
2930          * @type String
2931          */
2932         'alphanumText' : 'This field should only contain letters, numbers and _',
2933         /**
2934          * The keystroke filter mask to be applied on alphanumeric input
2935          * @type RegExp
2936          */
2937         'alphanumMask' : /[a-z0-9_]/i
2938     };
2939 }();/*
2940  * - LGPL
2941  *
2942  * Input
2943  * 
2944  */
2945
2946 /**
2947  * @class Roo.bootstrap.Input
2948  * @extends Roo.bootstrap.Component
2949  * Bootstrap Input class
2950  * @cfg {Boolean} disabled is it disabled
2951  * @cfg {String} fieldLabel - the label associated
2952  * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
2953  * @cfg {String} name name of the input
2954  * @cfg {string} fieldLabel - the label associated
2955  * @cfg {string}  inputType - input / file submit ...
2956  * @cfg {string} placeholder - placeholder to put in text.
2957  * @cfg {string}  before - input group add on before
2958  * @cfg {string} after - input group add on after
2959  * 
2960  * 
2961  * @constructor
2962  * Create a new Input
2963  * @param {Object} config The config object
2964  */
2965
2966 Roo.bootstrap.Input = function(config){
2967     Roo.bootstrap.Input.superclass.constructor.call(this, config);
2968    
2969         this.addEvents({
2970             /**
2971              * @event focus
2972              * Fires when this field receives input focus.
2973              * @param {Roo.form.Field} this
2974              */
2975             focus : true,
2976             /**
2977              * @event blur
2978              * Fires when this field loses input focus.
2979              * @param {Roo.form.Field} this
2980              */
2981             blur : true,
2982             /**
2983              * @event specialkey
2984              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
2985              * {@link Roo.EventObject#getKey} to determine which key was pressed.
2986              * @param {Roo.form.Field} this
2987              * @param {Roo.EventObject} e The event object
2988              */
2989             specialkey : true,
2990             /**
2991              * @event change
2992              * Fires just before the field blurs if the field value has changed.
2993              * @param {Roo.form.Field} this
2994              * @param {Mixed} newValue The new value
2995              * @param {Mixed} oldValue The original value
2996              */
2997             change : true,
2998             /**
2999              * @event invalid
3000              * Fires after the field has been marked as invalid.
3001              * @param {Roo.form.Field} this
3002              * @param {String} msg The validation message
3003              */
3004             invalid : true,
3005             /**
3006              * @event valid
3007              * Fires after the field has been validated with no errors.
3008              * @param {Roo.form.Field} this
3009              */
3010             valid : true,
3011              /**
3012              * @event keyup
3013              * Fires after the key up
3014              * @param {Roo.form.Field} this
3015              * @param {Roo.EventObject}  e The event Object
3016              */
3017             keyup : true
3018         });
3019 };
3020
3021 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
3022      /**
3023      * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
3024       automatic validation (defaults to "keyup").
3025      */
3026     validationEvent : "keyup",
3027      /**
3028      * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
3029      */
3030     validateOnBlur : true,
3031     /**
3032      * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
3033      */
3034     validationDelay : 250,
3035      /**
3036      * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
3037      */
3038     focusClass : "x-form-focus",  // not needed???
3039     
3040        
3041     /**
3042      * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
3043      */
3044     invalidClass : "has-error",
3045     
3046     /**
3047      * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
3048      */
3049     selectOnFocus : false,
3050     
3051      /**
3052      * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
3053      */
3054     maskRe : null,
3055        /**
3056      * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
3057      */
3058     vtype : null,
3059     
3060       /**
3061      * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
3062      */
3063     disableKeyFilter : false,
3064     
3065        /**
3066      * @cfg {Boolean} disabled True to disable the field (defaults to false).
3067      */
3068     disabled : false,
3069      /**
3070      * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
3071      */
3072     allowBlank : true,
3073     /**
3074      * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
3075      */
3076     blankText : "This field is required",
3077     
3078      /**
3079      * @cfg {Number} minLength Minimum input field length required (defaults to 0)
3080      */
3081     minLength : 0,
3082     /**
3083      * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
3084      */
3085     maxLength : Number.MAX_VALUE,
3086     /**
3087      * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
3088      */
3089     minLengthText : "The minimum length for this field is {0}",
3090     /**
3091      * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
3092      */
3093     maxLengthText : "The maximum length for this field is {0}",
3094   
3095     
3096     /**
3097      * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
3098      * If available, this function will be called only after the basic validators all return true, and will be passed the
3099      * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
3100      */
3101     validator : null,
3102     /**
3103      * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
3104      * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
3105      * current field value.  If the test fails, the field will be marked invalid using {@link #regexText}.
3106      */
3107     regex : null,
3108     /**
3109      * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
3110      */
3111     regexText : "",
3112     
3113     
3114     
3115     fieldLabel : '',
3116     inputType : 'text',
3117     
3118     name : false,
3119     placeholder: false,
3120     before : false,
3121     after : false,
3122     
3123     // private
3124     hasFocus : false,
3125     preventMark: false,
3126     
3127     getAutoCreate : function(){
3128         
3129         var parent = this.parent();
3130         
3131         var align = parent.labelAlign;
3132         
3133         var id = Roo.id();
3134         
3135         var cfg = {
3136             cls: 'form-group' //input-group
3137         };
3138         
3139         var input =  {
3140             tag: 'input',
3141             id : id,
3142             type : this.inputType,
3143             cls : 'form-control',
3144             placeholder : this.placeholder || '' 
3145             
3146         };
3147         if (this.name) {
3148             input.name = this.name;
3149         }
3150         
3151         var inputblock = input;
3152         
3153         if (this.before || this.after) {
3154             
3155             inputblock = {
3156                 cls : 'input-group',
3157                 cn :  [] 
3158             };
3159             if (this.before) {
3160                 inputblock.cn.push({
3161                     tag :'span',
3162                     cls : 'input-group-addon',
3163                     html : this.before
3164                 });
3165             }
3166             inputblock.cn.push(input);
3167             if (this.after) {
3168                 inputblock.cn.push({
3169                     tag :'span',
3170                     cls : 'input-group-addon',
3171                     html : this.after
3172                 });
3173             }
3174             
3175         }
3176         
3177         Roo.log(align);
3178         Roo.log(this.fieldLabel.length);
3179         
3180         if (align ==='left' && this.fieldLabel.length) {
3181                 Roo.log("left and has label");
3182                 cfg.cn = [
3183                     
3184                     {
3185                         tag: 'label',
3186                         'for' :  id,
3187                         cls : 'col-sm-2 control-label',
3188                         html : this.fieldLabel
3189                         
3190                     },
3191                     {
3192                         cls : "col-sm-10", 
3193                         cn: [
3194                             inputblock
3195                         ]
3196                     }
3197                     
3198                 ];
3199         } else if ( this.fieldLabel.length) {
3200                 Roo.log(" label");
3201                  cfg.cn = [
3202                    
3203                     {
3204                         tag: 'label',
3205                         //cls : 'input-group-addon',
3206                         html : this.fieldLabel
3207                         
3208                     },
3209                     
3210                     inputblock
3211                     
3212                 ];
3213
3214         } else {
3215             
3216                    Roo.log(" no label && no align");
3217                 cfg.cn = [
3218                     
3219                         inputblock
3220                     
3221                 ];
3222                 
3223                 
3224         }
3225          
3226         
3227         
3228         
3229         if (this.disabled) {
3230             input.disabled=true;
3231         }
3232         return cfg;
3233         
3234     },
3235     /**
3236      * return the real input element.
3237      */
3238     inputEl: function ()
3239     {
3240         return this.el.select('input.form-control',true).first();
3241     },
3242     setDisabled : function(v)
3243     {
3244         var i  = this.inputEl().dom;
3245         if (v) {
3246             i.removeAttribute('disabled');
3247             return;
3248             
3249         }
3250         i.setAttribute('disabled','true');
3251     },
3252     initEvents : function()
3253     {
3254         
3255         this.inputEl().on("keydown" , this.fireKey,  this);
3256         this.inputEl().on("focus", this.onFocus,  this);
3257         this.inputEl().on("blur", this.onBlur,  this);
3258         this.inputEl().relayEvent('keyup', this);
3259
3260         // reference to original value for reset
3261         this.originalValue = this.getValue();
3262         //Roo.form.TextField.superclass.initEvents.call(this);
3263         if(this.validationEvent == 'keyup'){
3264             this.validationTask = new Roo.util.DelayedTask(this.validate, this);
3265             this.inputEl().on('keyup', this.filterValidation, this);
3266         }
3267         else if(this.validationEvent !== false){
3268             this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
3269         }
3270         
3271         if(this.selectOnFocus){
3272             this.on("focus", this.preFocus, this);
3273             
3274         }
3275         if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
3276             this.inputEl().on("keypress", this.filterKeys, this);
3277         }
3278        /* if(this.grow){
3279             this.el.on("keyup", this.onKeyUp,  this, {buffer:50});
3280             this.el.on("click", this.autoSize,  this);
3281         }
3282         */
3283         if(this.inputEl().is('input[type=password]') && Roo.isSafari){
3284             this.inputEl().on('keydown', this.SafariOnKeyDown, this);
3285         }
3286         
3287     },
3288     filterValidation : function(e){
3289         if(!e.isNavKeyPress()){
3290             this.validationTask.delay(this.validationDelay);
3291         }
3292     },
3293      /**
3294      * Validates the field value
3295      * @return {Boolean} True if the value is valid, else false
3296      */
3297     validate : function(){
3298         //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
3299         if(this.disabled || this.validateValue(this.getRawValue())){
3300             this.clearInvalid();
3301             return true;
3302         }
3303         return false;
3304     },
3305     
3306     
3307     /**
3308      * Validates a value according to the field's validation rules and marks the field as invalid
3309      * if the validation fails
3310      * @param {Mixed} value The value to validate
3311      * @return {Boolean} True if the value is valid, else false
3312      */
3313     validateValue : function(value){
3314         if(value.length < 1)  { // if it's blank
3315              if(this.allowBlank){
3316                 this.clearInvalid();
3317                 return true;
3318              }else{
3319                 this.markInvalid(this.blankText);
3320                 return false;
3321              }
3322         }
3323         if(value.length < this.minLength){
3324             this.markInvalid(String.format(this.minLengthText, this.minLength));
3325             return false;
3326         }
3327         if(value.length > this.maxLength){
3328             this.markInvalid(String.format(this.maxLengthText, this.maxLength));
3329             return false;
3330         }
3331         if(this.vtype){
3332             var vt = Roo.form.VTypes;
3333             if(!vt[this.vtype](value, this)){
3334                 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
3335                 return false;
3336             }
3337         }
3338         if(typeof this.validator == "function"){
3339             var msg = this.validator(value);
3340             if(msg !== true){
3341                 this.markInvalid(msg);
3342                 return false;
3343             }
3344         }
3345         if(this.regex && !this.regex.test(value)){
3346             this.markInvalid(this.regexText);
3347             return false;
3348         }
3349         return true;
3350     },
3351
3352     
3353     
3354      // private
3355     fireKey : function(e){
3356         //Roo.log('field ' + e.getKey());
3357         if(e.isNavKeyPress()){
3358             this.fireEvent("specialkey", this, e);
3359         }
3360     },
3361     onFocus : function(){
3362         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3363            // this.el.addClass(this.focusClass);
3364         }
3365         if(!this.hasFocus){
3366             this.hasFocus = true;
3367             this.startValue = this.getValue();
3368             this.fireEvent("focus", this);
3369         }
3370     },
3371     
3372     beforeBlur : Roo.emptyFn,
3373
3374     
3375     // private
3376     onBlur : function(){
3377         this.beforeBlur();
3378         if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3379             //this.el.removeClass(this.focusClass);
3380         }
3381         this.hasFocus = false;
3382         if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
3383             this.validate();
3384         }
3385         var v = this.getValue();
3386         if(String(v) !== String(this.startValue)){
3387             this.fireEvent('change', this, v, this.startValue);
3388         }
3389         this.fireEvent("blur", this);
3390     },
3391      /**
3392      * Returns the normalized data value (undefined or emptyText will be returned as '').  To return the raw value see {@link #getRawValue}.
3393      * @return {Mixed} value The field value
3394      */
3395     getValue : function(){
3396         var v = this.inputEl().getValue();
3397         return v;
3398     },
3399     /**
3400      * Returns the raw data value which may or may not be a valid, defined value.  To return a normalized value see {@link #getValue}.
3401      * @return {Mixed} value The field value
3402      */
3403     getRawValue : function(){
3404         var v = this.inputEl().getValue();
3405         
3406         return v;
3407     },
3408     /**
3409      * Sets a data value into the field and validates it.  To set the value directly without validation see {@link #setRawValue}.
3410      * @param {Mixed} value The value to set
3411      */
3412     setValue : function(v){
3413         this.value = v;
3414         if(this.rendered){
3415             this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
3416             this.validate();
3417         }
3418     },
3419     
3420     /*
3421     processValue : function(value){
3422         if(this.stripCharsRe){
3423             var newValue = value.replace(this.stripCharsRe, '');
3424             if(newValue !== value){
3425                 this.setRawValue(newValue);
3426                 return newValue;
3427             }
3428         }
3429         return value;
3430     },
3431   */
3432     preFocus : function(){
3433         
3434         if(this.selectOnFocus){
3435             this.inputEl().dom.select();
3436         }
3437     },
3438     filterKeys : function(e){
3439         var k = e.getKey();
3440         if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
3441             return;
3442         }
3443         var c = e.getCharCode(), cc = String.fromCharCode(c);
3444         if(Roo.isIE && (e.isSpecialKey() || !cc)){
3445             return;
3446         }
3447         if(!this.maskRe.test(cc)){
3448             e.stopEvent();
3449         }
3450     },
3451      /**
3452      * Clear any invalid styles/messages for this field
3453      */
3454     clearInvalid : function(){
3455         
3456         if(!this.el || this.preventMark){ // not rendered
3457             return;
3458         }
3459         this.el.removeClass(this.invalidClass);
3460         /*
3461         switch(this.msgTarget){
3462             case 'qtip':
3463                 this.el.dom.qtip = '';
3464                 break;
3465             case 'title':
3466                 this.el.dom.title = '';
3467                 break;
3468             case 'under':
3469                 if(this.errorEl){
3470                     Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
3471                 }
3472                 break;
3473             case 'side':
3474                 if(this.errorIcon){
3475                     this.errorIcon.dom.qtip = '';
3476                     this.errorIcon.hide();
3477                     this.un('resize', this.alignErrorIcon, this);
3478                 }
3479                 break;
3480             default:
3481                 var t = Roo.getDom(this.msgTarget);
3482                 t.innerHTML = '';
3483                 t.style.display = 'none';
3484                 break;
3485         }
3486         */
3487         this.fireEvent('valid', this);
3488     },
3489      /**
3490      * Mark this field as invalid
3491      * @param {String} msg The validation message
3492      */
3493     markInvalid : function(msg){
3494         if(!this.el  || this.preventMark){ // not rendered
3495             return;
3496         }
3497         this.el.addClass(this.invalidClass);
3498         /*
3499         msg = msg || this.invalidText;
3500         switch(this.msgTarget){
3501             case 'qtip':
3502                 this.el.dom.qtip = msg;
3503                 this.el.dom.qclass = 'x-form-invalid-tip';
3504                 if(Roo.QuickTips){ // fix for floating editors interacting with DND
3505                     Roo.QuickTips.enable();
3506                 }
3507                 break;
3508             case 'title':
3509                 this.el.dom.title = msg;
3510                 break;
3511             case 'under':
3512                 if(!this.errorEl){
3513                     var elp = this.el.findParent('.x-form-element', 5, true);
3514                     this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
3515                     this.errorEl.setWidth(elp.getWidth(true)-20);
3516                 }
3517                 this.errorEl.update(msg);
3518                 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
3519                 break;
3520             case 'side':
3521                 if(!this.errorIcon){
3522                     var elp = this.el.findParent('.x-form-element', 5, true);
3523                     this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
3524                 }
3525                 this.alignErrorIcon();
3526                 this.errorIcon.dom.qtip = msg;
3527                 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
3528                 this.errorIcon.show();
3529                 this.on('resize', this.alignErrorIcon, this);
3530                 break;
3531             default:
3532                 var t = Roo.getDom(this.msgTarget);
3533                 t.innerHTML = msg;
3534                 t.style.display = this.msgDisplay;
3535                 break;
3536         }
3537         */
3538         this.fireEvent('invalid', this, msg);
3539     },
3540     // private
3541     SafariOnKeyDown : function(event)
3542     {
3543         // this is a workaround for a password hang bug on chrome/ webkit.
3544         
3545         var isSelectAll = false;
3546         
3547         if(this.inputEl().dom.selectionEnd > 0){
3548             isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
3549         }
3550         if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
3551             event.preventDefault();
3552             this.setValue('');
3553             return;
3554         }
3555         
3556         if(isSelectAll){ // backspace and delete key
3557             
3558             event.preventDefault();
3559             // this is very hacky as keydown always get's upper case.
3560             //
3561             var cc = String.fromCharCode(event.getCharCode());
3562             this.setValue( event.shiftKey ?  cc : cc.toLowerCase());
3563             
3564         }
3565         
3566         
3567     }
3568 });
3569
3570