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');
1194 this.el.removeClass('on');
1195 this.el.addClass('fade');
1196 this.el.setStyle('display', 'none');
1208 * @class Roo.bootstrap.Navbar
1209 * @extends Roo.bootstrap.Component
1210 * Bootstrap Navbar class
1211 * @cfg {Boolean} sidebar has side bar
1212 * @cfg {Boolean} bar is a bar?
1213 * @cfg {String} position (fixed-top|fixed-bottom|static-top) position
1214 * @cfg {String} brand what is brand
1215 * @cfg {Boolean} inverse is inverted color
1216 * @cfg {String} type (nav | pills | tabs)
1217 * @cfg {Boolean} arrangement stacked | justified
1218 * @cfg {String} align (left | right) alignment
1222 * Create a new Navbar
1223 * @param {Object} config The config object
1227 Roo.bootstrap.Navbar = function(config){
1228 Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
1231 Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component, {
1243 getAutoCreate : function(){
1248 if (this.sidebar === true) {
1256 if (this.bar === true) {
1264 cls: 'navbar-header',
1269 cls: 'navbar-toggle',
1270 'data-toggle': 'collapse',
1275 html: 'Toggle navigation'
1295 cls: 'collapse navbar-collapse'
1300 cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
1302 if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
1303 cfg.cls += ' navbar-' + this.position;
1304 cfg.tag = this.position == 'fixed-bottom' ? 'footer' : 'header';
1307 if (this.brand !== '') {
1311 cls: 'navbar-brand',
1320 } else if (this.bar === false) {
1323 Roo.log('Property \'bar\' in of Navbar must be either true or false')
1333 if (['tabs','pills'].indexOf(this.type)!==-1) {
1334 cfg.cn[0].cls += ' nav-' + this.type
1336 if (this.type!=='nav') {
1337 Roo.log('nav type must be nav/tabs/pills')
1339 cfg.cn[0].cls += ' navbar-nav'
1342 if (['stacked','justified'].indexOf(this.arrangement)!==-1) {
1343 cfg.cn[0].cls += ' nav-' + this.arrangement;
1346 if (this.align === 'right') {
1347 cfg.cn[0].cls += ' navbar-right';
1350 cfg.cls += ' navbar-inverse';
1358 getChildContainer : function() {
1359 if (this.bar === true) {
1360 return this.el.select('.collapse',true).first();
1378 * @class Roo.bootstrap.NavGroup
1379 * @extends Roo.bootstrap.Component
1380 * Bootstrap NavGroup class
1381 * @cfg {String} align left | right
1382 * @cfg {Boolean} inverse false | true
1385 * Create a new nav group
1386 * @param {Object} config The config object
1389 Roo.bootstrap.NavGroup = function(config){
1390 Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
1393 Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component, {
1399 getAutoCreate : function(){
1400 var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
1404 cls: 'nav navbar-nav'
1407 if (this.parent().sidebar === true) {
1410 cls: 'dashboard-menu'
1416 if (this.form === true) {
1422 if (this.align === 'right') {
1423 cfg.cls += ' navbar-right';
1425 cfg.cls += ' navbar-left';
1430 if (this.align === 'right') {
1431 cfg.cls += ' navbar-right';
1435 cfg.cls += ' navbar-inverse';
1454 * @class Roo.bootstrap.Navbar.Button
1455 * @extends Roo.bootstrap.Component
1456 * Bootstrap Navbar.Button class
1457 * @cfg {String} href link to
1458 * @cfg {String} html content of button
1461 * Create a new Navbar Button
1462 * @param {Object} config The config object
1466 Roo.bootstrap.Navbar.Button = function(config){
1467 Roo.bootstrap.Navbar.Button.superclass.constructor.call(this, config);
1470 Roo.extend(Roo.bootstrap.Navbar.Button, Roo.bootstrap.Component, {
1481 getAutoCreate : function(){
1491 html : this.html || ''
1515 * @class Roo.bootstrap.Navbar.Item
1516 * @extends Roo.bootstrap.Component
1517 * Bootstrap Navbar.Button class
1518 * @cfg {String} href link to
1519 * @cfg {String} html content of button
1520 * @cfg {String} badge text inside badge
1521 * @cfg {String} glyphicon name of glyphicon
1524 * Create a new Navbar Button
1525 * @param {Object} config The config object
1527 Roo.bootstrap.Navbar.Item = function(config){
1528 Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
1531 Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component, {
1539 getAutoCreate : function(){
1541 var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
1543 if (this.parent().parent().sidebar === true) {
1556 cfg.cn[0].html = this.html;
1560 this.cls += ' active';
1564 cfg.cn[0].cls += ' dropdown-toggle';
1565 cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
1569 cfg.cn[0].tag = 'a',
1570 cfg.cn[0].href = this.href;
1573 if (this.glyphicon) {
1574 cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
1590 if (this.glyphicon) {
1591 if(cfg.html){cfg.html = ' ' + this.html};
1595 cls: 'glyphicon glyphicon-' + this.glyphicon
1600 cfg.cn[0].html = this.html || cfg.cn[0].html ;
1604 cfg.cn[0].html += " <span class='caret'></span>";
1605 //}else if (!this.href) {
1606 // cfg.cn[0].tag='p';
1607 // cfg.cn[0].cls='navbar-text';
1610 cfg.cn[0].href=this.href||'#';
1611 cfg.cn[0].html=this.html;
1614 if (this.badge !== '') {
1617 cfg.cn[0].html + ' ',
1630 initEvents: function() {
1631 // Roo.log('init events?');
1632 // Roo.log(this.el.dom);
1633 this.el.select('a',true).on('click',
1635 this.fireEvent('click', this);
1652 * @class Roo.bootstrap.Row
1653 * @extends Roo.bootstrap.Component
1654 * Bootstrap Row class (contains columns...)
1658 * @param {Object} config The config object
1661 Roo.bootstrap.Row = function(config){
1662 Roo.bootstrap.Row.superclass.constructor.call(this, config);
1665 Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component, {
1684 * @class Roo.bootstrap.Element
1685 * @extends Roo.bootstrap.Component
1686 * Bootstrap Element class
1687 * @cfg {String} html contents of the element
1688 * @cfg {String} tag tag of the element
1689 * @cfg {String} cls class of the element
1692 * Create a new Element
1693 * @param {Object} config The config object
1696 Roo.bootstrap.Element = function(config){
1697 Roo.bootstrap.Element.superclass.constructor.call(this, config);
1700 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component, {
1708 getAutoCreate : function(){
1709 var cfg = Roo.apply({}, Roo.bootstrap.Element.superclass.getAutoCreate.call(this));
1732 * @class Roo.bootstrap.Pagination
1733 * @extends Roo.bootstrap.Component
1734 * Bootstrap Pagination class
1735 * @cfg {String} size xs | sm | md | lg
1736 * @cfg {Boolean} inverse false | true
1737 * @cfg {Number} from pagination starting number
1738 * @cfg {Number} to pagination ending number
1739 * @cfg {String} align empty or left | right
1740 * @cfg {Number} active active page number
1743 * Create a new Pagination
1744 * @param {Object} config The config object
1747 Roo.bootstrap.Pagination = function(config){
1748 Roo.bootstrap.Pagination.superclass.constructor.call(this, config);
1751 Roo.extend(Roo.bootstrap.Pagination, Roo.bootstrap.Component, {
1761 getAutoCreate : function(){
1768 cfg.cls += ' inverse';
1786 var from=this.from>0?this.from:1;
1787 var to=this.to-from<=10?this.to:from+10;
1788 var active=this.active>=from&&this.active<=to?this.active:null;
1789 for (var i=from;i<=to;i++) {
1793 cls: active===i?'active':'',
1834 * @class Roo.bootstrap.Slider
1835 * @extends Roo.bootstrap.Component
1836 * Bootstrap Slider class
1839 * Create a new Slider
1840 * @param {Object} config The config object
1843 Roo.bootstrap.Slider = function(config){
1844 Roo.bootstrap.Slider.superclass.constructor.call(this, config);
1847 Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component, {
1849 getAutoCreate : function(){
1853 cls: 'slider slider-sample1 vertical-handler ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all',
1857 cls: 'ui-slider-handle ui-state-default ui-corner-all'
1875 * @class Roo.bootstrap.Table
1876 * @extends Roo.bootstrap.Component
1877 * Bootstrap Table class
1880 * Create a new Table
1881 * @param {Object} config The config object
1884 Roo.bootstrap.Table = function(config){
1885 Roo.bootstrap.Table.superclass.constructor.call(this, config);
1888 Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
1893 getAutoCreate : function(){
1894 var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
1926 * @class Roo.bootstrap.TableCell
1927 * @extends Roo.bootstrap.Component
1928 * Bootstrap TableCell class
1931 * Create a new TableCell
1932 * @param {Object} config The config object
1935 Roo.bootstrap.TableCell = function(config){
1936 Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
1939 Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component, {
1941 getAutoCreate : function(){
1942 var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
1969 * @class Roo.bootstrap.TableRow
1970 * @extends Roo.bootstrap.Component
1971 * Bootstrap TableRow class
1974 * Create a new TableRow
1975 * @param {Object} config The config object
1978 Roo.bootstrap.TableRow = function(config){
1979 Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
1982 Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component, {
1984 getAutoCreate : function(){
1985 var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
2000 * Ext JS Library 1.1.1
2001 * Copyright(c) 2006-2007, Ext JS, LLC.
2003 * Originally Released Under LGPL - original licence link has changed is not relivant.
2006 * <script type="text/javascript">
2009 // as we use this in bootstrap.
2010 Roo.namespace('Roo.form');
2012 * @class Roo.form.Action
2013 * Internal Class used to handle form actions
2015 * @param {Roo.form.BasicForm} el The form element or its id
2016 * @param {Object} config Configuration options
2021 // define the action interface
2022 Roo.form.Action = function(form, options){
2024 this.options = options || {};
2027 * Client Validation Failed
2030 Roo.form.Action.CLIENT_INVALID = 'client';
2032 * Server Validation Failed
2035 Roo.form.Action.SERVER_INVALID = 'server';
2037 * Connect to Server Failed
2040 Roo.form.Action.CONNECT_FAILURE = 'connect';
2042 * Reading Data from Server Failed
2045 Roo.form.Action.LOAD_FAILURE = 'load';
2047 Roo.form.Action.prototype = {
2049 failureType : undefined,
2050 response : undefined,
2054 run : function(options){
2059 success : function(response){
2064 handleResponse : function(response){
2068 // default connection failure
2069 failure : function(response){
2071 this.response = response;
2072 this.failureType = Roo.form.Action.CONNECT_FAILURE;
2073 this.form.afterAction(this, false);
2076 processResponse : function(response){
2077 this.response = response;
2078 if(!response.responseText){
2081 this.result = this.handleResponse(response);
2085 // utility functions used internally
2086 getUrl : function(appendParams){
2087 var url = this.options.url || this.form.url || this.form.el.dom.action;
2089 var p = this.getParams();
2091 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
2097 getMethod : function(){
2098 return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
2101 getParams : function(){
2102 var bp = this.form.baseParams;
2103 var p = this.options.params;
2105 if(typeof p == "object"){
2106 p = Roo.urlEncode(Roo.applyIf(p, bp));
2107 }else if(typeof p == 'string' && bp){
2108 p += '&' + Roo.urlEncode(bp);
2111 p = Roo.urlEncode(bp);
2116 createCallback : function(){
2118 success: this.success,
2119 failure: this.failure,
2121 timeout: (this.form.timeout*1000),
2122 upload: this.form.fileUpload ? this.success : undefined
2127 Roo.form.Action.Submit = function(form, options){
2128 Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
2131 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
2134 haveProgress : false,
2135 uploadComplete : false,
2137 // uploadProgress indicator.
2138 uploadProgress : function()
2140 if (!this.form.progressUrl) {
2144 if (!this.haveProgress) {
2145 Roo.MessageBox.progress("Uploading", "Uploading");
2147 if (this.uploadComplete) {
2148 Roo.MessageBox.hide();
2152 this.haveProgress = true;
2154 var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
2156 var c = new Roo.data.Connection();
2158 url : this.form.progressUrl,
2163 success : function(req){
2164 //console.log(data);
2168 rdata = Roo.decode(req.responseText)
2170 Roo.log("Invalid data from server..");
2174 if (!rdata || !rdata.success) {
2176 Roo.MessageBox.alert(Roo.encode(rdata));
2179 var data = rdata.data;
2181 if (this.uploadComplete) {
2182 Roo.MessageBox.hide();
2187 Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
2188 Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
2191 this.uploadProgress.defer(2000,this);
2194 failure: function(data) {
2195 Roo.log('progress url failed ');
2206 // run get Values on the form, so it syncs any secondary forms.
2207 this.form.getValues();
2209 var o = this.options;
2210 var method = this.getMethod();
2211 var isPost = method == 'POST';
2212 if(o.clientValidation === false || this.form.isValid()){
2214 if (this.form.progressUrl) {
2215 this.form.findField('UPLOAD_IDENTIFIER').setValue(
2216 (new Date() * 1) + '' + Math.random());
2221 Roo.Ajax.request(Roo.apply(this.createCallback(), {
2222 form:this.form.el.dom,
2223 url:this.getUrl(!isPost),
2225 params:isPost ? this.getParams() : null,
2226 isUpload: this.form.fileUpload
2229 this.uploadProgress();
2231 }else if (o.clientValidation !== false){ // client validation failed
2232 this.failureType = Roo.form.Action.CLIENT_INVALID;
2233 this.form.afterAction(this, false);
2237 success : function(response)
2239 this.uploadComplete= true;
2240 if (this.haveProgress) {
2241 Roo.MessageBox.hide();
2245 var result = this.processResponse(response);
2246 if(result === true || result.success){
2247 this.form.afterAction(this, true);
2251 this.form.markInvalid(result.errors);
2252 this.failureType = Roo.form.Action.SERVER_INVALID;
2254 this.form.afterAction(this, false);
2256 failure : function(response)
2258 this.uploadComplete= true;
2259 if (this.haveProgress) {
2260 Roo.MessageBox.hide();
2263 this.response = response;
2264 this.failureType = Roo.form.Action.CONNECT_FAILURE;
2265 this.form.afterAction(this, false);
2268 handleResponse : function(response){
2269 if(this.form.errorReader){
2270 var rs = this.form.errorReader.read(response);
2273 for(var i = 0, len = rs.records.length; i < len; i++) {
2274 var r = rs.records[i];
2278 if(errors.length < 1){
2282 success : rs.success,
2288 ret = Roo.decode(response.responseText);
2292 errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
2302 Roo.form.Action.Load = function(form, options){
2303 Roo.form.Action.Load.superclass.constructor.call(this, form, options);
2304 this.reader = this.form.reader;
2307 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
2312 Roo.Ajax.request(Roo.apply(
2313 this.createCallback(), {
2314 method:this.getMethod(),
2315 url:this.getUrl(false),
2316 params:this.getParams()
2320 success : function(response){
2322 var result = this.processResponse(response);
2323 if(result === true || !result.success || !result.data){
2324 this.failureType = Roo.form.Action.LOAD_FAILURE;
2325 this.form.afterAction(this, false);
2328 this.form.clearInvalid();
2329 this.form.setValues(result.data);
2330 this.form.afterAction(this, true);
2333 handleResponse : function(response){
2334 if(this.form.reader){
2335 var rs = this.form.reader.read(response);
2336 var data = rs.records && rs.records[0] ? rs.records[0].data : null;
2338 success : rs.success,
2342 return Roo.decode(response.responseText);
2346 Roo.form.Action.ACTION_TYPES = {
2347 'load' : Roo.form.Action.Load,
2348 'submit' : Roo.form.Action.Submit
2357 * @class Roo.bootstrap.Form
2358 * @extends Roo.bootstrap.Component
2359 * Bootstrap Form class
2360 * @cfg {String} method GET | POST (default POST)
2361 * @cfg {String} labelAlign top | left (default top)
2365 * @param {Object} config The config object
2369 Roo.bootstrap.Form = function(config){
2370 Roo.bootstrap.Form.superclass.constructor.call(this, config);
2373 * @event clientvalidation
2374 * If the monitorValid config option is true, this event fires repetitively to notify of valid state
2375 * @param {Form} this
2376 * @param {Boolean} valid true if the form has passed client-side validation
2378 clientvalidation: true,
2380 * @event beforeaction
2381 * Fires before any action is performed. Return false to cancel the action.
2382 * @param {Form} this
2383 * @param {Action} action The action to be performed
2387 * @event actionfailed
2388 * Fires when an action fails.
2389 * @param {Form} this
2390 * @param {Action} action The action that failed
2392 actionfailed : true,
2394 * @event actioncomplete
2395 * Fires when an action is completed.
2396 * @param {Form} this
2397 * @param {Action} action The action that completed
2399 actioncomplete : true
2404 Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component, {
2407 * @cfg {String} method
2408 * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
2413 * The URL to use for form actions if one isn't supplied in the action options.
2416 * @cfg {Boolean} fileUpload
2417 * Set to true if this form is a file upload.
2421 * @cfg {Object} baseParams
2422 * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
2426 * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
2431 activeAction : null,
2434 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2435 * element by passing it or its id or mask the form itself by passing in true.
2438 waitMsgTarget : false,
2443 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2444 * element by passing it or its id or mask the form itself by passing in true.
2448 getAutoCreate : function(){
2452 method : this.method || 'POST',
2453 id : this.id || Roo.id(),
2457 if (this.labelAlign == 'left' ) {
2458 cfg.cls += ' form-horizontal';
2462 initEvents : function()
2464 this.el.on('submit', this.onSubmit, this);
2469 onSubmit : function(e){
2474 * Returns true if client-side validation on the form is successful.
2477 isValid : function(){
2478 var items = this.getItems();
2480 items.each(function(f){
2489 * Returns true if any fields in this form have changed since their original load.
2492 isDirty : function(){
2494 var items = this.getItems();
2495 items.each(function(f){
2505 * Performs a predefined action (submit or load) or custom actions you define on this form.
2506 * @param {String} actionName The name of the action type
2507 * @param {Object} options (optional) The options to pass to the action. All of the config options listed
2508 * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
2509 * accept other config options):
2511 Property Type Description
2512 ---------------- --------------- ----------------------------------------------------------------------------------
2513 url String The url for the action (defaults to the form's url)
2514 method String The form method to use (defaults to the form's method, or POST if not defined)
2515 params String/Object The params to pass (defaults to the form's baseParams, or none if not defined)
2516 clientValidation Boolean Applies to submit only. Pass true to call form.isValid() prior to posting to
2517 validate the form on the client (defaults to false)
2519 * @return {BasicForm} this
2521 doAction : function(action, options){
2522 if(typeof action == 'string'){
2523 action = new Roo.form.Action.ACTION_TYPES[action](this, options);
2525 if(this.fireEvent('beforeaction', this, action) !== false){
2526 this.beforeAction(action);
2527 action.run.defer(100, action);
2533 beforeAction : function(action){
2534 var o = action.options;
2536 // not really supported yet.. ??
2538 //if(this.waitMsgTarget === true){
2539 this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
2540 //}else if(this.waitMsgTarget){
2541 // this.waitMsgTarget = Roo.get(this.waitMsgTarget);
2542 // this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
2544 // Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
2550 afterAction : function(action, success){
2551 this.activeAction = null;
2552 var o = action.options;
2554 //if(this.waitMsgTarget === true){
2556 //}else if(this.waitMsgTarget){
2557 // this.waitMsgTarget.unmask();
2559 // Roo.MessageBox.updateProgress(1);
2560 // Roo.MessageBox.hide();
2567 Roo.callback(o.success, o.scope, [this, action]);
2568 this.fireEvent('actioncomplete', this, action);
2572 // failure condition..
2573 // we have a scenario where updates need confirming.
2574 // eg. if a locking scenario exists..
2575 // we look for { errors : { needs_confirm : true }} in the response.
2577 (typeof(action.result) != 'undefined') &&
2578 (typeof(action.result.errors) != 'undefined') &&
2579 (typeof(action.result.errors.needs_confirm) != 'undefined')
2582 Roo.log("not supported yet");
2585 Roo.MessageBox.confirm(
2586 "Change requires confirmation",
2587 action.result.errorMsg,
2592 _t.doAction('submit', { params : { _submit_confirmed : 1 } } );
2602 Roo.callback(o.failure, o.scope, [this, action]);
2603 // show an error message if no failed handler is set..
2604 if (!this.hasListener('actionfailed')) {
2605 Roo.log("need to add dialog support");
2607 Roo.MessageBox.alert("Error",
2608 (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
2609 action.result.errorMsg :
2610 "Saving Failed, please check your entries or try again"
2615 this.fireEvent('actionfailed', this, action);
2620 * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
2621 * @param {String} id The value to search for
2624 findField : function(id){
2625 var items = this.getItems();
2626 var field = items.get(id);
2628 items.each(function(f){
2629 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
2636 return field || null;
2639 * Mark fields in this form invalid in bulk.
2640 * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
2641 * @return {BasicForm} this
2643 markInvalid : function(errors){
2644 if(errors instanceof Array){
2645 for(var i = 0, len = errors.length; i < len; i++){
2646 var fieldError = errors[i];
2647 var f = this.findField(fieldError.id);
2649 f.markInvalid(fieldError.msg);
2655 if(typeof errors[id] != 'function' && (field = this.findField(id))){
2656 field.markInvalid(errors[id]);
2660 //Roo.each(this.childForms || [], function (f) {
2661 // f.markInvalid(errors);
2668 * Set values for fields in this form in bulk.
2669 * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
2670 * @return {BasicForm} this
2672 setValues : function(values){
2673 if(values instanceof Array){ // array of objects
2674 for(var i = 0, len = values.length; i < len; i++){
2676 var f = this.findField(v.id);
2678 f.setValue(v.value);
2679 if(this.trackResetOnLoad){
2680 f.originalValue = f.getValue();
2684 }else{ // object hash
2687 if(typeof values[id] != 'function' && (field = this.findField(id))){
2689 if (field.setFromData &&
2691 field.displayField &&
2692 // combos' with local stores can
2693 // be queried via setValue()
2694 // to set their value..
2695 (field.store && !field.store.isLocal)
2699 sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
2700 sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
2701 field.setFromData(sd);
2704 field.setValue(values[id]);
2708 if(this.trackResetOnLoad){
2709 field.originalValue = field.getValue();
2715 //Roo.each(this.childForms || [], function (f) {
2716 // f.setValues(values);
2723 * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
2724 * they are returned as an array.
2725 * @param {Boolean} asString
2728 getValues : function(asString){
2729 //if (this.childForms) {
2730 // copy values from the child forms
2731 // Roo.each(this.childForms, function (f) {
2732 // this.setValues(f.getValues());
2738 var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
2739 if(asString === true){
2742 return Roo.urlDecode(fs);
2746 * Returns the fields in this form as an object with key/value pairs.
2747 * This differs from getValues as it calls getValue on each child item, rather than using dom data.
2750 getFieldValues : function(with_hidden)
2752 var items = this.getItems();
2754 items.each(function(f){
2758 var v = f.getValue();
2759 if (f.inputType =='radio') {
2760 if (typeof(ret[f.getName()]) == 'undefined') {
2761 ret[f.getName()] = ''; // empty..
2764 if (!f.el.dom.checked) {
2772 // not sure if this supported any more..
2773 if ((typeof(v) == 'object') && f.getRawValue) {
2774 v = f.getRawValue() ; // dates..
2776 // combo boxes where name != hiddenName...
2777 if (f.name != f.getName()) {
2778 ret[f.name] = f.getRawValue();
2780 ret[f.getName()] = v;
2787 * Clears all invalid messages in this form.
2788 * @return {BasicForm} this
2790 clearInvalid : function(){
2791 var items = this.getItems();
2793 items.each(function(f){
2804 * @return {BasicForm} this
2807 var items = this.getItems();
2808 items.each(function(f){
2812 Roo.each(this.childForms || [], function (f) {
2819 getItems : function()
2821 var r=new Roo.util.MixedCollection(false, function(o){
2822 return o.id || (o.id = Roo.id());
2824 var iter = function(el) {
2831 Roo.each(el.items,function(e) {
2850 * Ext JS Library 1.1.1
2851 * Copyright(c) 2006-2007, Ext JS, LLC.
2853 * Originally Released Under LGPL - original licence link has changed is not relivant.
2856 * <script type="text/javascript">
2859 * @class Roo.form.VTypes
2860 * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
2863 Roo.form.VTypes = function(){
2864 // closure these in so they are only created once.
2865 var alpha = /^[a-zA-Z_]+$/;
2866 var alphanum = /^[a-zA-Z0-9_]+$/;
2867 var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
2868 var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
2870 // All these messages and functions are configurable
2873 * The function used to validate email addresses
2874 * @param {String} value The email address
2876 'email' : function(v){
2877 return email.test(v);
2880 * The error text to display when the email validation function returns false
2883 'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
2885 * The keystroke filter mask to be applied on email input
2888 'emailMask' : /[a-z0-9_\.\-@]/i,
2891 * The function used to validate URLs
2892 * @param {String} value The URL
2894 'url' : function(v){
2898 * The error text to display when the url validation function returns false
2901 'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
2904 * The function used to validate alpha values
2905 * @param {String} value The value
2907 'alpha' : function(v){
2908 return alpha.test(v);
2911 * The error text to display when the alpha validation function returns false
2914 'alphaText' : 'This field should only contain letters and _',
2916 * The keystroke filter mask to be applied on alpha input
2919 'alphaMask' : /[a-z_]/i,
2922 * The function used to validate alphanumeric values
2923 * @param {String} value The value
2925 'alphanum' : function(v){
2926 return alphanum.test(v);
2929 * The error text to display when the alphanumeric validation function returns false
2932 'alphanumText' : 'This field should only contain letters, numbers and _',
2934 * The keystroke filter mask to be applied on alphanumeric input
2937 'alphanumMask' : /[a-z0-9_]/i
2947 * @class Roo.bootstrap.Input
2948 * @extends Roo.bootstrap.Component
2949 * Bootstrap Input class
2950 * @cfg {Boolean} disabled is it disabled
2951 * @cfg {String} fieldLabel - the label associated
2952 * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
2953 * @cfg {String} name name of the input
2954 * @cfg {string} fieldLabel - the label associated
2955 * @cfg {string} inputType - input / file submit ...
2956 * @cfg {string} placeholder - placeholder to put in text.
2957 * @cfg {string} before - input group add on before
2958 * @cfg {string} after - input group add on after
2962 * Create a new Input
2963 * @param {Object} config The config object
2966 Roo.bootstrap.Input = function(config){
2967 Roo.bootstrap.Input.superclass.constructor.call(this, config);
2972 * Fires when this field receives input focus.
2973 * @param {Roo.form.Field} this
2978 * Fires when this field loses input focus.
2979 * @param {Roo.form.Field} this
2984 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
2985 * {@link Roo.EventObject#getKey} to determine which key was pressed.
2986 * @param {Roo.form.Field} this
2987 * @param {Roo.EventObject} e The event object
2992 * Fires just before the field blurs if the field value has changed.
2993 * @param {Roo.form.Field} this
2994 * @param {Mixed} newValue The new value
2995 * @param {Mixed} oldValue The original value
3000 * Fires after the field has been marked as invalid.
3001 * @param {Roo.form.Field} this
3002 * @param {String} msg The validation message
3007 * Fires after the field has been validated with no errors.
3008 * @param {Roo.form.Field} this
3013 * Fires after the key up
3014 * @param {Roo.form.Field} this
3015 * @param {Roo.EventObject} e The event Object
3021 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component, {
3023 * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
3024 automatic validation (defaults to "keyup").
3026 validationEvent : "keyup",
3028 * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
3030 validateOnBlur : true,
3032 * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
3034 validationDelay : 250,
3036 * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
3038 focusClass : "x-form-focus", // not needed???
3042 * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
3044 invalidClass : "has-error",
3047 * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
3049 selectOnFocus : false,
3052 * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
3056 * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
3061 * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
3063 disableKeyFilter : false,
3066 * @cfg {Boolean} disabled True to disable the field (defaults to false).
3070 * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
3074 * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
3076 blankText : "This field is required",
3079 * @cfg {Number} minLength Minimum input field length required (defaults to 0)
3083 * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
3085 maxLength : Number.MAX_VALUE,
3087 * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
3089 minLengthText : "The minimum length for this field is {0}",
3091 * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
3093 maxLengthText : "The maximum length for this field is {0}",
3097 * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
3098 * If available, this function will be called only after the basic validators all return true, and will be passed the
3099 * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
3103 * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
3104 * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
3105 * current field value. If the test fails, the field will be marked invalid using {@link #regexText}.
3109 * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
3127 getAutoCreate : function(){
3129 var parent = this.parent();
3131 var align = parent.labelAlign;
3136 cls: 'form-group' //input-group
3142 type : this.inputType,
3143 cls : 'form-control',
3144 placeholder : this.placeholder || ''
3148 input.name = this.name;
3151 var inputblock = input;
3153 if (this.before || this.after) {
3156 cls : 'input-group',
3160 inputblock.cn.push({
3162 cls : 'input-group-addon',
3166 inputblock.cn.push(input);
3168 inputblock.cn.push({
3170 cls : 'input-group-addon',
3178 Roo.log(this.fieldLabel.length);
3180 if (align ==='left' && this.fieldLabel.length) {
3181 Roo.log("left and has label");
3187 cls : 'col-sm-2 control-label',
3188 html : this.fieldLabel
3199 } else if ( this.fieldLabel.length) {
3205 //cls : 'input-group-addon',
3206 html : this.fieldLabel
3216 Roo.log(" no label && no align");
3229 if (this.disabled) {
3230 input.disabled=true;
3236 * return the real input element.
3238 inputEl: function ()
3240 return this.el.select('input.form-control',true).first();
3242 setDisabled : function(v)
3244 var i = this.inputEl().dom;
3246 i.removeAttribute('disabled');
3250 i.setAttribute('disabled','true');
3252 initEvents : function()
3255 this.inputEl().on("keydown" , this.fireKey, this);
3256 this.inputEl().on("focus", this.onFocus, this);
3257 this.inputEl().on("blur", this.onBlur, this);
3258 this.inputEl().relayEvent('keyup', this);
3260 // reference to original value for reset
3261 this.originalValue = this.getValue();
3262 //Roo.form.TextField.superclass.initEvents.call(this);
3263 if(this.validationEvent == 'keyup'){
3264 this.validationTask = new Roo.util.DelayedTask(this.validate, this);
3265 this.inputEl().on('keyup', this.filterValidation, this);
3267 else if(this.validationEvent !== false){
3268 this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
3271 if(this.selectOnFocus){
3272 this.on("focus", this.preFocus, this);
3275 if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
3276 this.inputEl().on("keypress", this.filterKeys, this);
3279 this.el.on("keyup", this.onKeyUp, this, {buffer:50});
3280 this.el.on("click", this.autoSize, this);
3283 if(this.inputEl().is('input[type=password]') && Roo.isSafari){
3284 this.inputEl().on('keydown', this.SafariOnKeyDown, this);
3288 filterValidation : function(e){
3289 if(!e.isNavKeyPress()){
3290 this.validationTask.delay(this.validationDelay);
3294 * Validates the field value
3295 * @return {Boolean} True if the value is valid, else false
3297 validate : function(){
3298 //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
3299 if(this.disabled || this.validateValue(this.getRawValue())){
3300 this.clearInvalid();
3308 * Validates a value according to the field's validation rules and marks the field as invalid
3309 * if the validation fails
3310 * @param {Mixed} value The value to validate
3311 * @return {Boolean} True if the value is valid, else false
3313 validateValue : function(value){
3314 if(value.length < 1) { // if it's blank
3315 if(this.allowBlank){
3316 this.clearInvalid();
3319 this.markInvalid(this.blankText);
3323 if(value.length < this.minLength){
3324 this.markInvalid(String.format(this.minLengthText, this.minLength));
3327 if(value.length > this.maxLength){
3328 this.markInvalid(String.format(this.maxLengthText, this.maxLength));
3332 var vt = Roo.form.VTypes;
3333 if(!vt[this.vtype](value, this)){
3334 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
3338 if(typeof this.validator == "function"){
3339 var msg = this.validator(value);
3341 this.markInvalid(msg);
3345 if(this.regex && !this.regex.test(value)){
3346 this.markInvalid(this.regexText);
3355 fireKey : function(e){
3356 //Roo.log('field ' + e.getKey());
3357 if(e.isNavKeyPress()){
3358 this.fireEvent("specialkey", this, e);
3361 onFocus : function(){
3362 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3363 // this.el.addClass(this.focusClass);
3366 this.hasFocus = true;
3367 this.startValue = this.getValue();
3368 this.fireEvent("focus", this);
3372 beforeBlur : Roo.emptyFn,
3376 onBlur : function(){
3378 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3379 //this.el.removeClass(this.focusClass);
3381 this.hasFocus = false;
3382 if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
3385 var v = this.getValue();
3386 if(String(v) !== String(this.startValue)){
3387 this.fireEvent('change', this, v, this.startValue);
3389 this.fireEvent("blur", this);
3392 * Returns the normalized data value (undefined or emptyText will be returned as ''). To return the raw value see {@link #getRawValue}.
3393 * @return {Mixed} value The field value
3395 getValue : function(){
3396 var v = this.inputEl().getValue();
3400 * Returns the raw data value which may or may not be a valid, defined value. To return a normalized value see {@link #getValue}.
3401 * @return {Mixed} value The field value
3403 getRawValue : function(){
3404 var v = this.inputEl().getValue();
3409 * Sets a data value into the field and validates it. To set the value directly without validation see {@link #setRawValue}.
3410 * @param {Mixed} value The value to set
3412 setValue : function(v){
3415 this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
3421 processValue : function(value){
3422 if(this.stripCharsRe){
3423 var newValue = value.replace(this.stripCharsRe, '');
3424 if(newValue !== value){
3425 this.setRawValue(newValue);
3432 preFocus : function(){
3434 if(this.selectOnFocus){
3435 this.inputEl().dom.select();
3438 filterKeys : function(e){
3440 if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
3443 var c = e.getCharCode(), cc = String.fromCharCode(c);
3444 if(Roo.isIE && (e.isSpecialKey() || !cc)){
3447 if(!this.maskRe.test(cc)){
3452 * Clear any invalid styles/messages for this field
3454 clearInvalid : function(){
3456 if(!this.el || this.preventMark){ // not rendered
3459 this.el.removeClass(this.invalidClass);
3461 switch(this.msgTarget){
3463 this.el.dom.qtip = '';
3466 this.el.dom.title = '';
3470 Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
3475 this.errorIcon.dom.qtip = '';
3476 this.errorIcon.hide();
3477 this.un('resize', this.alignErrorIcon, this);
3481 var t = Roo.getDom(this.msgTarget);
3483 t.style.display = 'none';
3487 this.fireEvent('valid', this);
3490 * Mark this field as invalid
3491 * @param {String} msg The validation message
3493 markInvalid : function(msg){
3494 if(!this.el || this.preventMark){ // not rendered
3497 this.el.addClass(this.invalidClass);
3499 msg = msg || this.invalidText;
3500 switch(this.msgTarget){
3502 this.el.dom.qtip = msg;
3503 this.el.dom.qclass = 'x-form-invalid-tip';
3504 if(Roo.QuickTips){ // fix for floating editors interacting with DND
3505 Roo.QuickTips.enable();
3509 this.el.dom.title = msg;
3513 var elp = this.el.findParent('.x-form-element', 5, true);
3514 this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
3515 this.errorEl.setWidth(elp.getWidth(true)-20);
3517 this.errorEl.update(msg);
3518 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
3521 if(!this.errorIcon){
3522 var elp = this.el.findParent('.x-form-element', 5, true);
3523 this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
3525 this.alignErrorIcon();
3526 this.errorIcon.dom.qtip = msg;
3527 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
3528 this.errorIcon.show();
3529 this.on('resize', this.alignErrorIcon, this);
3532 var t = Roo.getDom(this.msgTarget);
3534 t.style.display = this.msgDisplay;
3538 this.fireEvent('invalid', this, msg);
3541 SafariOnKeyDown : function(event)
3543 // this is a workaround for a password hang bug on chrome/ webkit.
3545 var isSelectAll = false;
3547 if(this.inputEl().dom.selectionEnd > 0){
3548 isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
3550 if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
3551 event.preventDefault();
3556 if(isSelectAll){ // backspace and delete key
3558 event.preventDefault();
3559 // this is very hacky as keydown always get's upper case.
3561 var cc = String.fromCharCode(event.getCharCode());
3562 this.setValue( event.shiftKey ? cc : cc.toLowerCase());