4 * base class for bootstrap elements.
8 Roo.bootstrap = Roo.bootstrap || {};
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.)
19 * Do not use directly - it does not do anything..
20 * @param {Object} config The config object
25 Roo.bootstrap.Component = function(config){
26 Roo.bootstrap.Component.superclass.constructor.call(this, config);
29 Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, {
32 allowDomMove : false, // to stop relocations in parent onRender...
40 initEvents : function() { },
47 // returns the parent component..
48 return Roo.ComponentMgr.get(this.parentId)
54 onRender : function(ct, position)
56 // Roo.log("Call onRender: " + this.xtype);
58 Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
61 if (this.el.attr('xtype')) {
62 this.el.dom.removeAttribute('xtype');
71 var cfg = Roo.apply({}, this.getAutoCreate());
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];
82 cfg.cls += ' ' + this.cls;
84 if (this.style) { // fixme needs to support more complex style data.
85 cfg.style = this.style;
87 this.el = ct.createChild(cfg, position);
88 if(this.tabIndex !== undefined){
89 this.el.dom.setAttribute('tabIndex', this.tabIndex);
96 getChildContainer : function()
101 addxtype : function (tree, cntr) {
103 cntr = typeof(cntr == 'undefined' ) ? 'getChildContainer' : cntr;
105 // render the element if it's not BODY.
106 if (tree.xtype != 'Body') {
108 cn = Roo.factory(tree);
110 cn.parentType = this.xtype; //??
111 cn.parentId = this.id;
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') {
119 var echild = Roo.get(this[cntr]()).child('*[xtype]');
121 // Roo.log("found child for " + this.xtype +": " + echild.attr('xtype') );
123 //echild.dom.removeAttribute('xtype');
125 Roo.log("missing child for " + this.xtype);
128 cn.render(this[cntr]());
129 // then add the element..
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)));
142 if (typeof (tree.buttons) != 'undefined' && typeof(cn.getButtonContainer) == 'function') {
144 for(var i =0;i < tree.buttons.length;i++) {
145 nitems.push(cn.addxtype(Roo.apply({}, tree.buttons[i]), 'getButtonContainer'));
150 if (!tree.items || !tree.items.length) {
154 var items = tree.items;
157 //Roo.log(items.length);
159 for(var i =0;i < items.length;i++) {
160 nitems.push(cn.addxtype(Roo.apply({}, items[i])));
180 Roo.bootstrap.Body = function(config){
181 Roo.bootstrap.Body.superclass.constructor.call(this, config);
182 this.el = Roo.get(document.body);
185 Roo.extend(Roo.bootstrap.Body, Roo.bootstrap.Component, {
190 onRender : function(ct, position){
193 //this.el.addClass([this.fieldClass, this.cls]);
211 * @class Roo.bootstrap.ButtonGroup
212 * @extends Roo.bootstrap.Component
213 * Bootstrap ButtonGroup class
214 * @cfg {String} size lg | sm | xs (default empty normal)
215 * @cfg {String} align vertical | justified (default none)
216 * @cfg {String} direction up | down (default down)
217 * @cfg {Boolean} toolbar false | true
218 * @cfg {Boolean} btn true | false
223 * @param {Object} config The config object
226 Roo.bootstrap.ButtonGroup = function(config){
227 Roo.bootstrap.ButtonGroup.superclass.constructor.call(this, config);
230 Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component, {
238 getAutoCreate : function(){
244 cfg.html = this.html || cfg.html;
255 if (['vertical','justified'].indexOf(this.align)!==-1) {
256 cfg.cls = 'btn-group-' + this.align;
258 if (this.align == 'justified') {
259 console.log(this.items);
263 if (['lg','sm','xs'].indexOf(this.size)!==-1) {
264 cfg.cls += ' btn-group-' + this.size;
267 if (this.direction == 'up') {
268 cfg.cls += ' dropup' ;
284 * @class Roo.bootstrap.Button
285 * @extends Roo.bootstrap.Component
286 * Bootstrap Button class
287 * @cfg {String} html The button content
288 * @cfg {String} weight default (or empty) | primary | success | info | warning | danger
289 * @cfg {String} size empty | lg | sm | xs
290 * @cfg {String} tag empty | a | input | submit
291 * @cfg {String} href empty or href
292 * @cfg {Boolean} disabled false | true
293 * @cfg {Boolean} isClose false | true
294 * @cfg {String} glyphicon empty | adjust | align-center | align-justify | align-left | align-right | arrow-down | arrow-left | arrow-right | arrow-up | asterisk | backward | ban-circle | barcode | bell | bold | book | bookmark | briefcase | bullhorn | calendar | camera | certificate | check | chevron-down | chevron-left | chevron-right | chevron-up | circle-arrow-down | circle-arrow-left | circle-arrow-right | circle-arrow-up | cloud | cloud-download | cloud-upload | cog | collapse-down | collapse-up | comment | compressed | copyright-mark | credit-card | cutlery | dashboard | download | download-alt | earphone | edit | eject | envelope | euro | exclamation-sign | expand | export | eye-close | eye-open | facetime-video | fast-backward | fast-forward | file | film | filter | fire | flag | flash | floppy-disk | floppy-open | floppy-remove | floppy-save | floppy-saved | folder-close | folder-open | font | forward | fullscreen | gbp | gift | glass | globe | hand-down | hand-left | hand-right | hand-up | hd-video | hdd | header | headphones | heart | heart-empty | home | import | inbox | indent-left | indent-right | info-sign | italic | leaf | link | list | list-alt | lock | log-in | log-out | magnet | map-marker | minus | minus-sign | move | music | new-window | off | ok | ok-circle | ok-sign | open | paperclip | pause | pencil | phone | phone-alt | picture | plane | play | play-circle | plus | plus-sign | print | pushpin | qrcode | question-sign | random | record | refresh | registration-mark | remove | remove-circle | remove-sign | repeat | resize-full | resize-horizontal | resize-small | resize-vertical | retweet | road | save | saved | screenshot | sd-video | search | send | share | share-alt | shopping-cart | signal | sort | sort-by-alphabet | sort-by-alphabet-alt | sort-by-attributes | sort-by-attributes-alt | sort-by-order | sort-by-order-alt | sound-5-1 | sound-6-1 | sound-7-1 | sound-dolby | sound-stereo | star | star-empty | stats | step-backward | step-forward | stop | subtitles | tag | tags | tasks | text-height | text-width | th | th-large | th-list | thumbs-down | thumbs-up | time | tint | tower | transfer | trash | tree-conifer | tree-deciduous | unchecked | upload | usd | user | volume-down | volume-off | volume-up | warning-sign | wrench | zoom-in | zoom-out
295 * @cfg {String} badge text for badge
296 * @cfg {String} theme default (or empty) | glow
297 * @cfg {Boolean} inverse false | true
298 * @cfg {Boolean} toggle false | true
299 * @cfg {String} ontext text for on toggle state
300 * @cfg {String} offtext text for off toggle state
301 * @cfg {Boolean} defaulton true | false
304 * Create a new button
305 * @param {Object} config The config object
309 Roo.bootstrap.Button = function(config){
310 Roo.bootstrap.Button.superclass.constructor.call(this, config);
315 * The raw click event for the entire grid.
316 * @param {Roo.EventObject} e
322 Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component, {
341 getAutoCreate : function(){
349 if (['a', 'button', 'input', 'submit'].indexOf(this.tag) < 0) {
350 throw "Invalid value for tag: " + this.tag + ". must be a, button, input or submit.";
355 cfg.html = this.html || cfg.html;
357 if (this.toggle===true) {
360 cls: 'slider-frame roo-button',
365 'data-off-text':'OFF',
366 cls: 'slider-button',
372 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
373 cfg.cls += ' '+this.weight;
382 cfg["aria-hidden"] = true;
384 cfg.html = "×";
390 if (this.theme==='default') {
391 cfg.cls = 'btn roo-button';
393 if (this.parentType != 'Navbar') {
394 this.weight = this.weight.length ? this.weight : 'default';
396 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
398 cfg.cls += ' btn-' + this.weight;
400 } else if (this.theme==='glow') {
403 cfg.cls = 'btn-glow roo-button';
405 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
407 cfg.cls += ' ' + this.weight;
413 this.cls += ' inverse';
418 cfg.cls += ' active';
421 cfg.cls += this.size.length ? (' btn-' + this.size) : '';
423 //gsRoo.log(this.parentType);
424 if (this.parentType === 'Navbar') {
432 href : this.href || '#'
435 cfg.cn[0].html = this.html + ' <span class="caret"></span>';
436 cfg.cls += ' dropdown';
441 } else if (this.menu) {
443 cfg.cls += ' dropdown test';
449 cfg.disabled = 'disabled';
453 Roo.log('changing to ul' );
455 this.glyphicon = 'caret';
458 if (this.glyphicon) {
459 cfg.html = ' ' + cfg.html;
464 cls: 'glyphicon glyphicon-' + this.glyphicon
474 cfg.cls='btn roo-button';
490 if (cfg.tag !== 'a' && this.href !== '') {
491 throw "Tag must be a to set href.";
492 } else if (this.href.length > 0) {
493 cfg.href = this.href;
498 initEvents: function() {
499 // Roo.log('init events?');
500 // Roo.log(this.el.dom);
501 if (this.el.hasClass('roo-button')) {
502 this.el.on('click', this.onClick, this);
504 this.el.select('.roo-button').on('click', this.onClick, this);
510 onClick : function(e)
512 Roo.log('button on click ');
514 this.fireEvent('click', this, e);
528 * @class Roo.bootstrap.Column
529 * @extends Roo.bootstrap.Component
530 * Bootstrap Column class
531 * @cfg {Number} xs colspan out of 12 for mobile-sized screens
532 * @cfg {Number} sm colspan out of 12 for tablet-sized screens
533 * @cfg {Number} md colspan out of 12 for computer-sized screens
534 * @cfg {Number} lg colspan out of 12 for large computer-sized screens
535 * @cfg {String} html content of column.
538 * Create a new Column
539 * @param {Object} config The config object
542 Roo.bootstrap.Column = function(config){
543 Roo.bootstrap.Column.superclass.constructor.call(this, config);
546 Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component, {
555 getAutoCreate : function(){
556 var cfg = Roo.apply({}, Roo.bootstrap.Column.superclass.getAutoCreate.call(this));
564 ['xs','sm','md','lg'].map(function(size){
565 if (settings[size]) {
566 cfg.cls += ' col-' + size + '-' + settings[size];
569 if (this.html.length) {
570 cfg.html = this.html;
589 * @class Roo.bootstrap.Container
590 * @extends Roo.bootstrap.Component
591 * Bootstrap Container class
592 * @cfg {Boolean} jumbotron is it a jumbotron element
593 * @cfg {String} html content of element
594 * @cfg {String} well (lg|sm|md) a well, large, small or medium.
595 * @cfg {String} panel (primary|success|info|warning|danger) render as a panel.
596 * @cfg {String} header content of header (for panel)
597 * @cfg {String} footer content of footer (for panel)
598 * @cfg {String} sticky (footer|wrap|push) block to use as footer or body- needs css-bootstrap/sticky-footer.css
601 * Create a new Container
602 * @param {Object} config The config object
605 Roo.bootstrap.Container = function(config){
606 Roo.bootstrap.Container.superclass.constructor.call(this, config);
609 Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component, {
619 getChildContainer : function() {
620 if (this.panel.length) {
621 return this.el.select('.panel-body',true).first();
628 getAutoCreate : function(){
634 if (this.jumbotron) {
635 cfg.cls = 'jumbotron';
638 cfg.cls = this.cls + '';
641 if (this.sticky.length) {
642 var bd = Roo.get(document.body);
643 if (!bd.hasClass('bootstrap-sticky')) {
644 bd.addClass('bootstrap-sticky');
645 Roo.select('html',true).setStyle('height', '100%');
648 cfg.cls += 'bootstrap-sticky-' + this.sticky;
652 if (this.well.length) {
656 cfg.cls +=' well well-' +this.well;
666 if (this.panel.length) {
667 cfg.cls += 'panel panel-' + this.panel;
669 if (this.header.length) {
672 cls : 'panel-heading',
688 if (this.footer.length) {
690 cls : 'panel-footer',
698 body.html = this.html || cfg.html;
700 if (!cfg.cls.length) {
701 cfg.cls = 'container';
718 * @class Roo.bootstrap.Img
719 * @extends Roo.bootstrap.Component
720 * Bootstrap Img class
721 * @cfg {Boolean} imgResponsive false | true
722 * @cfg {String} border rounded | circle | thumbnail
723 * @cfg {String} src image source
724 * @cfg {String} alt image alternative text
728 * @param {Object} config The config object
731 Roo.bootstrap.Img = function(config){
732 Roo.bootstrap.Img.superclass.constructor.call(this, config);
735 Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component, {
741 getAutoCreate : function(){
745 cls: 'img-responsive',
749 cfg.html = this.html || cfg.html;
751 cfg.src = this.src || cfg.src;
753 if (['rounded','circle','thumbnail'].indexOf(this.border)>-1) {
754 cfg.cls += ' img-' + this.border;
774 * @class Roo.bootstrap.Header
775 * @extends Roo.bootstrap.Component
776 * Bootstrap Header class
777 * @cfg {String} html content of header
778 * @cfg {Number} level (1|2|3|4|5|6) default 1
781 * Create a new Header
782 * @param {Object} config The config object
786 Roo.bootstrap.Header = function(config){
787 Roo.bootstrap.Header.superclass.constructor.call(this, config);
790 Roo.extend(Roo.bootstrap.Header, Roo.bootstrap.Component, {
798 getAutoCreate : function(){
801 tag: 'h' + (1 *this.level),
802 html: this.html || 'fill in html'
820 * @class Roo.bootstrap.Menu
821 * @extends Roo.bootstrap.Component
822 * Bootstrap Menu class - container for MenuItems
823 * @cfg {String} type type of menu
827 * @param {Object} config The config object
831 Roo.bootstrap.Menu = function(config){
832 Roo.bootstrap.Menu.superclass.constructor.call(this, config);
835 Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, {
843 getChildContainer : function() {
847 getAutoCreate : function(){
849 //if (['right'].indexOf(this.align)!==-1) {
850 // cfg.cn[1].cls += ' pull-right'
854 cls : 'dropdown-menu'
858 if (this.type==='submenu') {
859 cfg.cls='submenu active'
864 initEvents : function() {
865 // Roo.log("ADD event");
866 // Roo.log(this.triggerEl.dom);
867 this.triggerEl.on('click', this.toggle, this);
868 this.triggerEl.addClass('dropdown-toggle');
873 //Roo.log(e.getTarget());
874 // Roo.log(this.triggerEl.dom);
875 if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
878 var isActive = this.triggerEl.hasClass('open');
879 // if disabled.. ingore
881 //if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
882 // if mobile we use a backdrop because click events don't delegate
883 // $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
886 //var relatedTarget = { relatedTarget: this }
887 //$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
889 //if (e.isDefaultPrevented()) return;
891 this.triggerEl[isActive ? 'removeClass' : 'addClass']('open');
893 // .trigger('shown.bs.dropdown', relatedTarget)
895 this.triggerEl.focus();
901 clearMenus : function()
903 //$(backdrop).remove()
904 Roo.select('.dropdown-toggle',true).each(function(aa) {
905 if (!aa.hasClass('open')) {
909 aa.removeClass('open');
910 //var parent = getParent($(this))
911 //var relatedTarget = { relatedTarget: this }
913 //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
914 //if (e.isDefaultPrevented()) return
915 //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
933 * @class Roo.bootstrap.MenuItem
934 * @extends Roo.bootstrap.Component
935 * Bootstrap MenuItem class
936 * @cfg {String} html the menu label
937 * @cfg {String} href the link
941 * Create a new MenuItem
942 * @param {Object} config The config object
946 Roo.bootstrap.MenuItem = function(config){
947 Roo.bootstrap.MenuItem.superclass.constructor.call(this, config);
950 Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component, {
955 getAutoCreate : function(){
967 cfg.cn[0].href = this.href || cfg.cn[0].href ;
968 cfg.cn[0].html = this.html || cfg.cn[0].html ;
985 * @class Roo.bootstrap.MenuSeparator
986 * @extends Roo.bootstrap.Component
987 * Bootstrap MenuSeparator class
990 * Create a new MenuItem
991 * @param {Object} config The config object
995 Roo.bootstrap.MenuSeparator = function(config){
996 Roo.bootstrap.MenuSeparator.superclass.constructor.call(this, config);
999 Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component, {
1001 getAutoCreate : function(){
1016 <div class="modal fade">
1017 <div class="modal-dialog">
1018 <div class="modal-content">
1019 <div class="modal-header">
1020 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
1021 <h4 class="modal-title">Modal title</h4>
1023 <div class="modal-body">
1024 <p>One fine body…</p>
1026 <div class="modal-footer">
1027 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
1028 <button type="button" class="btn btn-primary">Save changes</button>
1030 </div><!-- /.modal-content -->
1031 </div><!-- /.modal-dialog -->
1032 </div><!-- /.modal -->
1042 * @class Roo.bootstrap.Modal
1043 * @extends Roo.bootstrap.Component
1044 * Bootstrap Modal class
1045 * @cfg {String} title Title of dialog
1046 * @cfg {Array} buttons Array of buttons
1049 * Create a new Modal Dialog
1050 * @param {Object} config The config object
1053 Roo.bootstrap.Modal = function(config){
1054 Roo.bootstrap.Modal.superclass.constructor.call(this, config);
1057 Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component, {
1059 title : 'test dialog',
1063 onRender : function(ct, position)
1065 Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
1067 var cfg = Roo.apply({}, this.getAutoCreate());
1070 // cfg.name = typeof(this.name) == 'undefined' ? this.id : this.name;
1072 //if (!cfg.name.length) {
1076 cfg.cls += ' ' + this.cls;
1079 cfg.style = this.style;
1081 this.el = Roo.get(document.body).createChild(cfg, position);
1083 //var type = this.el.dom.type;
1085 if(this.tabIndex !== undefined){
1086 this.el.dom.setAttribute('tabIndex', this.tabIndex);
1091 this.maskEl = Roo.DomHelper.append(document.body, {tag: "div", cls:"x-dlg-mask"}, true);
1092 this.maskEl.enableDisplayMode("block");
1094 //this.el.addClass("x-dlg-modal");
1101 //this.el.addClass([this.fieldClass, this.cls]);
1104 getAutoCreate : function(){
1110 cls: "modal-dialog",
1113 cls : "modal-content",
1116 cls : 'modal-header',
1125 cls : 'modal-title',
1136 cls : 'modal-footer'
1141 cls : 'btn btn-default',
1146 cls : 'btn btn-primary',
1167 getChildContainer : function() {
1169 return this.el.select('.modal-body',true).first();
1172 getButtonContainer : function() {
1173 return this.el.select('.modal-footer',true).first();
1176 initEvents : function()
1178 this.el.select('.modal-header .close').on('click', this.hide, this);
1181 if (!this.rendered) {
1185 this.el.addClass('on');
1186 this.el.removeClass('fade');
1187 this.el.setStyle('display', 'block');
1188 Roo.get(document.body).addClass("x-body-masked");
1189 this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
1191 this.el.setStyle('zIndex', '10001');
1197 this.el.removeClass('on');
1198 this.el.addClass('fade');
1199 this.el.setStyle('display', 'none');
1211 * @class Roo.bootstrap.Navbar
1212 * @extends Roo.bootstrap.Component
1213 * Bootstrap Navbar class
1214 * @cfg {Boolean} sidebar has side bar
1215 * @cfg {Boolean} bar is a bar?
1216 * @cfg {String} position (fixed-top|fixed-bottom|static-top) position
1217 * @cfg {String} brand what is brand
1218 * @cfg {Boolean} inverse is inverted color
1219 * @cfg {String} type (nav | pills | tabs)
1220 * @cfg {Boolean} arrangement stacked | justified
1221 * @cfg {String} align (left | right) alignment
1225 * Create a new Navbar
1226 * @param {Object} config The config object
1230 Roo.bootstrap.Navbar = function(config){
1231 Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
1234 Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component, {
1246 getAutoCreate : function(){
1251 if (this.sidebar === true) {
1259 if (this.bar === true) {
1267 cls: 'navbar-header',
1272 cls: 'navbar-toggle',
1273 'data-toggle': 'collapse',
1278 html: 'Toggle navigation'
1298 cls: 'collapse navbar-collapse'
1303 cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
1305 if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
1306 cfg.cls += ' navbar-' + this.position;
1307 cfg.tag = this.position == 'fixed-bottom' ? 'footer' : 'header';
1310 if (this.brand !== '') {
1314 cls: 'navbar-brand',
1323 } else if (this.bar === false) {
1326 Roo.log('Property \'bar\' in of Navbar must be either true or false')
1336 if (['tabs','pills'].indexOf(this.type)!==-1) {
1337 cfg.cn[0].cls += ' nav-' + this.type
1339 if (this.type!=='nav') {
1340 Roo.log('nav type must be nav/tabs/pills')
1342 cfg.cn[0].cls += ' navbar-nav'
1345 if (['stacked','justified'].indexOf(this.arrangement)!==-1) {
1346 cfg.cn[0].cls += ' nav-' + this.arrangement;
1349 if (this.align === 'right') {
1350 cfg.cn[0].cls += ' navbar-right';
1353 cfg.cls += ' navbar-inverse';
1361 getChildContainer : function() {
1362 if (this.bar === true) {
1363 return this.el.select('.collapse',true).first();
1381 * @class Roo.bootstrap.NavGroup
1382 * @extends Roo.bootstrap.Component
1383 * Bootstrap NavGroup class
1384 * @cfg {String} align left | right
1385 * @cfg {Boolean} inverse false | true
1388 * Create a new nav group
1389 * @param {Object} config The config object
1392 Roo.bootstrap.NavGroup = function(config){
1393 Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
1396 Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component, {
1402 getAutoCreate : function(){
1403 var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
1407 cls: 'nav navbar-nav'
1410 if (this.parent().sidebar === true) {
1413 cls: 'dashboard-menu'
1419 if (this.form === true) {
1425 if (this.align === 'right') {
1426 cfg.cls += ' navbar-right';
1428 cfg.cls += ' navbar-left';
1433 if (this.align === 'right') {
1434 cfg.cls += ' navbar-right';
1438 cfg.cls += ' navbar-inverse';
1457 * @class Roo.bootstrap.Navbar.Button
1458 * @extends Roo.bootstrap.Component
1459 * Bootstrap Navbar.Button class
1460 * @cfg {String} href link to
1461 * @cfg {String} html content of button
1464 * Create a new Navbar Button
1465 * @param {Object} config The config object
1469 Roo.bootstrap.Navbar.Button = function(config){
1470 Roo.bootstrap.Navbar.Button.superclass.constructor.call(this, config);
1473 Roo.extend(Roo.bootstrap.Navbar.Button, Roo.bootstrap.Component, {
1484 getAutoCreate : function(){
1494 html : this.html || ''
1518 * @class Roo.bootstrap.Navbar.Item
1519 * @extends Roo.bootstrap.Component
1520 * Bootstrap Navbar.Button class
1521 * @cfg {String} href link to
1522 * @cfg {String} html content of button
1523 * @cfg {String} badge text inside badge
1524 * @cfg {String} glyphicon name of glyphicon
1527 * Create a new Navbar Button
1528 * @param {Object} config The config object
1530 Roo.bootstrap.Navbar.Item = function(config){
1531 Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
1534 Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component, {
1542 getAutoCreate : function(){
1544 var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
1546 if (this.parent().parent().sidebar === true) {
1559 cfg.cn[0].html = this.html;
1563 this.cls += ' active';
1567 cfg.cn[0].cls += ' dropdown-toggle';
1568 cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
1572 cfg.cn[0].tag = 'a',
1573 cfg.cn[0].href = this.href;
1576 if (this.glyphicon) {
1577 cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
1593 if (this.glyphicon) {
1594 if(cfg.html){cfg.html = ' ' + this.html};
1598 cls: 'glyphicon glyphicon-' + this.glyphicon
1603 cfg.cn[0].html = this.html || cfg.cn[0].html ;
1607 cfg.cn[0].html += " <span class='caret'></span>";
1608 //}else if (!this.href) {
1609 // cfg.cn[0].tag='p';
1610 // cfg.cn[0].cls='navbar-text';
1613 cfg.cn[0].href=this.href||'#';
1614 cfg.cn[0].html=this.html;
1617 if (this.badge !== '') {
1620 cfg.cn[0].html + ' ',
1633 initEvents: function() {
1634 // Roo.log('init events?');
1635 // Roo.log(this.el.dom);
1636 this.el.select('a',true).on('click',
1638 this.fireEvent('click', this);
1655 * @class Roo.bootstrap.Row
1656 * @extends Roo.bootstrap.Component
1657 * Bootstrap Row class (contains columns...)
1661 * @param {Object} config The config object
1664 Roo.bootstrap.Row = function(config){
1665 Roo.bootstrap.Row.superclass.constructor.call(this, config);
1668 Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component, {
1687 * @class Roo.bootstrap.Element
1688 * @extends Roo.bootstrap.Component
1689 * Bootstrap Element class
1690 * @cfg {String} html contents of the element
1691 * @cfg {String} tag tag of the element
1692 * @cfg {String} cls class of the element
1695 * Create a new Element
1696 * @param {Object} config The config object
1699 Roo.bootstrap.Element = function(config){
1700 Roo.bootstrap.Element.superclass.constructor.call(this, config);
1703 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component, {
1711 getAutoCreate : function(){
1712 var cfg = Roo.apply({}, Roo.bootstrap.Element.superclass.getAutoCreate.call(this));
1735 * @class Roo.bootstrap.Pagination
1736 * @extends Roo.bootstrap.Component
1737 * Bootstrap Pagination class
1738 * @cfg {String} size xs | sm | md | lg
1739 * @cfg {Boolean} inverse false | true
1740 * @cfg {Number} from pagination starting number
1741 * @cfg {Number} to pagination ending number
1742 * @cfg {String} align empty or left | right
1743 * @cfg {Number} active active page number
1746 * Create a new Pagination
1747 * @param {Object} config The config object
1750 Roo.bootstrap.Pagination = function(config){
1751 Roo.bootstrap.Pagination.superclass.constructor.call(this, config);
1754 Roo.extend(Roo.bootstrap.Pagination, Roo.bootstrap.Component, {
1764 getAutoCreate : function(){
1771 cfg.cls += ' inverse';
1789 var from=this.from>0?this.from:1;
1790 var to=this.to-from<=10?this.to:from+10;
1791 var active=this.active>=from&&this.active<=to?this.active:null;
1792 for (var i=from;i<=to;i++) {
1796 cls: active===i?'active':'',
1837 * @class Roo.bootstrap.Slider
1838 * @extends Roo.bootstrap.Component
1839 * Bootstrap Slider class
1842 * Create a new Slider
1843 * @param {Object} config The config object
1846 Roo.bootstrap.Slider = function(config){
1847 Roo.bootstrap.Slider.superclass.constructor.call(this, config);
1850 Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component, {
1852 getAutoCreate : function(){
1856 cls: 'slider slider-sample1 vertical-handler ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all',
1860 cls: 'ui-slider-handle ui-state-default ui-corner-all'
1878 * @class Roo.bootstrap.Table
1879 * @extends Roo.bootstrap.Component
1880 * Bootstrap Table class
1883 * Create a new Table
1884 * @param {Object} config The config object
1887 Roo.bootstrap.Table = function(config){
1888 Roo.bootstrap.Table.superclass.constructor.call(this, config);
1891 Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
1896 getAutoCreate : function(){
1897 var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
1929 * @class Roo.bootstrap.TableCell
1930 * @extends Roo.bootstrap.Component
1931 * Bootstrap TableCell class
1934 * Create a new TableCell
1935 * @param {Object} config The config object
1938 Roo.bootstrap.TableCell = function(config){
1939 Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
1942 Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component, {
1944 getAutoCreate : function(){
1945 var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
1972 * @class Roo.bootstrap.TableRow
1973 * @extends Roo.bootstrap.Component
1974 * Bootstrap TableRow class
1977 * Create a new TableRow
1978 * @param {Object} config The config object
1981 Roo.bootstrap.TableRow = function(config){
1982 Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
1985 Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component, {
1987 getAutoCreate : function(){
1988 var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
2003 * Ext JS Library 1.1.1
2004 * Copyright(c) 2006-2007, Ext JS, LLC.
2006 * Originally Released Under LGPL - original licence link has changed is not relivant.
2009 * <script type="text/javascript">
2012 // as we use this in bootstrap.
2013 Roo.namespace('Roo.form');
2015 * @class Roo.form.Action
2016 * Internal Class used to handle form actions
2018 * @param {Roo.form.BasicForm} el The form element or its id
2019 * @param {Object} config Configuration options
2024 // define the action interface
2025 Roo.form.Action = function(form, options){
2027 this.options = options || {};
2030 * Client Validation Failed
2033 Roo.form.Action.CLIENT_INVALID = 'client';
2035 * Server Validation Failed
2038 Roo.form.Action.SERVER_INVALID = 'server';
2040 * Connect to Server Failed
2043 Roo.form.Action.CONNECT_FAILURE = 'connect';
2045 * Reading Data from Server Failed
2048 Roo.form.Action.LOAD_FAILURE = 'load';
2050 Roo.form.Action.prototype = {
2052 failureType : undefined,
2053 response : undefined,
2057 run : function(options){
2062 success : function(response){
2067 handleResponse : function(response){
2071 // default connection failure
2072 failure : function(response){
2074 this.response = response;
2075 this.failureType = Roo.form.Action.CONNECT_FAILURE;
2076 this.form.afterAction(this, false);
2079 processResponse : function(response){
2080 this.response = response;
2081 if(!response.responseText){
2084 this.result = this.handleResponse(response);
2088 // utility functions used internally
2089 getUrl : function(appendParams){
2090 var url = this.options.url || this.form.url || this.form.el.dom.action;
2092 var p = this.getParams();
2094 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
2100 getMethod : function(){
2101 return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
2104 getParams : function(){
2105 var bp = this.form.baseParams;
2106 var p = this.options.params;
2108 if(typeof p == "object"){
2109 p = Roo.urlEncode(Roo.applyIf(p, bp));
2110 }else if(typeof p == 'string' && bp){
2111 p += '&' + Roo.urlEncode(bp);
2114 p = Roo.urlEncode(bp);
2119 createCallback : function(){
2121 success: this.success,
2122 failure: this.failure,
2124 timeout: (this.form.timeout*1000),
2125 upload: this.form.fileUpload ? this.success : undefined
2130 Roo.form.Action.Submit = function(form, options){
2131 Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
2134 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
2137 haveProgress : false,
2138 uploadComplete : false,
2140 // uploadProgress indicator.
2141 uploadProgress : function()
2143 if (!this.form.progressUrl) {
2147 if (!this.haveProgress) {
2148 Roo.MessageBox.progress("Uploading", "Uploading");
2150 if (this.uploadComplete) {
2151 Roo.MessageBox.hide();
2155 this.haveProgress = true;
2157 var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
2159 var c = new Roo.data.Connection();
2161 url : this.form.progressUrl,
2166 success : function(req){
2167 //console.log(data);
2171 rdata = Roo.decode(req.responseText)
2173 Roo.log("Invalid data from server..");
2177 if (!rdata || !rdata.success) {
2179 Roo.MessageBox.alert(Roo.encode(rdata));
2182 var data = rdata.data;
2184 if (this.uploadComplete) {
2185 Roo.MessageBox.hide();
2190 Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
2191 Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
2194 this.uploadProgress.defer(2000,this);
2197 failure: function(data) {
2198 Roo.log('progress url failed ');
2209 // run get Values on the form, so it syncs any secondary forms.
2210 this.form.getValues();
2212 var o = this.options;
2213 var method = this.getMethod();
2214 var isPost = method == 'POST';
2215 if(o.clientValidation === false || this.form.isValid()){
2217 if (this.form.progressUrl) {
2218 this.form.findField('UPLOAD_IDENTIFIER').setValue(
2219 (new Date() * 1) + '' + Math.random());
2224 Roo.Ajax.request(Roo.apply(this.createCallback(), {
2225 form:this.form.el.dom,
2226 url:this.getUrl(!isPost),
2228 params:isPost ? this.getParams() : null,
2229 isUpload: this.form.fileUpload
2232 this.uploadProgress();
2234 }else if (o.clientValidation !== false){ // client validation failed
2235 this.failureType = Roo.form.Action.CLIENT_INVALID;
2236 this.form.afterAction(this, false);
2240 success : function(response)
2242 this.uploadComplete= true;
2243 if (this.haveProgress) {
2244 Roo.MessageBox.hide();
2248 var result = this.processResponse(response);
2249 if(result === true || result.success){
2250 this.form.afterAction(this, true);
2254 this.form.markInvalid(result.errors);
2255 this.failureType = Roo.form.Action.SERVER_INVALID;
2257 this.form.afterAction(this, false);
2259 failure : function(response)
2261 this.uploadComplete= true;
2262 if (this.haveProgress) {
2263 Roo.MessageBox.hide();
2266 this.response = response;
2267 this.failureType = Roo.form.Action.CONNECT_FAILURE;
2268 this.form.afterAction(this, false);
2271 handleResponse : function(response){
2272 if(this.form.errorReader){
2273 var rs = this.form.errorReader.read(response);
2276 for(var i = 0, len = rs.records.length; i < len; i++) {
2277 var r = rs.records[i];
2281 if(errors.length < 1){
2285 success : rs.success,
2291 ret = Roo.decode(response.responseText);
2295 errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
2305 Roo.form.Action.Load = function(form, options){
2306 Roo.form.Action.Load.superclass.constructor.call(this, form, options);
2307 this.reader = this.form.reader;
2310 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
2315 Roo.Ajax.request(Roo.apply(
2316 this.createCallback(), {
2317 method:this.getMethod(),
2318 url:this.getUrl(false),
2319 params:this.getParams()
2323 success : function(response){
2325 var result = this.processResponse(response);
2326 if(result === true || !result.success || !result.data){
2327 this.failureType = Roo.form.Action.LOAD_FAILURE;
2328 this.form.afterAction(this, false);
2331 this.form.clearInvalid();
2332 this.form.setValues(result.data);
2333 this.form.afterAction(this, true);
2336 handleResponse : function(response){
2337 if(this.form.reader){
2338 var rs = this.form.reader.read(response);
2339 var data = rs.records && rs.records[0] ? rs.records[0].data : null;
2341 success : rs.success,
2345 return Roo.decode(response.responseText);
2349 Roo.form.Action.ACTION_TYPES = {
2350 'load' : Roo.form.Action.Load,
2351 'submit' : Roo.form.Action.Submit
2360 * @class Roo.bootstrap.Form
2361 * @extends Roo.bootstrap.Component
2362 * Bootstrap Form class
2363 * @cfg {String} method GET | POST (default POST)
2364 * @cfg {String} labelAlign top | left (default top)
2368 * @param {Object} config The config object
2372 Roo.bootstrap.Form = function(config){
2373 Roo.bootstrap.Form.superclass.constructor.call(this, config);
2376 * @event clientvalidation
2377 * If the monitorValid config option is true, this event fires repetitively to notify of valid state
2378 * @param {Form} this
2379 * @param {Boolean} valid true if the form has passed client-side validation
2381 clientvalidation: true,
2383 * @event beforeaction
2384 * Fires before any action is performed. Return false to cancel the action.
2385 * @param {Form} this
2386 * @param {Action} action The action to be performed
2390 * @event actionfailed
2391 * Fires when an action fails.
2392 * @param {Form} this
2393 * @param {Action} action The action that failed
2395 actionfailed : true,
2397 * @event actioncomplete
2398 * Fires when an action is completed.
2399 * @param {Form} this
2400 * @param {Action} action The action that completed
2402 actioncomplete : true
2407 Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component, {
2410 * @cfg {String} method
2411 * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
2416 * The URL to use for form actions if one isn't supplied in the action options.
2419 * @cfg {Boolean} fileUpload
2420 * Set to true if this form is a file upload.
2424 * @cfg {Object} baseParams
2425 * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
2429 * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
2434 activeAction : null,
2437 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2438 * element by passing it or its id or mask the form itself by passing in true.
2441 waitMsgTarget : false,
2446 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2447 * element by passing it or its id or mask the form itself by passing in true.
2451 getAutoCreate : function(){
2455 method : this.method || 'POST',
2456 id : this.id || Roo.id(),
2460 if (this.labelAlign == 'left' ) {
2461 cfg.cls += ' form-horizontal';
2465 initEvents : function()
2467 this.el.on('submit', this.onSubmit, this);
2472 onSubmit : function(e){
2477 * Returns true if client-side validation on the form is successful.
2480 isValid : function(){
2481 var items = this.getItems();
2483 items.each(function(f){
2492 * Returns true if any fields in this form have changed since their original load.
2495 isDirty : function(){
2497 var items = this.getItems();
2498 items.each(function(f){
2508 * Performs a predefined action (submit or load) or custom actions you define on this form.
2509 * @param {String} actionName The name of the action type
2510 * @param {Object} options (optional) The options to pass to the action. All of the config options listed
2511 * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
2512 * accept other config options):
2514 Property Type Description
2515 ---------------- --------------- ----------------------------------------------------------------------------------
2516 url String The url for the action (defaults to the form's url)
2517 method String The form method to use (defaults to the form's method, or POST if not defined)
2518 params String/Object The params to pass (defaults to the form's baseParams, or none if not defined)
2519 clientValidation Boolean Applies to submit only. Pass true to call form.isValid() prior to posting to
2520 validate the form on the client (defaults to false)
2522 * @return {BasicForm} this
2524 doAction : function(action, options){
2525 if(typeof action == 'string'){
2526 action = new Roo.form.Action.ACTION_TYPES[action](this, options);
2528 if(this.fireEvent('beforeaction', this, action) !== false){
2529 this.beforeAction(action);
2530 action.run.defer(100, action);
2536 beforeAction : function(action){
2537 var o = action.options;
2539 // not really supported yet.. ??
2541 //if(this.waitMsgTarget === true){
2542 this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
2543 //}else if(this.waitMsgTarget){
2544 // this.waitMsgTarget = Roo.get(this.waitMsgTarget);
2545 // this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
2547 // Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
2553 afterAction : function(action, success){
2554 this.activeAction = null;
2555 var o = action.options;
2557 //if(this.waitMsgTarget === true){
2559 //}else if(this.waitMsgTarget){
2560 // this.waitMsgTarget.unmask();
2562 // Roo.MessageBox.updateProgress(1);
2563 // Roo.MessageBox.hide();
2570 Roo.callback(o.success, o.scope, [this, action]);
2571 this.fireEvent('actioncomplete', this, action);
2575 // failure condition..
2576 // we have a scenario where updates need confirming.
2577 // eg. if a locking scenario exists..
2578 // we look for { errors : { needs_confirm : true }} in the response.
2580 (typeof(action.result) != 'undefined') &&
2581 (typeof(action.result.errors) != 'undefined') &&
2582 (typeof(action.result.errors.needs_confirm) != 'undefined')
2585 Roo.log("not supported yet");
2588 Roo.MessageBox.confirm(
2589 "Change requires confirmation",
2590 action.result.errorMsg,
2595 _t.doAction('submit', { params : { _submit_confirmed : 1 } } );
2605 Roo.callback(o.failure, o.scope, [this, action]);
2606 // show an error message if no failed handler is set..
2607 if (!this.hasListener('actionfailed')) {
2608 Roo.log("need to add dialog support");
2610 Roo.MessageBox.alert("Error",
2611 (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
2612 action.result.errorMsg :
2613 "Saving Failed, please check your entries or try again"
2618 this.fireEvent('actionfailed', this, action);
2623 * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
2624 * @param {String} id The value to search for
2627 findField : function(id){
2628 var items = this.getItems();
2629 var field = items.get(id);
2631 items.each(function(f){
2632 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
2639 return field || null;
2642 * Mark fields in this form invalid in bulk.
2643 * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
2644 * @return {BasicForm} this
2646 markInvalid : function(errors){
2647 if(errors instanceof Array){
2648 for(var i = 0, len = errors.length; i < len; i++){
2649 var fieldError = errors[i];
2650 var f = this.findField(fieldError.id);
2652 f.markInvalid(fieldError.msg);
2658 if(typeof errors[id] != 'function' && (field = this.findField(id))){
2659 field.markInvalid(errors[id]);
2663 //Roo.each(this.childForms || [], function (f) {
2664 // f.markInvalid(errors);
2671 * Set values for fields in this form in bulk.
2672 * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
2673 * @return {BasicForm} this
2675 setValues : function(values){
2676 if(values instanceof Array){ // array of objects
2677 for(var i = 0, len = values.length; i < len; i++){
2679 var f = this.findField(v.id);
2681 f.setValue(v.value);
2682 if(this.trackResetOnLoad){
2683 f.originalValue = f.getValue();
2687 }else{ // object hash
2690 if(typeof values[id] != 'function' && (field = this.findField(id))){
2692 if (field.setFromData &&
2694 field.displayField &&
2695 // combos' with local stores can
2696 // be queried via setValue()
2697 // to set their value..
2698 (field.store && !field.store.isLocal)
2702 sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
2703 sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
2704 field.setFromData(sd);
2707 field.setValue(values[id]);
2711 if(this.trackResetOnLoad){
2712 field.originalValue = field.getValue();
2718 //Roo.each(this.childForms || [], function (f) {
2719 // f.setValues(values);
2726 * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
2727 * they are returned as an array.
2728 * @param {Boolean} asString
2731 getValues : function(asString){
2732 //if (this.childForms) {
2733 // copy values from the child forms
2734 // Roo.each(this.childForms, function (f) {
2735 // this.setValues(f.getValues());
2741 var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
2742 if(asString === true){
2745 return Roo.urlDecode(fs);
2749 * Returns the fields in this form as an object with key/value pairs.
2750 * This differs from getValues as it calls getValue on each child item, rather than using dom data.
2753 getFieldValues : function(with_hidden)
2755 var items = this.getItems();
2757 items.each(function(f){
2761 var v = f.getValue();
2762 if (f.inputType =='radio') {
2763 if (typeof(ret[f.getName()]) == 'undefined') {
2764 ret[f.getName()] = ''; // empty..
2767 if (!f.el.dom.checked) {
2775 // not sure if this supported any more..
2776 if ((typeof(v) == 'object') && f.getRawValue) {
2777 v = f.getRawValue() ; // dates..
2779 // combo boxes where name != hiddenName...
2780 if (f.name != f.getName()) {
2781 ret[f.name] = f.getRawValue();
2783 ret[f.getName()] = v;
2790 * Clears all invalid messages in this form.
2791 * @return {BasicForm} this
2793 clearInvalid : function(){
2794 var items = this.getItems();
2796 items.each(function(f){
2807 * @return {BasicForm} this
2810 var items = this.getItems();
2811 items.each(function(f){
2815 Roo.each(this.childForms || [], function (f) {
2822 getItems : function()
2824 var r=new Roo.util.MixedCollection(false, function(o){
2825 return o.id || (o.id = Roo.id());
2827 var iter = function(el) {
2834 Roo.each(el.items,function(e) {
2853 * Ext JS Library 1.1.1
2854 * Copyright(c) 2006-2007, Ext JS, LLC.
2856 * Originally Released Under LGPL - original licence link has changed is not relivant.
2859 * <script type="text/javascript">
2862 * @class Roo.form.VTypes
2863 * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
2866 Roo.form.VTypes = function(){
2867 // closure these in so they are only created once.
2868 var alpha = /^[a-zA-Z_]+$/;
2869 var alphanum = /^[a-zA-Z0-9_]+$/;
2870 var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
2871 var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
2873 // All these messages and functions are configurable
2876 * The function used to validate email addresses
2877 * @param {String} value The email address
2879 'email' : function(v){
2880 return email.test(v);
2883 * The error text to display when the email validation function returns false
2886 'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
2888 * The keystroke filter mask to be applied on email input
2891 'emailMask' : /[a-z0-9_\.\-@]/i,
2894 * The function used to validate URLs
2895 * @param {String} value The URL
2897 'url' : function(v){
2901 * The error text to display when the url validation function returns false
2904 'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
2907 * The function used to validate alpha values
2908 * @param {String} value The value
2910 'alpha' : function(v){
2911 return alpha.test(v);
2914 * The error text to display when the alpha validation function returns false
2917 'alphaText' : 'This field should only contain letters and _',
2919 * The keystroke filter mask to be applied on alpha input
2922 'alphaMask' : /[a-z_]/i,
2925 * The function used to validate alphanumeric values
2926 * @param {String} value The value
2928 'alphanum' : function(v){
2929 return alphanum.test(v);
2932 * The error text to display when the alphanumeric validation function returns false
2935 'alphanumText' : 'This field should only contain letters, numbers and _',
2937 * The keystroke filter mask to be applied on alphanumeric input
2940 'alphanumMask' : /[a-z0-9_]/i
2950 * @class Roo.bootstrap.Input
2951 * @extends Roo.bootstrap.Component
2952 * Bootstrap Input class
2953 * @cfg {Boolean} disabled is it disabled
2954 * @cfg {String} fieldLabel - the label associated
2955 * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
2956 * @cfg {String} name name of the input
2957 * @cfg {string} fieldLabel - the label associated
2958 * @cfg {string} inputType - input / file submit ...
2959 * @cfg {string} placeholder - placeholder to put in text.
2960 * @cfg {string} before - input group add on before
2961 * @cfg {string} after - input group add on after
2965 * Create a new Input
2966 * @param {Object} config The config object
2969 Roo.bootstrap.Input = function(config){
2970 Roo.bootstrap.Input.superclass.constructor.call(this, config);
2975 * Fires when this field receives input focus.
2976 * @param {Roo.form.Field} this
2981 * Fires when this field loses input focus.
2982 * @param {Roo.form.Field} this
2987 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
2988 * {@link Roo.EventObject#getKey} to determine which key was pressed.
2989 * @param {Roo.form.Field} this
2990 * @param {Roo.EventObject} e The event object
2995 * Fires just before the field blurs if the field value has changed.
2996 * @param {Roo.form.Field} this
2997 * @param {Mixed} newValue The new value
2998 * @param {Mixed} oldValue The original value
3003 * Fires after the field has been marked as invalid.
3004 * @param {Roo.form.Field} this
3005 * @param {String} msg The validation message
3010 * Fires after the field has been validated with no errors.
3011 * @param {Roo.form.Field} this
3016 * Fires after the key up
3017 * @param {Roo.form.Field} this
3018 * @param {Roo.EventObject} e The event Object
3024 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component, {
3026 * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
3027 automatic validation (defaults to "keyup").
3029 validationEvent : "keyup",
3031 * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
3033 validateOnBlur : true,
3035 * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
3037 validationDelay : 250,
3039 * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
3041 focusClass : "x-form-focus", // not needed???
3045 * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
3047 invalidClass : "has-error",
3050 * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
3052 selectOnFocus : false,
3055 * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
3059 * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
3064 * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
3066 disableKeyFilter : false,
3069 * @cfg {Boolean} disabled True to disable the field (defaults to false).
3073 * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
3077 * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
3079 blankText : "This field is required",
3082 * @cfg {Number} minLength Minimum input field length required (defaults to 0)
3086 * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
3088 maxLength : Number.MAX_VALUE,
3090 * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
3092 minLengthText : "The minimum length for this field is {0}",
3094 * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
3096 maxLengthText : "The maximum length for this field is {0}",
3100 * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
3101 * If available, this function will be called only after the basic validators all return true, and will be passed the
3102 * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
3106 * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
3107 * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
3108 * current field value. If the test fails, the field will be marked invalid using {@link #regexText}.
3112 * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
3130 getAutoCreate : function(){
3132 var parent = this.parent();
3134 var align = parent.labelAlign;
3139 cls: 'form-group' //input-group
3145 type : this.inputType,
3146 cls : 'form-control',
3147 placeholder : this.placeholder || ''
3151 input.name = this.name;
3154 var inputblock = input;
3156 if (this.before || this.after) {
3159 cls : 'input-group',
3163 inputblock.cn.push({
3165 cls : 'input-group-addon',
3169 inputblock.cn.push(input);
3171 inputblock.cn.push({
3173 cls : 'input-group-addon',
3181 Roo.log(this.fieldLabel.length);
3183 if (align ==='left' && this.fieldLabel.length) {
3184 Roo.log("left and has label");
3190 cls : 'col-sm-2 control-label',
3191 html : this.fieldLabel
3202 } else if ( this.fieldLabel.length) {
3208 //cls : 'input-group-addon',
3209 html : this.fieldLabel
3219 Roo.log(" no label && no align");
3232 if (this.disabled) {
3233 input.disabled=true;
3239 * return the real input element.
3241 inputEl: function ()
3243 return this.el.select('input.form-control',true).first();
3245 setDisabled : function(v)
3247 var i = this.inputEl().dom;
3249 i.removeAttribute('disabled');
3253 i.setAttribute('disabled','true');
3255 initEvents : function()
3258 this.inputEl().on("keydown" , this.fireKey, this);
3259 this.inputEl().on("focus", this.onFocus, this);
3260 this.inputEl().on("blur", this.onBlur, this);
3261 this.inputEl().relayEvent('keyup', this);
3263 // reference to original value for reset
3264 this.originalValue = this.getValue();
3265 //Roo.form.TextField.superclass.initEvents.call(this);
3266 if(this.validationEvent == 'keyup'){
3267 this.validationTask = new Roo.util.DelayedTask(this.validate, this);
3268 this.inputEl().on('keyup', this.filterValidation, this);
3270 else if(this.validationEvent !== false){
3271 this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
3274 if(this.selectOnFocus){
3275 this.on("focus", this.preFocus, this);
3278 if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
3279 this.inputEl().on("keypress", this.filterKeys, this);
3282 this.el.on("keyup", this.onKeyUp, this, {buffer:50});
3283 this.el.on("click", this.autoSize, this);
3286 if(this.inputEl().is('input[type=password]') && Roo.isSafari){
3287 this.inputEl().on('keydown', this.SafariOnKeyDown, this);
3291 filterValidation : function(e){
3292 if(!e.isNavKeyPress()){
3293 this.validationTask.delay(this.validationDelay);
3297 * Validates the field value
3298 * @return {Boolean} True if the value is valid, else false
3300 validate : function(){
3301 //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
3302 if(this.disabled || this.validateValue(this.getRawValue())){
3303 this.clearInvalid();
3311 * Validates a value according to the field's validation rules and marks the field as invalid
3312 * if the validation fails
3313 * @param {Mixed} value The value to validate
3314 * @return {Boolean} True if the value is valid, else false
3316 validateValue : function(value){
3317 if(value.length < 1) { // if it's blank
3318 if(this.allowBlank){
3319 this.clearInvalid();
3322 this.markInvalid(this.blankText);
3326 if(value.length < this.minLength){
3327 this.markInvalid(String.format(this.minLengthText, this.minLength));
3330 if(value.length > this.maxLength){
3331 this.markInvalid(String.format(this.maxLengthText, this.maxLength));
3335 var vt = Roo.form.VTypes;
3336 if(!vt[this.vtype](value, this)){
3337 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
3341 if(typeof this.validator == "function"){
3342 var msg = this.validator(value);
3344 this.markInvalid(msg);
3348 if(this.regex && !this.regex.test(value)){
3349 this.markInvalid(this.regexText);
3358 fireKey : function(e){
3359 //Roo.log('field ' + e.getKey());
3360 if(e.isNavKeyPress()){
3361 this.fireEvent("specialkey", this, e);
3364 onFocus : function(){
3365 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3366 // this.el.addClass(this.focusClass);
3369 this.hasFocus = true;
3370 this.startValue = this.getValue();
3371 this.fireEvent("focus", this);
3375 beforeBlur : Roo.emptyFn,
3379 onBlur : function(){
3381 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3382 //this.el.removeClass(this.focusClass);
3384 this.hasFocus = false;
3385 if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
3388 var v = this.getValue();
3389 if(String(v) !== String(this.startValue)){
3390 this.fireEvent('change', this, v, this.startValue);
3392 this.fireEvent("blur", this);
3395 * Returns the normalized data value (undefined or emptyText will be returned as ''). To return the raw value see {@link #getRawValue}.
3396 * @return {Mixed} value The field value
3398 getValue : function(){
3399 var v = this.inputEl().getValue();
3403 * Returns the raw data value which may or may not be a valid, defined value. To return a normalized value see {@link #getValue}.
3404 * @return {Mixed} value The field value
3406 getRawValue : function(){
3407 var v = this.inputEl().getValue();
3412 * Sets a data value into the field and validates it. To set the value directly without validation see {@link #setRawValue}.
3413 * @param {Mixed} value The value to set
3415 setValue : function(v){
3418 this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
3424 processValue : function(value){
3425 if(this.stripCharsRe){
3426 var newValue = value.replace(this.stripCharsRe, '');
3427 if(newValue !== value){
3428 this.setRawValue(newValue);
3435 preFocus : function(){
3437 if(this.selectOnFocus){
3438 this.inputEl().dom.select();
3441 filterKeys : function(e){
3443 if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
3446 var c = e.getCharCode(), cc = String.fromCharCode(c);
3447 if(Roo.isIE && (e.isSpecialKey() || !cc)){
3450 if(!this.maskRe.test(cc)){
3455 * Clear any invalid styles/messages for this field
3457 clearInvalid : function(){
3459 if(!this.el || this.preventMark){ // not rendered
3462 this.el.removeClass(this.invalidClass);
3464 switch(this.msgTarget){
3466 this.el.dom.qtip = '';
3469 this.el.dom.title = '';
3473 Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
3478 this.errorIcon.dom.qtip = '';
3479 this.errorIcon.hide();
3480 this.un('resize', this.alignErrorIcon, this);
3484 var t = Roo.getDom(this.msgTarget);
3486 t.style.display = 'none';
3490 this.fireEvent('valid', this);
3493 * Mark this field as invalid
3494 * @param {String} msg The validation message
3496 markInvalid : function(msg){
3497 if(!this.el || this.preventMark){ // not rendered
3500 this.el.addClass(this.invalidClass);
3502 msg = msg || this.invalidText;
3503 switch(this.msgTarget){
3505 this.el.dom.qtip = msg;
3506 this.el.dom.qclass = 'x-form-invalid-tip';
3507 if(Roo.QuickTips){ // fix for floating editors interacting with DND
3508 Roo.QuickTips.enable();
3512 this.el.dom.title = msg;
3516 var elp = this.el.findParent('.x-form-element', 5, true);
3517 this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
3518 this.errorEl.setWidth(elp.getWidth(true)-20);
3520 this.errorEl.update(msg);
3521 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
3524 if(!this.errorIcon){
3525 var elp = this.el.findParent('.x-form-element', 5, true);
3526 this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
3528 this.alignErrorIcon();
3529 this.errorIcon.dom.qtip = msg;
3530 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
3531 this.errorIcon.show();
3532 this.on('resize', this.alignErrorIcon, this);
3535 var t = Roo.getDom(this.msgTarget);
3537 t.style.display = this.msgDisplay;
3541 this.fireEvent('invalid', this, msg);
3544 SafariOnKeyDown : function(event)
3546 // this is a workaround for a password hang bug on chrome/ webkit.
3548 var isSelectAll = false;
3550 if(this.inputEl().dom.selectionEnd > 0){
3551 isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
3553 if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
3554 event.preventDefault();
3559 if(isSelectAll){ // backspace and delete key
3561 event.preventDefault();
3562 // this is very hacky as keydown always get's upper case.
3564 var cc = String.fromCharCode(event.getCharCode());
3565 this.setValue( event.shiftKey ? cc : cc.toLowerCase());