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, {
37 initEvents : function() { },
44 // returns the parent component..
45 return Roo.ComponentMgr.get(this.parentId)
51 onRender : function(ct, position)
53 Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
56 if (this.el.attr('xtype')) {
57 this.el.dom.removeAttribute('xtype');
66 var cfg = Roo.apply({}, this.getAutoCreate());
69 // fill in the extra attributes
70 if (this.xattr && typeof(this.xattr) =='object') {
71 for (var i in this.xattr) {
72 cfg[i] = this.xattr[i];
77 cfg.cls += ' ' + this.cls;
79 if (this.style) { // fixme needs to support more complex style data.
80 cfg.style = this.style;
82 this.el = ct.createChild(cfg, position);
83 if(this.tabIndex !== undefined){
84 this.el.dom.setAttribute('tabIndex', this.tabIndex);
91 getChildContainer : function()
96 addxtype : function (tree, cntr) {
98 cntr = typeof(cntr == 'undefined' ) ? 'getChildContainer' : cntr;
100 // render the element if it's not BODY.
101 if (tree.xtype != 'Body') {
103 cn = Roo.factory(tree);
105 cn.parentType = this.xtype; //??
106 cn.parentId = this.id;
108 // does the container contain child eleemnts with 'xtype' attributes.
109 // that match this xtype..
110 // note - when we render we create these as well..
111 // so we should check to see if body has xtype set.
112 if (Roo.get(document.body).attr('xtype') == 'Roo.bootstrap.Body') {
114 var echild = Roo.get(this[cntr]()).child('*[xtype]');
117 //echild.dom.removeAttribute('xtype');
120 cn.render(this[cntr]());
121 // then add the element..
128 if (typeof (tree.menu) != 'undefined') {
129 tree.menu.parentType = cn.xtype;
130 tree.menu.triggerEl = cn.el;
131 nitems.push(cn.addxtype(Roo.apply({}, tree.menu)));
134 if (typeof (tree.buttons) != 'undefined' && typeof(cn.getButtonContainer) == 'function') {
136 for(var i =0;i < tree.buttons.length;i++) {
137 nitems.push(cn.addxtype(Roo.apply({}, tree.buttons[i]), 'getButtonContainer'));
142 if (!tree.items || !tree.items.length) {
146 var items = tree.items;
149 //Roo.log(items.length);
151 for(var i =0;i < items.length;i++) {
152 nitems.push(cn.addxtype(Roo.apply({}, items[i])));
172 Roo.bootstrap.Body = function(config){
173 Roo.bootstrap.Body.superclass.constructor.call(this, config);
174 this.el = Roo.get(document.body);
177 Roo.extend(Roo.bootstrap.Body, Roo.bootstrap.Component, {
182 onRender : function(ct, position){
185 //this.el.addClass([this.fieldClass, this.cls]);
203 * @class Roo.bootstrap.ButtonGroup
204 * @extends Roo.bootstrap.Component
205 * Bootstrap ButtonGroup class
206 * @cfg {String} size lg | sm | xs (default empty normal)
207 * @cfg {String} align vertical | justified (default none)
208 * @cfg {String} direction up | down (default down)
209 * @cfg {Boolean} toolbar false | true
210 * @cfg {Boolean} btn true | false
215 * @param {Object} config The config object
218 Roo.bootstrap.ButtonGroup = function(config){
219 Roo.bootstrap.ButtonGroup.superclass.constructor.call(this, config);
222 Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component, {
230 getAutoCreate : function(){
236 cfg.html = this.html || cfg.html;
247 if (['vertical','justified'].indexOf(this.align)!==-1) {
248 cfg.cls = 'btn-group-' + this.align;
250 if (this.align == 'justified') {
251 console.log(this.items);
255 if (['lg','sm','xs'].indexOf(this.size)!==-1) {
256 cfg.cls += ' btn-group-' + this.size;
259 if (this.direction == 'up') {
260 cfg.cls += ' dropup' ;
276 * @class Roo.bootstrap.Button
277 * @extends Roo.bootstrap.Component
278 * Bootstrap Button class
279 * @cfg {String} html The button content
280 * @cfg {String} weight default (or empty) | primary | success | info | warning | danger
281 * @cfg {String} size empty | lg | sm | xs
282 * @cfg {String} tag empty | a | input | submit
283 * @cfg {String} href empty or href
284 * @cfg {Boolean} disabled false | true
285 * @cfg {Boolean} isClose false | true
286 * @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
287 * @cfg {String} badge text for badge
288 * @cfg {String} theme default (or empty) | glow
289 * @cfg {Boolean} inverse false | true
290 * @cfg {Boolean} toggle false | true
291 * @cfg {String} ontext text for on toggle state
292 * @cfg {String} offtext text for off toggle state
293 * @cfg {Boolean} defaulton true | false
296 * Create a new button
297 * @param {Object} config The config object
301 Roo.bootstrap.Button = function(config){
302 Roo.bootstrap.Button.superclass.constructor.call(this, config);
307 * The raw click event for the entire grid.
308 * @param {Roo.EventObject} e
314 Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component, {
333 getAutoCreate : function(){
341 if (['a', 'button', 'input', 'submit'].indexOf(this.tag) < 0) {
342 throw "Invalid value for tag: " + this.tag + ". must be a, button, input or submit.";
347 cfg.html = this.html || cfg.html;
349 if (this.toggle===true) {
352 cls: 'slider-frame roo-button',
357 'data-off-text':'OFF',
358 cls: 'slider-button',
364 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
365 cfg.cls += ' '+this.weight;
374 cfg["aria-hidden"] = true;
376 cfg.html = "×";
382 if (this.theme==='default') {
383 cfg.cls = 'btn roo-button';
385 if (this.parentType != 'Navbar') {
386 this.weight = this.weight.length ? this.weight : 'default';
388 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
390 cfg.cls += ' btn-' + this.weight;
392 } else if (this.theme==='glow') {
395 cfg.cls = 'btn-glow roo-button';
397 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
399 cfg.cls += ' ' + this.weight;
405 this.cls += ' inverse';
410 cfg.cls += ' active';
413 cfg.cls += this.size.length ? (' btn-' + this.size) : '';
415 //gsRoo.log(this.parentType);
416 if (this.parentType === 'Navbar') {
424 href : this.href || '#'
427 cfg.cn[0].html = this.html + ' <span class="caret"></span>';
428 cfg.cls += ' dropdown';
433 } else if (this.menu) {
435 cfg.cls += ' dropdown test';
441 cfg.disabled = 'disabled';
445 Roo.log('changing to ul' );
447 this.glyphicon = 'caret';
450 if (this.glyphicon) {
451 cfg.html = ' ' + cfg.html;
456 cls: 'glyphicon glyphicon-' + this.glyphicon
466 cfg.cls='btn roo-button';
482 if (cfg.tag !== 'a' && this.href !== '') {
483 throw "Tag must be a to set href.";
484 } else if (this.href.length > 0) {
485 cfg.href = this.href;
490 initEvents: function() {
491 // Roo.log('init events?');
492 // Roo.log(this.el.dom);
493 if (this.el.hasClass('roo-button')) {
494 this.el.on('click', this.onClick, this);
496 this.el.select('.roo-button').on('click', this.onClick, this);
502 onClick : function(e)
504 Roo.log('button on click ');
506 this.fireEvent('click', this, e);
520 * @class Roo.bootstrap.Column
521 * @extends Roo.bootstrap.Component
522 * Bootstrap Column class
523 * @cfg {Number} xs colspan out of 12 for mobile-sized screens
524 * @cfg {Number} sm colspan out of 12 for tablet-sized screens
525 * @cfg {Number} md colspan out of 12 for computer-sized screens
526 * @cfg {Number} lg colspan out of 12 for large computer-sized screens
527 * @cfg {String} html content of column.
530 * Create a new Column
531 * @param {Object} config The config object
534 Roo.bootstrap.Column = function(config){
535 Roo.bootstrap.Column.superclass.constructor.call(this, config);
538 Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component, {
547 getAutoCreate : function(){
548 var cfg = Roo.apply({}, Roo.bootstrap.Column.superclass.getAutoCreate.call(this));
556 ['xs','sm','md','lg'].map(function(size){
557 if (settings[size]) {
558 cfg.cls += ' col-' + size + '-' + settings[size];
561 if (this.html.length) {
562 cfg.html = this.html;
581 * @class Roo.bootstrap.Container
582 * @extends Roo.bootstrap.Component
583 * Bootstrap Container class
584 * @cfg {Boolean} jumbotron is it a jumbotron element
585 * @cfg {String} html content of element
586 * @cfg {String} well (lg|sm|md) a well, large, small or medium.
587 * @cfg {String} panel (primary|success|info|warning|danger) render as a panel.
588 * @cfg {String} header content of header (for panel)
589 * @cfg {String} footer content of footer (for panel)
590 * @cfg {String} sticky (footer|wrap|push) block to use as footer or body- needs css-bootstrap/sticky-footer.css
593 * Create a new Container
594 * @param {Object} config The config object
597 Roo.bootstrap.Container = function(config){
598 Roo.bootstrap.Container.superclass.constructor.call(this, config);
601 Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component, {
611 getChildContainer : function() {
612 if (this.panel.length) {
613 return this.el.select('.panel-body',true).first();
620 getAutoCreate : function(){
626 if (this.jumbotron) {
627 cfg.cls = 'jumbotron';
630 cfg.cls = this.cls + '';
633 if (this.sticky.length) {
634 var bd = Roo.get(document.body);
635 if (!bd.hasClass('bootstrap-sticky')) {
636 bd.addClass('bootstrap-sticky');
637 Roo.select('html',true).setStyle('height', '100%');
640 cfg.cls += 'bootstrap-sticky-' + this.sticky;
644 if (this.well.length) {
648 cfg.cls +=' well well-' +this.well;
658 if (this.panel.length) {
659 cfg.cls += 'panel panel-' + this.panel;
661 if (this.header.length) {
664 cls : 'panel-heading',
680 if (this.footer.length) {
682 cls : 'panel-footer',
690 body.html = this.html || cfg.html;
692 if (!cfg.cls.length) {
693 cfg.cls = 'container';
710 * @class Roo.bootstrap.Img
711 * @extends Roo.bootstrap.Component
712 * Bootstrap Img class
713 * @cfg {Boolean} imgResponsive false | true
714 * @cfg {String} border rounded | circle | thumbnail
715 * @cfg {String} src image source
716 * @cfg {String} alt image alternative text
720 * @param {Object} config The config object
723 Roo.bootstrap.Img = function(config){
724 Roo.bootstrap.Img.superclass.constructor.call(this, config);
727 Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component, {
733 getAutoCreate : function(){
737 cls: 'img-responsive',
741 cfg.html = this.html || cfg.html;
743 cfg.src = this.src || cfg.src;
745 if (['rounded','circle','thumbnail'].indexOf(this.border)>-1) {
746 cfg.cls += ' img-' + this.border;
766 * @class Roo.bootstrap.Header
767 * @extends Roo.bootstrap.Component
768 * Bootstrap Header class
769 * @cfg {String} html content of header
770 * @cfg {Number} level (1|2|3|4|5|6) default 1
773 * Create a new Header
774 * @param {Object} config The config object
778 Roo.bootstrap.Header = function(config){
779 Roo.bootstrap.Header.superclass.constructor.call(this, config);
782 Roo.extend(Roo.bootstrap.Header, Roo.bootstrap.Component, {
790 getAutoCreate : function(){
793 tag: 'h' + (1 *this.level),
794 html: this.html || 'fill in html'
812 * @class Roo.bootstrap.Menu
813 * @extends Roo.bootstrap.Component
814 * Bootstrap Menu class - container for MenuItems
815 * @cfg {String} type type of menu
819 * @param {Object} config The config object
823 Roo.bootstrap.Menu = function(config){
824 Roo.bootstrap.Menu.superclass.constructor.call(this, config);
827 Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, {
835 getChildContainer : function() {
839 getAutoCreate : function(){
841 //if (['right'].indexOf(this.align)!==-1) {
842 // cfg.cn[1].cls += ' pull-right'
846 cls : 'dropdown-menu'
850 if (this.type==='submenu') {
851 cfg.cls='submenu active'
856 initEvents : function() {
857 // Roo.log("ADD event");
858 // Roo.log(this.triggerEl.dom);
859 this.triggerEl.on('click', this.toggle, this);
860 this.triggerEl.addClass('dropdown-toggle');
865 //Roo.log(e.getTarget());
866 // Roo.log(this.triggerEl.dom);
867 if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
870 var isActive = this.triggerEl.hasClass('open');
871 // if disabled.. ingore
873 //if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
874 // if mobile we use a backdrop because click events don't delegate
875 // $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
878 //var relatedTarget = { relatedTarget: this }
879 //$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
881 //if (e.isDefaultPrevented()) return;
883 this.triggerEl[isActive ? 'removeClass' : 'addClass']('open');
885 // .trigger('shown.bs.dropdown', relatedTarget)
887 this.triggerEl.focus();
893 clearMenus : function()
895 //$(backdrop).remove()
896 Roo.select('.dropdown-toggle',true).each(function(aa) {
897 if (!aa.hasClass('open')) {
901 aa.removeClass('open');
902 //var parent = getParent($(this))
903 //var relatedTarget = { relatedTarget: this }
905 //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
906 //if (e.isDefaultPrevented()) return
907 //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
925 * @class Roo.bootstrap.MenuItem
926 * @extends Roo.bootstrap.Component
927 * Bootstrap MenuItem class
928 * @cfg {String} html the menu label
929 * @cfg {String} href the link
933 * Create a new MenuItem
934 * @param {Object} config The config object
938 Roo.bootstrap.MenuItem = function(config){
939 Roo.bootstrap.MenuItem.superclass.constructor.call(this, config);
942 Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component, {
947 getAutoCreate : function(){
959 cfg.cn[0].href = this.href || cfg.cn[0].href ;
960 cfg.cn[0].html = this.html || cfg.cn[0].html ;
977 * @class Roo.bootstrap.MenuSeparator
978 * @extends Roo.bootstrap.Component
979 * Bootstrap MenuSeparator class
982 * Create a new MenuItem
983 * @param {Object} config The config object
987 Roo.bootstrap.MenuSeparator = function(config){
988 Roo.bootstrap.MenuSeparator.superclass.constructor.call(this, config);
991 Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component, {
993 getAutoCreate : function(){
1008 <div class="modal fade">
1009 <div class="modal-dialog">
1010 <div class="modal-content">
1011 <div class="modal-header">
1012 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
1013 <h4 class="modal-title">Modal title</h4>
1015 <div class="modal-body">
1016 <p>One fine body…</p>
1018 <div class="modal-footer">
1019 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
1020 <button type="button" class="btn btn-primary">Save changes</button>
1022 </div><!-- /.modal-content -->
1023 </div><!-- /.modal-dialog -->
1024 </div><!-- /.modal -->
1034 * @class Roo.bootstrap.Modal
1035 * @extends Roo.bootstrap.Component
1036 * Bootstrap Modal class
1037 * @cfg {String} title Title of dialog
1038 * @cfg {Array} buttons Array of buttons
1041 * Create a new Modal Dialog
1042 * @param {Object} config The config object
1045 Roo.bootstrap.Modal = function(config){
1046 Roo.bootstrap.Modal.superclass.constructor.call(this, config);
1049 Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component, {
1051 title : 'test dialog',
1055 onRender : function(ct, position)
1057 Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
1059 var cfg = Roo.apply({}, this.getAutoCreate());
1062 // cfg.name = typeof(this.name) == 'undefined' ? this.id : this.name;
1064 //if (!cfg.name.length) {
1068 cfg.cls += ' ' + this.cls;
1071 cfg.style = this.style;
1073 this.el = Roo.get(document.body).createChild(cfg, position);
1075 //var type = this.el.dom.type;
1077 if(this.tabIndex !== undefined){
1078 this.el.dom.setAttribute('tabIndex', this.tabIndex);
1081 //this.el.addClass([this.fieldClass, this.cls]);
1084 getAutoCreate : function(){
1090 cls: "modal-dialog",
1093 cls : "modal-content",
1096 cls : 'modal-header',
1105 cls : 'modal-title',
1116 cls : 'modal-footer'
1121 cls : 'btn btn-default',
1126 cls : 'btn btn-primary',
1147 getChildContainer : function() {
1149 return this.el.select('.modal-body',true).first();
1152 getButtonContainer : function() {
1153 return this.el.select('.modal-footer',true).first();
1156 initEvents : function()
1158 this.el.select('.modal-header .close').on('click', this.hide, this);
1161 this.el.addClass('on');
1162 this.el.removeClass('fade');
1163 this.el.setStyle('display', 'block');
1166 this.el.removeClass('on');
1167 this.el.addClass('fade');
1168 this.el.setStyle('display', 'none');
1180 * @class Roo.bootstrap.Navbar
1181 * @extends Roo.bootstrap.Component
1182 * Bootstrap Navbar class
1183 * @cfg {Boolean} sidebar has side bar
1184 * @cfg {Boolean} bar is a bar?
1185 * @cfg {String} position (fixed-top|fixed-bottom|static-top) position
1186 * @cfg {String} brand what is brand
1187 * @cfg {Boolean} inverse is inverted color
1188 * @cfg {String} type (nav | pills | tabs)
1189 * @cfg {Boolean} arrangement stacked | justified
1190 * @cfg {String} align (left | right) alignment
1194 * Create a new Navbar
1195 * @param {Object} config The config object
1199 Roo.bootstrap.Navbar = function(config){
1200 Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
1203 Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component, {
1215 getAutoCreate : function(){
1220 if (this.sidebar === true) {
1228 if (this.bar === true) {
1236 cls: 'navbar-header',
1241 cls: 'navbar-toggle',
1242 'data-toggle': 'collapse',
1247 html: 'Toggle navigation'
1267 cls: 'collapse navbar-collapse'
1272 cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
1274 if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
1275 cfg.cls += ' navbar-' + this.position;
1276 cfg.tag = this.position == 'fixed-bottom' ? 'footer' : 'header';
1279 if (this.brand !== '') {
1283 cls: 'navbar-brand',
1292 } else if (this.bar === false) {
1295 Roo.log('Property \'bar\' in of Navbar must be either true or false')
1305 if (['tabs','pills'].indexOf(this.type)!==-1) {
1306 cfg.cn[0].cls += ' nav-' + this.type
1308 if (this.type!=='nav') {
1309 Roo.log('nav type must be nav/tabs/pills')
1311 cfg.cn[0].cls += ' navbar-nav'
1314 if (['stacked','justified'].indexOf(this.arrangement)!==-1) {
1315 cfg.cn[0].cls += ' nav-' + this.arrangement;
1318 if (this.align === 'right') {
1319 cfg.cn[0].cls += ' navbar-right';
1322 cfg.cls += ' navbar-inverse';
1330 getChildContainer : function() {
1331 if (this.bar === true) {
1332 return this.el.select('.collapse',true).first();
1350 * @class Roo.bootstrap.NavGroup
1351 * @extends Roo.bootstrap.Component
1352 * Bootstrap NavGroup class
1353 * @cfg {String} align left | right
1354 * @cfg {Boolean} inverse false | true
1357 * Create a new nav group
1358 * @param {Object} config The config object
1361 Roo.bootstrap.NavGroup = function(config){
1362 Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
1365 Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component, {
1371 getAutoCreate : function(){
1372 var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
1376 cls: 'nav navbar-nav'
1379 if (this.parent().sidebar === true) {
1382 cls: 'dashboard-menu'
1388 if (this.form === true) {
1394 if (this.align === 'right') {
1395 cfg.cls += ' navbar-right';
1397 cfg.cls += ' navbar-left';
1402 if (this.align === 'right') {
1403 cfg.cls += ' navbar-right';
1407 cfg.cls += ' navbar-inverse';
1426 * @class Roo.bootstrap.Navbar.Button
1427 * @extends Roo.bootstrap.Component
1428 * Bootstrap Navbar.Button class
1429 * @cfg {String} href link to
1430 * @cfg {String} html content of button
1433 * Create a new Navbar Button
1434 * @param {Object} config The config object
1438 Roo.bootstrap.Navbar.Button = function(config){
1439 Roo.bootstrap.Navbar.Button.superclass.constructor.call(this, config);
1442 Roo.extend(Roo.bootstrap.Navbar.Button, Roo.bootstrap.Component, {
1453 getAutoCreate : function(){
1463 html : this.html || ''
1487 * @class Roo.bootstrap.Navbar.Item
1488 * @extends Roo.bootstrap.Component
1489 * Bootstrap Navbar.Button class
1490 * @cfg {String} href link to
1491 * @cfg {String} html content of button
1492 * @cfg {String} badge text inside badge
1493 * @cfg {String} glyphicon name of glyphicon
1496 * Create a new Navbar Button
1497 * @param {Object} config The config object
1499 Roo.bootstrap.Navbar.Item = function(config){
1500 Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
1503 Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component, {
1511 getAutoCreate : function(){
1513 var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
1515 if (this.parent().parent().sidebar === true) {
1528 cfg.cn[0].html = this.html;
1532 this.cls += ' active';
1536 cfg.cn[0].cls += ' dropdown-toggle';
1537 cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
1541 cfg.cn[0].tag = 'a',
1542 cfg.cn[0].href = this.href;
1545 if (this.glyphicon) {
1546 cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
1562 if (this.glyphicon) {
1563 if(cfg.html){cfg.html = ' ' + this.html};
1567 cls: 'glyphicon glyphicon-' + this.glyphicon
1572 cfg.cn[0].html = this.html || cfg.cn[0].html ;
1576 cfg.cn[0].html += " <span class='caret'></span>";
1577 //}else if (!this.href) {
1578 // cfg.cn[0].tag='p';
1579 // cfg.cn[0].cls='navbar-text';
1582 cfg.cn[0].href=this.href||'#';
1583 cfg.cn[0].html=this.html;
1586 if (this.badge !== '') {
1589 cfg.cn[0].html + ' ',
1602 initEvents: function() {
1603 // Roo.log('init events?');
1604 // Roo.log(this.el.dom);
1605 this.el.select('a',true).on('click',
1607 this.fireEvent('click', this);
1624 * @class Roo.bootstrap.Row
1625 * @extends Roo.bootstrap.Component
1626 * Bootstrap Row class (contains columns...)
1630 * @param {Object} config The config object
1633 Roo.bootstrap.Row = function(config){
1634 Roo.bootstrap.Row.superclass.constructor.call(this, config);
1637 Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component, {
1656 * @class Roo.bootstrap.Element
1657 * @extends Roo.bootstrap.Component
1658 * Bootstrap Element class
1659 * @cfg {String} html contents of the element
1660 * @cfg {String} tag tag of the element
1661 * @cfg {String} cls class of the element
1664 * Create a new Element
1665 * @param {Object} config The config object
1668 Roo.bootstrap.Element = function(config){
1669 Roo.bootstrap.Element.superclass.constructor.call(this, config);
1672 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component, {
1680 getAutoCreate : function(){
1681 var cfg = Roo.apply({}, Roo.bootstrap.Element.superclass.getAutoCreate.call(this));
1704 * @class Roo.bootstrap.Pagination
1705 * @extends Roo.bootstrap.Component
1706 * Bootstrap Pagination class
1707 * @cfg {String} size xs | sm | md | lg
1708 * @cfg {Boolean} inverse false | true
1709 * @cfg {Number} from pagination starting number
1710 * @cfg {Number} to pagination ending number
1711 * @cfg {String} align empty or left | right
1712 * @cfg {Number} active active page number
1715 * Create a new Pagination
1716 * @param {Object} config The config object
1719 Roo.bootstrap.Pagination = function(config){
1720 Roo.bootstrap.Pagination.superclass.constructor.call(this, config);
1723 Roo.extend(Roo.bootstrap.Pagination, Roo.bootstrap.Component, {
1733 getAutoCreate : function(){
1740 cfg.cls += ' inverse';
1758 var from=this.from>0?this.from:1;
1759 var to=this.to-from<=10?this.to:from+10;
1760 var active=this.active>=from&&this.active<=to?this.active:null;
1761 for (var i=from;i<=to;i++) {
1765 cls: active===i?'active':'',
1806 * @class Roo.bootstrap.Slider
1807 * @extends Roo.bootstrap.Component
1808 * Bootstrap Slider class
1811 * Create a new Slider
1812 * @param {Object} config The config object
1815 Roo.bootstrap.Slider = function(config){
1816 Roo.bootstrap.Slider.superclass.constructor.call(this, config);
1819 Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component, {
1821 getAutoCreate : function(){
1825 cls: 'slider slider-sample1 vertical-handler ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all',
1829 cls: 'ui-slider-handle ui-state-default ui-corner-all'
1847 * @class Roo.bootstrap.Table
1848 * @extends Roo.bootstrap.Component
1849 * Bootstrap Table class
1852 * Create a new Table
1853 * @param {Object} config The config object
1856 Roo.bootstrap.Table = function(config){
1857 Roo.bootstrap.Table.superclass.constructor.call(this, config);
1860 Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
1865 getAutoCreate : function(){
1866 var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
1898 * @class Roo.bootstrap.TableCell
1899 * @extends Roo.bootstrap.Component
1900 * Bootstrap TableCell class
1903 * Create a new TableCell
1904 * @param {Object} config The config object
1907 Roo.bootstrap.TableCell = function(config){
1908 Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
1911 Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component, {
1913 getAutoCreate : function(){
1914 var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
1941 * @class Roo.bootstrap.TableRow
1942 * @extends Roo.bootstrap.Component
1943 * Bootstrap TableRow class
1946 * Create a new TableRow
1947 * @param {Object} config The config object
1950 Roo.bootstrap.TableRow = function(config){
1951 Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
1954 Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component, {
1956 getAutoCreate : function(){
1957 var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
1978 * @class Roo.bootstrap.Form
1979 * @extends Roo.bootstrap.Component
1980 * Bootstrap Form class
1981 * @cfg {String} method GET | POST (default POST)
1982 * @cfg {String} labelAlign top | left (default top)
1986 * @param {Object} config The config object
1990 Roo.bootstrap.Form = function(config){
1991 Roo.bootstrap.Form.superclass.constructor.call(this, config);
1994 * @event clientvalidation
1995 * If the monitorValid config option is true, this event fires repetitively to notify of valid state
1996 * @param {Form} this
1997 * @param {Boolean} valid true if the form has passed client-side validation
1999 clientvalidation: true,
2001 * @event beforeaction
2002 * Fires before any action is performed. Return false to cancel the action.
2003 * @param {Form} this
2004 * @param {Action} action The action to be performed
2008 * @event actionfailed
2009 * Fires when an action fails.
2010 * @param {Form} this
2011 * @param {Action} action The action that failed
2013 actionfailed : true,
2015 * @event actioncomplete
2016 * Fires when an action is completed.
2017 * @param {Form} this
2018 * @param {Action} action The action that completed
2020 actioncomplete : true
2025 Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component, {
2028 * @cfg {String} method
2029 * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
2034 * The URL to use for form actions if one isn't supplied in the action options.
2037 * @cfg {Boolean} fileUpload
2038 * Set to true if this form is a file upload.
2042 * @cfg {Object} baseParams
2043 * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
2047 * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
2052 activeAction : null,
2055 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2056 * element by passing it or its id or mask the form itself by passing in true.
2059 waitMsgTarget : false,
2064 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2065 * element by passing it or its id or mask the form itself by passing in true.
2069 getAutoCreate : function(){
2073 method : this.method || 'POST',
2074 id : this.id || Roo.id(),
2078 if (this.labelAlign == 'left' ) {
2079 cfg.cls += ' form-horizontal';
2083 initEvents : function()
2085 this.el.on('submit', this.onSubmit, this);
2090 onSubmit : function(e){
2095 * Returns true if client-side validation on the form is successful.
2098 isValid : function(){
2099 var items = this.getItems();
2101 items.each(function(f){
2110 * Returns true if any fields in this form have changed since their original load.
2113 isDirty : function(){
2115 var items = this.getItems();
2116 items.each(function(f){
2126 * Performs a predefined action (submit or load) or custom actions you define on this form.
2127 * @param {String} actionName The name of the action type
2128 * @param {Object} options (optional) The options to pass to the action. All of the config options listed
2129 * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
2130 * accept other config options):
2132 Property Type Description
2133 ---------------- --------------- ----------------------------------------------------------------------------------
2134 url String The url for the action (defaults to the form's url)
2135 method String The form method to use (defaults to the form's method, or POST if not defined)
2136 params String/Object The params to pass (defaults to the form's baseParams, or none if not defined)
2137 clientValidation Boolean Applies to submit only. Pass true to call form.isValid() prior to posting to
2138 validate the form on the client (defaults to false)
2140 * @return {BasicForm} this
2142 doAction : function(action, options){
2143 if(typeof action == 'string'){
2144 action = new Roo.form.Action.ACTION_TYPES[action](this, options);
2146 if(this.fireEvent('beforeaction', this, action) !== false){
2147 this.beforeAction(action);
2148 action.run.defer(100, action);
2154 beforeAction : function(action){
2155 var o = action.options;
2157 // not really supported yet.. ??
2159 //if(this.waitMsgTarget === true){
2160 this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
2161 //}else if(this.waitMsgTarget){
2162 // this.waitMsgTarget = Roo.get(this.waitMsgTarget);
2163 // this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
2165 // Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
2171 afterAction : function(action, success){
2172 this.activeAction = null;
2173 var o = action.options;
2175 //if(this.waitMsgTarget === true){
2177 //}else if(this.waitMsgTarget){
2178 // this.waitMsgTarget.unmask();
2180 // Roo.MessageBox.updateProgress(1);
2181 // Roo.MessageBox.hide();
2188 Roo.callback(o.success, o.scope, [this, action]);
2189 this.fireEvent('actioncomplete', this, action);
2193 // failure condition..
2194 // we have a scenario where updates need confirming.
2195 // eg. if a locking scenario exists..
2196 // we look for { errors : { needs_confirm : true }} in the response.
2198 (typeof(action.result) != 'undefined') &&
2199 (typeof(action.result.errors) != 'undefined') &&
2200 (typeof(action.result.errors.needs_confirm) != 'undefined')
2203 Roo.log("not supported yet");
2206 Roo.MessageBox.confirm(
2207 "Change requires confirmation",
2208 action.result.errorMsg,
2213 _t.doAction('submit', { params : { _submit_confirmed : 1 } } );
2223 Roo.callback(o.failure, o.scope, [this, action]);
2224 // show an error message if no failed handler is set..
2225 if (!this.hasListener('actionfailed')) {
2226 Roo.log("need to add dialog support");
2228 Roo.MessageBox.alert("Error",
2229 (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
2230 action.result.errorMsg :
2231 "Saving Failed, please check your entries or try again"
2236 this.fireEvent('actionfailed', this, action);
2241 * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
2242 * @param {String} id The value to search for
2245 findField : function(id){
2246 var items = this.getItems();
2247 var field = items.get(id);
2249 this.items.each(function(f){
2250 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
2257 return field || null;
2260 * Mark fields in this form invalid in bulk.
2261 * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
2262 * @return {BasicForm} this
2264 markInvalid : function(errors){
2265 if(errors instanceof Array){
2266 for(var i = 0, len = errors.length; i < len; i++){
2267 var fieldError = errors[i];
2268 var f = this.findField(fieldError.id);
2270 f.markInvalid(fieldError.msg);
2276 if(typeof errors[id] != 'function' && (field = this.findField(id))){
2277 field.markInvalid(errors[id]);
2281 //Roo.each(this.childForms || [], function (f) {
2282 // f.markInvalid(errors);
2289 * Set values for fields in this form in bulk.
2290 * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
2291 * @return {BasicForm} this
2293 setValues : function(values){
2294 if(values instanceof Array){ // array of objects
2295 for(var i = 0, len = values.length; i < len; i++){
2297 var f = this.findField(v.id);
2299 f.setValue(v.value);
2300 if(this.trackResetOnLoad){
2301 f.originalValue = f.getValue();
2305 }else{ // object hash
2308 if(typeof values[id] != 'function' && (field = this.findField(id))){
2310 if (field.setFromData &&
2312 field.displayField &&
2313 // combos' with local stores can
2314 // be queried via setValue()
2315 // to set their value..
2316 (field.store && !field.store.isLocal)
2320 sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
2321 sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
2322 field.setFromData(sd);
2325 field.setValue(values[id]);
2329 if(this.trackResetOnLoad){
2330 field.originalValue = field.getValue();
2336 //Roo.each(this.childForms || [], function (f) {
2337 // f.setValues(values);
2344 * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
2345 * they are returned as an array.
2346 * @param {Boolean} asString
2349 getValues : function(asString){
2350 //if (this.childForms) {
2351 // copy values from the child forms
2352 // Roo.each(this.childForms, function (f) {
2353 // this.setValues(f.getValues());
2359 var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
2360 if(asString === true){
2363 return Roo.urlDecode(fs);
2367 * Returns the fields in this form as an object with key/value pairs.
2368 * This differs from getValues as it calls getValue on each child item, rather than using dom data.
2371 getFieldValues : function(with_hidden)
2373 var items = this.getItems();
2375 items.each(function(f){
2379 var v = f.getValue();
2380 if (f.inputType =='radio') {
2381 if (typeof(ret[f.getName()]) == 'undefined') {
2382 ret[f.getName()] = ''; // empty..
2385 if (!f.el.dom.checked) {
2393 // not sure if this supported any more..
2394 if ((typeof(v) == 'object') && f.getRawValue) {
2395 v = f.getRawValue() ; // dates..
2397 // combo boxes where name != hiddenName...
2398 if (f.name != f.getName()) {
2399 ret[f.name] = f.getRawValue();
2401 ret[f.getName()] = v;
2408 * Clears all invalid messages in this form.
2409 * @return {BasicForm} this
2411 clearInvalid : function(){
2412 var items = this.getItems();
2414 items.each(function(f){
2425 * @return {BasicForm} this
2428 var items = this.getItems();
2429 items.each(function(f){
2433 Roo.each(this.childForms || [], function (f) {
2440 getItems : function()
2443 var iter = function(el) {
2459 * Ext JS Library 1.1.1
2460 * Copyright(c) 2006-2007, Ext JS, LLC.
2462 * Originally Released Under LGPL - original licence link has changed is not relivant.
2465 * <script type="text/javascript">
2468 * @class Roo.form.VTypes
2469 * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
2472 Roo.form.VTypes = function(){
2473 // closure these in so they are only created once.
2474 var alpha = /^[a-zA-Z_]+$/;
2475 var alphanum = /^[a-zA-Z0-9_]+$/;
2476 var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
2477 var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
2479 // All these messages and functions are configurable
2482 * The function used to validate email addresses
2483 * @param {String} value The email address
2485 'email' : function(v){
2486 return email.test(v);
2489 * The error text to display when the email validation function returns false
2492 'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
2494 * The keystroke filter mask to be applied on email input
2497 'emailMask' : /[a-z0-9_\.\-@]/i,
2500 * The function used to validate URLs
2501 * @param {String} value The URL
2503 'url' : function(v){
2507 * The error text to display when the url validation function returns false
2510 'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
2513 * The function used to validate alpha values
2514 * @param {String} value The value
2516 'alpha' : function(v){
2517 return alpha.test(v);
2520 * The error text to display when the alpha validation function returns false
2523 'alphaText' : 'This field should only contain letters and _',
2525 * The keystroke filter mask to be applied on alpha input
2528 'alphaMask' : /[a-z_]/i,
2531 * The function used to validate alphanumeric values
2532 * @param {String} value The value
2534 'alphanum' : function(v){
2535 return alphanum.test(v);
2538 * The error text to display when the alphanumeric validation function returns false
2541 'alphanumText' : 'This field should only contain letters, numbers and _',
2543 * The keystroke filter mask to be applied on alphanumeric input
2546 'alphanumMask' : /[a-z0-9_]/i
2556 * @class Roo.bootstrap.Input
2557 * @extends Roo.bootstrap.Component
2558 * Bootstrap Input class
2559 * @cfg {Boolean} disabled is it disabled
2560 * @cfg {String} fieldLabel - the label associated
2561 * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
2562 * @cfg {String} name name of the input
2563 * @cfg {string} fieldLabel - the label associated
2564 * @cfg {string} inputType - input / file submit ...
2565 * @cfg {string} placeholder - placeholder to put in text.
2566 * @cfg {string} before - input group add on before
2567 * @cfg {string} after - input group add on after
2571 * Create a new Input
2572 * @param {Object} config The config object
2575 Roo.bootstrap.Input = function(config){
2576 Roo.bootstrap.Input.superclass.constructor.call(this, config);
2581 * Fires when this field receives input focus.
2582 * @param {Roo.form.Field} this
2587 * Fires when this field loses input focus.
2588 * @param {Roo.form.Field} this
2593 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
2594 * {@link Roo.EventObject#getKey} to determine which key was pressed.
2595 * @param {Roo.form.Field} this
2596 * @param {Roo.EventObject} e The event object
2601 * Fires just before the field blurs if the field value has changed.
2602 * @param {Roo.form.Field} this
2603 * @param {Mixed} newValue The new value
2604 * @param {Mixed} oldValue The original value
2609 * Fires after the field has been marked as invalid.
2610 * @param {Roo.form.Field} this
2611 * @param {String} msg The validation message
2616 * Fires after the field has been validated with no errors.
2617 * @param {Roo.form.Field} this
2622 * Fires after the key up
2623 * @param {Roo.form.Field} this
2624 * @param {Roo.EventObject} e The event Object
2630 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component, {
2632 * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
2633 automatic validation (defaults to "keyup").
2635 validationEvent : "keyup",
2637 * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
2639 validateOnBlur : true,
2641 * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
2643 validationDelay : 250,
2645 * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
2647 focusClass : "x-form-focus", // not needed???
2651 * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
2653 invalidClass : "has-error",
2656 * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
2658 selectOnFocus : false,
2661 * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
2665 * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
2670 * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
2672 disableKeyFilter : false,
2675 * @cfg {Boolean} disabled True to disable the field (defaults to false).
2679 * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
2683 * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
2685 blankText : "This field is required",
2688 * @cfg {Number} minLength Minimum input field length required (defaults to 0)
2692 * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
2694 maxLength : Number.MAX_VALUE,
2696 * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
2698 minLengthText : "The minimum length for this field is {0}",
2700 * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
2702 maxLengthText : "The maximum length for this field is {0}",
2706 * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
2707 * If available, this function will be called only after the basic validators all return true, and will be passed the
2708 * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
2712 * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
2713 * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
2714 * current field value. If the test fails, the field will be marked invalid using {@link #regexText}.
2718 * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
2736 getAutoCreate : function(){
2738 var parent = this.parent();
2740 var align = parent.labelAlign;
2745 cls: 'form-group' //input-group
2751 type : this.inputType,
2752 cls : 'form-control',
2753 placeholder : this.placeholder || ''
2760 var inputblock = input;
2762 if (this.before || this.after) {
2765 cls : 'input-group',
2769 inputblock.cn.push({
2771 cls : 'input-group-addon',
2775 inputblock.cn.push(input);
2777 inputblock.cn.push({
2779 cls : 'input-group-addon',
2787 Roo.log(this.fieldLabel.length);
2789 if (align ==='left' && this.fieldLabel.length) {
2790 Roo.log("left and has label");
2796 cls : 'col-sm-2 control-label',
2797 html : this.fieldLabel
2808 } else if ( this.fieldLabel.length) {
2814 //cls : 'input-group-addon',
2815 html : this.fieldLabel
2825 Roo.log(" no label && no align");
2838 if (this.disabled) {
2839 input.disabled=true;
2845 * return the real input element.
2847 inputEl: function ()
2849 return this.el.select('input.form-control',true).first();
2851 setDisabled : function(v)
2853 var i = this.inputEl().dom;
2855 i.removeAttribute('disabled');
2859 i.setAttribute('disabled','true');
2861 initEvents : function()
2864 this.inputEl().on("keydown" , this.fireKey, this);
2865 this.inputEl().on("focus", this.onFocus, this);
2866 this.inputEl().on("blur", this.onBlur, this);
2867 this.inputEl().relayEvent('keyup', this);
2869 // reference to original value for reset
2870 this.originalValue = this.getValue();
2871 //Roo.form.TextField.superclass.initEvents.call(this);
2872 if(this.validationEvent == 'keyup'){
2873 this.validationTask = new Roo.util.DelayedTask(this.validate, this);
2874 this.inputEl().on('keyup', this.filterValidation, this);
2876 else if(this.validationEvent !== false){
2877 this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
2880 if(this.selectOnFocus){
2881 this.on("focus", this.preFocus, this);
2884 if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
2885 this.inputEl().on("keypress", this.filterKeys, this);
2888 this.el.on("keyup", this.onKeyUp, this, {buffer:50});
2889 this.el.on("click", this.autoSize, this);
2892 if(this.inputEl().is('input[type=password]') && Roo.isSafari){
2893 this.inputEl().on('keydown', this.SafariOnKeyDown, this);
2897 filterValidation : function(e){
2898 if(!e.isNavKeyPress()){
2899 this.validationTask.delay(this.validationDelay);
2903 * Validates the field value
2904 * @return {Boolean} True if the value is valid, else false
2906 validate : function(){
2907 //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
2908 if(this.disabled || this.validateValue(this.getRawValue())){
2909 this.clearInvalid();
2917 * Validates a value according to the field's validation rules and marks the field as invalid
2918 * if the validation fails
2919 * @param {Mixed} value The value to validate
2920 * @return {Boolean} True if the value is valid, else false
2922 validateValue : function(value){
2923 if(value.length < 1) { // if it's blank
2924 if(this.allowBlank){
2925 this.clearInvalid();
2928 this.markInvalid(this.blankText);
2932 if(value.length < this.minLength){
2933 this.markInvalid(String.format(this.minLengthText, this.minLength));
2936 if(value.length > this.maxLength){
2937 this.markInvalid(String.format(this.maxLengthText, this.maxLength));
2941 var vt = Roo.form.VTypes;
2942 if(!vt[this.vtype](value, this)){
2943 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
2947 if(typeof this.validator == "function"){
2948 var msg = this.validator(value);
2950 this.markInvalid(msg);
2954 if(this.regex && !this.regex.test(value)){
2955 this.markInvalid(this.regexText);
2964 fireKey : function(e){
2965 //Roo.log('field ' + e.getKey());
2966 if(e.isNavKeyPress()){
2967 this.fireEvent("specialkey", this, e);
2970 onFocus : function(){
2971 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
2972 // this.el.addClass(this.focusClass);
2975 this.hasFocus = true;
2976 this.startValue = this.getValue();
2977 this.fireEvent("focus", this);
2981 beforeBlur : Roo.emptyFn,
2985 onBlur : function(){
2987 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
2988 //this.el.removeClass(this.focusClass);
2990 this.hasFocus = false;
2991 if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
2994 var v = this.getValue();
2995 if(String(v) !== String(this.startValue)){
2996 this.fireEvent('change', this, v, this.startValue);
2998 this.fireEvent("blur", this);
3001 * Returns the normalized data value (undefined or emptyText will be returned as ''). To return the raw value see {@link #getRawValue}.
3002 * @return {Mixed} value The field value
3004 getValue : function(){
3005 var v = this.inputEl().getValue();
3009 * Returns the raw data value which may or may not be a valid, defined value. To return a normalized value see {@link #getValue}.
3010 * @return {Mixed} value The field value
3012 getRawValue : function(){
3013 var v = this.inputEl().getValue();
3018 * Sets a data value into the field and validates it. To set the value directly without validation see {@link #setRawValue}.
3019 * @param {Mixed} value The value to set
3021 setValue : function(v){
3024 this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
3030 processValue : function(value){
3031 if(this.stripCharsRe){
3032 var newValue = value.replace(this.stripCharsRe, '');
3033 if(newValue !== value){
3034 this.setRawValue(newValue);
3041 preFocus : function(){
3043 if(this.selectOnFocus){
3044 this.inputEl().dom.select();
3047 filterKeys : function(e){
3049 if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
3052 var c = e.getCharCode(), cc = String.fromCharCode(c);
3053 if(Roo.isIE && (e.isSpecialKey() || !cc)){
3056 if(!this.maskRe.test(cc)){
3061 * Clear any invalid styles/messages for this field
3063 clearInvalid : function(){
3065 if(!this.el || this.preventMark){ // not rendered
3068 this.el.removeClass(this.invalidClass);
3070 switch(this.msgTarget){
3072 this.el.dom.qtip = '';
3075 this.el.dom.title = '';
3079 Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
3084 this.errorIcon.dom.qtip = '';
3085 this.errorIcon.hide();
3086 this.un('resize', this.alignErrorIcon, this);
3090 var t = Roo.getDom(this.msgTarget);
3092 t.style.display = 'none';
3096 this.fireEvent('valid', this);
3099 * Mark this field as invalid
3100 * @param {String} msg The validation message
3102 markInvalid : function(msg){
3103 if(!this.el || this.preventMark){ // not rendered
3106 this.el.addClass(this.invalidClass);
3108 msg = msg || this.invalidText;
3109 switch(this.msgTarget){
3111 this.el.dom.qtip = msg;
3112 this.el.dom.qclass = 'x-form-invalid-tip';
3113 if(Roo.QuickTips){ // fix for floating editors interacting with DND
3114 Roo.QuickTips.enable();
3118 this.el.dom.title = msg;
3122 var elp = this.el.findParent('.x-form-element', 5, true);
3123 this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
3124 this.errorEl.setWidth(elp.getWidth(true)-20);
3126 this.errorEl.update(msg);
3127 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
3130 if(!this.errorIcon){
3131 var elp = this.el.findParent('.x-form-element', 5, true);
3132 this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
3134 this.alignErrorIcon();
3135 this.errorIcon.dom.qtip = msg;
3136 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
3137 this.errorIcon.show();
3138 this.on('resize', this.alignErrorIcon, this);
3141 var t = Roo.getDom(this.msgTarget);
3143 t.style.display = this.msgDisplay;
3147 this.fireEvent('invalid', this, msg);
3150 SafariOnKeyDown : function(event)
3152 // this is a workaround for a password hang bug on chrome/ webkit.
3154 var isSelectAll = false;
3156 if(this.inputEl().dom.selectionEnd > 0){
3157 isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
3159 if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
3160 event.preventDefault();
3165 if(isSelectAll){ // backspace and delete key
3167 event.preventDefault();
3168 // this is very hacky as keydown always get's upper case.
3170 var cc = String.fromCharCode(event.getCharCode());
3171 this.setValue( event.shiftKey ? cc : cc.toLowerCase());