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