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)));
143 if (!tree.items || !tree.items.length) {
147 var items = tree.items;
150 //Roo.log(items.length);
152 for(var i =0;i < items.length;i++) {
153 nitems.push(cn.addxtype(Roo.apply({}, items[i])));
173 Roo.bootstrap.Body = function(config){
174 Roo.bootstrap.Body.superclass.constructor.call(this, config);
175 this.el = Roo.get(document.body);
178 Roo.extend(Roo.bootstrap.Body, Roo.bootstrap.Component, {
183 onRender : function(ct, position){
186 //this.el.addClass([this.fieldClass, this.cls]);
204 * @class Roo.bootstrap.ButtonGroup
205 * @extends Roo.bootstrap.Component
206 * Bootstrap ButtonGroup class
207 * @cfg {String} size lg | sm | xs (default empty normal)
208 * @cfg {String} align vertical | justified (default none)
209 * @cfg {String} direction up | down (default down)
210 * @cfg {Boolean} toolbar false | true
211 * @cfg {Boolean} btn true | false
216 * @param {Object} config The config object
219 Roo.bootstrap.ButtonGroup = function(config){
220 Roo.bootstrap.ButtonGroup.superclass.constructor.call(this, config);
223 Roo.extend(Roo.bootstrap.ButtonGroup, Roo.bootstrap.Component, {
231 getAutoCreate : function(){
237 cfg.html = this.html || cfg.html;
248 if (['vertical','justified'].indexOf(this.align)!==-1) {
249 cfg.cls = 'btn-group-' + this.align;
251 if (this.align == 'justified') {
252 console.log(this.items);
256 if (['lg','sm','xs'].indexOf(this.size)!==-1) {
257 cfg.cls += ' btn-group-' + this.size;
260 if (this.direction == 'up') {
261 cfg.cls += ' dropup' ;
277 * @class Roo.bootstrap.Button
278 * @extends Roo.bootstrap.Component
279 * Bootstrap Button class
280 * @cfg {String} html The button content
281 * @cfg {String} weight default (or empty) | primary | success | info | warning | danger
282 * @cfg {String} size empty | lg | sm | xs
283 * @cfg {String} tag empty | a | input | submit
284 * @cfg {String} href empty or href
285 * @cfg {Boolean} disabled false | true
286 * @cfg {Boolean} isClose false | true
287 * @cfg {String} glyphicon empty | adjust | align-center | align-justify | align-left | align-right | arrow-down | arrow-left | arrow-right | arrow-up | asterisk | backward | ban-circle | barcode | bell | bold | book | bookmark | briefcase | bullhorn | calendar | camera | certificate | check | chevron-down | chevron-left | chevron-right | chevron-up | circle-arrow-down | circle-arrow-left | circle-arrow-right | circle-arrow-up | cloud | cloud-download | cloud-upload | cog | collapse-down | collapse-up | comment | compressed | copyright-mark | credit-card | cutlery | dashboard | download | download-alt | earphone | edit | eject | envelope | euro | exclamation-sign | expand | export | eye-close | eye-open | facetime-video | fast-backward | fast-forward | file | film | filter | fire | flag | flash | floppy-disk | floppy-open | floppy-remove | floppy-save | floppy-saved | folder-close | folder-open | font | forward | fullscreen | gbp | gift | glass | globe | hand-down | hand-left | hand-right | hand-up | hd-video | hdd | header | headphones | heart | heart-empty | home | import | inbox | indent-left | indent-right | info-sign | italic | leaf | link | list | list-alt | lock | log-in | log-out | magnet | map-marker | minus | minus-sign | move | music | new-window | off | ok | ok-circle | ok-sign | open | paperclip | pause | pencil | phone | phone-alt | picture | plane | play | play-circle | plus | plus-sign | print | pushpin | qrcode | question-sign | random | record | refresh | registration-mark | remove | remove-circle | remove-sign | repeat | resize-full | resize-horizontal | resize-small | resize-vertical | retweet | road | save | saved | screenshot | sd-video | search | send | share | share-alt | shopping-cart | signal | sort | sort-by-alphabet | sort-by-alphabet-alt | sort-by-attributes | sort-by-attributes-alt | sort-by-order | sort-by-order-alt | sound-5-1 | sound-6-1 | sound-7-1 | sound-dolby | sound-stereo | star | star-empty | stats | step-backward | step-forward | stop | subtitles | tag | tags | tasks | text-height | text-width | th | th-large | th-list | thumbs-down | thumbs-up | time | tint | tower | transfer | trash | tree-conifer | tree-deciduous | unchecked | upload | usd | user | volume-down | volume-off | volume-up | warning-sign | wrench | zoom-in | zoom-out
288 * @cfg {String} badge text for badge
289 * @cfg {String} theme default (or empty) | glow
290 * @cfg {Boolean} inverse false | true
291 * @cfg {Boolean} toggle false | true
292 * @cfg {String} ontext text for on toggle state
293 * @cfg {String} offtext text for off toggle state
294 * @cfg {Boolean} defaulton true | false
297 * Create a new button
298 * @param {Object} config The config object
302 Roo.bootstrap.Button = function(config){
303 Roo.bootstrap.Button.superclass.constructor.call(this, config);
308 * The raw click event for the entire grid.
309 * @param {Roo.EventObject} e
315 Roo.extend(Roo.bootstrap.Button, Roo.bootstrap.Component, {
334 getAutoCreate : function(){
342 if (['a', 'button', 'input', 'submit'].indexOf(this.tag) < 0) {
343 throw "Invalid value for tag: " + this.tag + ". must be a, button, input or submit.";
348 cfg.html = this.html || cfg.html;
350 if (this.toggle===true) {
353 cls: 'slider-frame roo-button',
358 'data-off-text':'OFF',
359 cls: 'slider-button',
365 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
366 cfg.cls += ' '+this.weight;
375 cfg["aria-hidden"] = true;
377 cfg.html = "×";
383 if (this.theme==='default') {
384 cfg.cls = 'btn roo-button';
386 if (this.parentType != 'Navbar') {
387 this.weight = this.weight.length ? this.weight : 'default';
389 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
391 cfg.cls += ' btn-' + this.weight;
393 } else if (this.theme==='glow') {
396 cfg.cls = 'btn-glow roo-button';
398 if (['default', 'primary', 'success', 'info', 'warning', 'danger', 'link'].indexOf(this.weight) > -1) {
400 cfg.cls += ' ' + this.weight;
406 this.cls += ' inverse';
411 cfg.cls += ' active';
414 cfg.cls += this.size.length ? (' btn-' + this.size) : '';
416 //gsRoo.log(this.parentType);
417 if (this.parentType === 'Navbar') {
425 href : this.href || '#'
428 cfg.cn[0].html = this.html + ' <span class="caret"></span>';
429 cfg.cls += ' dropdown';
434 } else if (this.menu) {
436 cfg.cls += ' dropdown test';
442 cfg.disabled = 'disabled';
446 Roo.log('changing to ul' );
448 this.glyphicon = 'caret';
451 if (this.glyphicon) {
452 cfg.html = ' ' + cfg.html;
457 cls: 'glyphicon glyphicon-' + this.glyphicon
467 cfg.cls='btn roo-button';
483 if (cfg.tag !== 'a' && this.href !== '') {
484 throw "Tag must be a to set href.";
485 } else if (this.href.length > 0) {
486 cfg.href = this.href;
491 initEvents: function() {
492 // Roo.log('init events?');
493 // Roo.log(this.el.dom);
494 if (this.el.hasClass('roo-button')) {
495 this.el.on('click', this.onClick, this);
497 this.el.select('.roo-button').on('click', this.onClick, this);
503 onClick : function(e)
505 Roo.log('button on click ');
507 this.fireEvent('click', this, e);
521 * @class Roo.bootstrap.Column
522 * @extends Roo.bootstrap.Component
523 * Bootstrap Column class
524 * @cfg {Number} xs colspan out of 12 for mobile-sized screens
525 * @cfg {Number} sm colspan out of 12 for tablet-sized screens
526 * @cfg {Number} md colspan out of 12 for computer-sized screens
527 * @cfg {Number} lg colspan out of 12 for large computer-sized screens
528 * @cfg {String} html content of column.
531 * Create a new Column
532 * @param {Object} config The config object
535 Roo.bootstrap.Column = function(config){
536 Roo.bootstrap.Column.superclass.constructor.call(this, config);
539 Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component, {
548 getAutoCreate : function(){
549 var cfg = Roo.apply({}, Roo.bootstrap.Column.superclass.getAutoCreate.call(this));
557 ['xs','sm','md','lg'].map(function(size){
558 if (settings[size]) {
559 cfg.cls += ' col-' + size + '-' + settings[size];
562 if (this.html.length) {
563 cfg.html = this.html;
582 * @class Roo.bootstrap.Container
583 * @extends Roo.bootstrap.Component
584 * Bootstrap Container class
585 * @cfg {Boolean} jumbotron is it a jumbotron element
586 * @cfg {String} html content of element
587 * @cfg {String} well (lg|sm|md) a well, large, small or medium.
588 * @cfg {String} panel (primary|success|info|warning|danger) render as a panel.
589 * @cfg {String} header content of header (for panel)
590 * @cfg {String} footer content of footer (for panel)
591 * @cfg {String} sticky (footer|wrap|push) block to use as footer or body- needs css-bootstrap/sticky-footer.css
594 * Create a new Container
595 * @param {Object} config The config object
598 Roo.bootstrap.Container = function(config){
599 Roo.bootstrap.Container.superclass.constructor.call(this, config);
602 Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component, {
612 getChildContainer : function() {
613 if (this.panel.length) {
614 return this.el.select('.panel-body',true).first();
621 getAutoCreate : function(){
627 if (this.jumbotron) {
628 cfg.cls = 'jumbotron';
631 cfg.cls = this.cls + '';
634 if (this.sticky.length) {
635 var bd = Roo.get(document.body);
636 if (!bd.hasClass('bootstrap-sticky')) {
637 bd.addClass('bootstrap-sticky');
638 Roo.select('html',true).setStyle('height', '100%');
641 cfg.cls += 'bootstrap-sticky-' + this.sticky;
645 if (this.well.length) {
649 cfg.cls +=' well well-' +this.well;
659 if (this.panel.length) {
660 cfg.cls += 'panel panel-' + this.panel;
662 if (this.header.length) {
665 cls : 'panel-heading',
681 if (this.footer.length) {
683 cls : 'panel-footer',
691 body.html = this.html || cfg.html;
693 if (!cfg.cls.length) {
694 cfg.cls = 'container';
711 * @class Roo.bootstrap.Img
712 * @extends Roo.bootstrap.Component
713 * Bootstrap Img class
714 * @cfg {Boolean} imgResponsive false | true
715 * @cfg {String} border rounded | circle | thumbnail
716 * @cfg {String} src image source
717 * @cfg {String} alt image alternative text
721 * @param {Object} config The config object
724 Roo.bootstrap.Img = function(config){
725 Roo.bootstrap.Img.superclass.constructor.call(this, config);
728 Roo.extend(Roo.bootstrap.Img, Roo.bootstrap.Component, {
734 getAutoCreate : function(){
738 cls: 'img-responsive',
742 cfg.html = this.html || cfg.html;
744 cfg.src = this.src || cfg.src;
746 if (['rounded','circle','thumbnail'].indexOf(this.border)>-1) {
747 cfg.cls += ' img-' + this.border;
767 * @class Roo.bootstrap.Header
768 * @extends Roo.bootstrap.Component
769 * Bootstrap Header class
770 * @cfg {String} html content of header
771 * @cfg {Number} level (1|2|3|4|5|6) default 1
774 * Create a new Header
775 * @param {Object} config The config object
779 Roo.bootstrap.Header = function(config){
780 Roo.bootstrap.Header.superclass.constructor.call(this, config);
783 Roo.extend(Roo.bootstrap.Header, Roo.bootstrap.Component, {
791 getAutoCreate : function(){
794 tag: 'h' + (1 *this.level),
795 html: this.html || 'fill in html'
813 * @class Roo.bootstrap.Menu
814 * @extends Roo.bootstrap.Component
815 * Bootstrap Menu class - container for MenuItems
816 * @cfg {String} type type of menu
820 * @param {Object} config The config object
824 Roo.bootstrap.Menu = function(config){
825 Roo.bootstrap.Menu.superclass.constructor.call(this, config);
828 Roo.extend(Roo.bootstrap.Menu, Roo.bootstrap.Component, {
836 getChildContainer : function() {
840 getAutoCreate : function(){
842 //if (['right'].indexOf(this.align)!==-1) {
843 // cfg.cn[1].cls += ' pull-right'
847 cls : 'dropdown-menu'
851 if (this.type==='submenu') {
852 cfg.cls='submenu active'
857 initEvents : function() {
858 // Roo.log("ADD event");
859 // Roo.log(this.triggerEl.dom);
860 this.triggerEl.on('click', this.toggle, this);
861 this.triggerEl.addClass('dropdown-toggle');
866 //Roo.log(e.getTarget());
867 // Roo.log(this.triggerEl.dom);
868 if (Roo.get(e.getTarget()).findParent('.dropdown-menu')) {
871 var isActive = this.triggerEl.hasClass('open');
872 // if disabled.. ingore
874 //if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
875 // if mobile we use a backdrop because click events don't delegate
876 // $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
879 //var relatedTarget = { relatedTarget: this }
880 //$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
882 //if (e.isDefaultPrevented()) return;
884 this.triggerEl[isActive ? 'removeClass' : 'addClass']('open');
886 // .trigger('shown.bs.dropdown', relatedTarget)
888 this.triggerEl.focus();
894 clearMenus : function()
896 //$(backdrop).remove()
897 Roo.select('.dropdown-toggle',true).each(function(aa) {
898 if (!aa.hasClass('open')) {
902 aa.removeClass('open');
903 //var parent = getParent($(this))
904 //var relatedTarget = { relatedTarget: this }
906 //$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
907 //if (e.isDefaultPrevented()) return
908 //$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
926 * @class Roo.bootstrap.MenuItem
927 * @extends Roo.bootstrap.Component
928 * Bootstrap MenuItem class
929 * @cfg {String} html the menu label
930 * @cfg {String} href the link
934 * Create a new MenuItem
935 * @param {Object} config The config object
939 Roo.bootstrap.MenuItem = function(config){
940 Roo.bootstrap.MenuItem.superclass.constructor.call(this, config);
943 Roo.extend(Roo.bootstrap.MenuItem, Roo.bootstrap.Component, {
948 getAutoCreate : function(){
960 cfg.cn[0].href = this.href || cfg.cn[0].href ;
961 cfg.cn[0].html = this.html || cfg.cn[0].html ;
978 * @class Roo.bootstrap.MenuSeparator
979 * @extends Roo.bootstrap.Component
980 * Bootstrap MenuSeparator class
983 * Create a new MenuItem
984 * @param {Object} config The config object
988 Roo.bootstrap.MenuSeparator = function(config){
989 Roo.bootstrap.MenuSeparator.superclass.constructor.call(this, config);
992 Roo.extend(Roo.bootstrap.MenuSeparator, Roo.bootstrap.Component, {
994 getAutoCreate : function(){
1009 <div class="modal fade">
1010 <div class="modal-dialog">
1011 <div class="modal-content">
1012 <div class="modal-header">
1013 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
1014 <h4 class="modal-title">Modal title</h4>
1016 <div class="modal-body">
1017 <p>One fine body…</p>
1019 <div class="modal-footer">
1020 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
1021 <button type="button" class="btn btn-primary">Save changes</button>
1023 </div><!-- /.modal-content -->
1024 </div><!-- /.modal-dialog -->
1025 </div><!-- /.modal -->
1035 * @class Roo.bootstrap.Modal
1036 * @extends Roo.bootstrap.Component
1037 * Bootstrap Modal class
1038 * @cfg {String} title Title of dialog
1039 * @cfg {Array} buttons Array of buttons or standard button set..
1042 * Create a new Modal Dialog
1043 * @param {Object} config The config object
1046 Roo.bootstrap.Modal = function(config){
1047 Roo.bootstrap.Modal.superclass.constructor.call(this, config);
1052 * The raw click event for the entire grid.
1053 * @param {Roo.EventObject} e
1059 Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component, {
1061 title : 'test dialog',
1065 onRender : function(ct, position)
1067 Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
1069 var cfg = Roo.apply({}, this.getAutoCreate());
1072 // cfg.name = typeof(this.name) == 'undefined' ? this.id : this.name;
1074 //if (!cfg.name.length) {
1078 cfg.cls += ' ' + this.cls;
1081 cfg.style = this.style;
1083 this.el = Roo.get(document.body).createChild(cfg, position);
1085 //var type = this.el.dom.type;
1087 if(this.tabIndex !== undefined){
1088 this.el.dom.setAttribute('tabIndex', this.tabIndex);
1093 this.maskEl = Roo.DomHelper.append(document.body, {tag: "div", cls:"x-dlg-mask"}, true);
1094 this.maskEl.enableDisplayMode("block");
1096 //this.el.addClass("x-dlg-modal");
1100 Roo.each(this.buttons, function(bb) {
1101 b = Roo.apply({}, bb);
1102 b.xns = b.xns || Roo.bootstrap;
1103 b.xtype = b.xtype || 'Button';
1104 if (typeof(b.listeners) == 'undefined') {
1105 b.listeners = { click : this.onButtonClick.createDelegate(this) };
1108 var btn = Roo.factory(b);
1110 btn.onRender(this.el.select('.modal-footer').first());
1118 //this.el.addClass([this.fieldClass, this.cls]);
1121 getAutoCreate : function(){
1126 html : this.html || ''
1134 cls: "modal-dialog",
1137 cls : "modal-content",
1140 cls : 'modal-header',
1149 cls : 'modal-title',
1157 cls : 'modal-footer'
1173 getChildContainer : function() {
1175 return this.el.select('.modal-body',true).first();
1178 getButtonContainer : function() {
1179 return this.el.select('.modal-footer',true).first();
1182 initEvents : function()
1184 this.el.select('.modal-header .close').on('click', this.hide, this);
1187 if (!this.rendered) {
1191 this.el.addClass('on');
1192 this.el.removeClass('fade');
1193 this.el.setStyle('display', 'block');
1194 Roo.get(document.body).addClass("x-body-masked");
1195 this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
1197 this.el.setStyle('zIndex', '10001');
1204 this.el.removeClass('on');
1205 this.el.addClass('fade');
1206 this.el.setStyle('display', 'none');
1208 onButtonClick: function(btn,e)
1211 this.fireEvent('btnclick', btn.name, e);
1216 Roo.apply(Roo.bootstrap.Modal, {
1218 * Button config that displays a single OK button
1227 * Button config that displays Yes and No buttons
1243 * Button config that displays OK and Cancel buttons
1258 * Button config that displays Yes, No and Cancel buttons
1286 * @class Roo.bootstrap.Navbar
1287 * @extends Roo.bootstrap.Component
1288 * Bootstrap Navbar class
1289 * @cfg {Boolean} sidebar has side bar
1290 * @cfg {Boolean} bar is a bar?
1291 * @cfg {String} position (fixed-top|fixed-bottom|static-top) position
1292 * @cfg {String} brand what is brand
1293 * @cfg {Boolean} inverse is inverted color
1294 * @cfg {String} type (nav | pills | tabs)
1295 * @cfg {Boolean} arrangement stacked | justified
1296 * @cfg {String} align (left | right) alignment
1300 * Create a new Navbar
1301 * @param {Object} config The config object
1305 Roo.bootstrap.Navbar = function(config){
1306 Roo.bootstrap.Navbar.superclass.constructor.call(this, config);
1309 Roo.extend(Roo.bootstrap.Navbar, Roo.bootstrap.Component, {
1321 getAutoCreate : function(){
1326 if (this.sidebar === true) {
1334 if (this.bar === true) {
1342 cls: 'navbar-header',
1347 cls: 'navbar-toggle',
1348 'data-toggle': 'collapse',
1353 html: 'Toggle navigation'
1373 cls: 'collapse navbar-collapse'
1378 cfg.cls += this.inverse ? ' navbar-inverse' : ' navbar-default';
1380 if (['fixed-top','fixed-bottom','static-top'].indexOf(this.position)>-1) {
1381 cfg.cls += ' navbar-' + this.position;
1382 cfg.tag = this.position == 'fixed-bottom' ? 'footer' : 'header';
1385 if (this.brand !== '') {
1389 cls: 'navbar-brand',
1398 } else if (this.bar === false) {
1401 Roo.log('Property \'bar\' in of Navbar must be either true or false')
1411 if (['tabs','pills'].indexOf(this.type)!==-1) {
1412 cfg.cn[0].cls += ' nav-' + this.type
1414 if (this.type!=='nav') {
1415 Roo.log('nav type must be nav/tabs/pills')
1417 cfg.cn[0].cls += ' navbar-nav'
1420 if (['stacked','justified'].indexOf(this.arrangement)!==-1) {
1421 cfg.cn[0].cls += ' nav-' + this.arrangement;
1424 if (this.align === 'right') {
1425 cfg.cn[0].cls += ' navbar-right';
1428 cfg.cls += ' navbar-inverse';
1436 getChildContainer : function() {
1437 if (this.bar === true) {
1438 return this.el.select('.collapse',true).first();
1456 * @class Roo.bootstrap.NavGroup
1457 * @extends Roo.bootstrap.Component
1458 * Bootstrap NavGroup class
1459 * @cfg {String} align left | right
1460 * @cfg {Boolean} inverse false | true
1463 * Create a new nav group
1464 * @param {Object} config The config object
1467 Roo.bootstrap.NavGroup = function(config){
1468 Roo.bootstrap.NavGroup.superclass.constructor.call(this, config);
1471 Roo.extend(Roo.bootstrap.NavGroup, Roo.bootstrap.Component, {
1477 getAutoCreate : function(){
1478 var cfg = Roo.apply({}, Roo.bootstrap.NavGroup.superclass.getAutoCreate.call(this));
1482 cls: 'nav navbar-nav'
1485 if (this.parent().sidebar === true) {
1488 cls: 'dashboard-menu'
1494 if (this.form === true) {
1500 if (this.align === 'right') {
1501 cfg.cls += ' navbar-right';
1503 cfg.cls += ' navbar-left';
1508 if (this.align === 'right') {
1509 cfg.cls += ' navbar-right';
1513 cfg.cls += ' navbar-inverse';
1532 * @class Roo.bootstrap.Navbar.Button
1533 * @extends Roo.bootstrap.Component
1534 * Bootstrap Navbar.Button class
1535 * @cfg {String} href link to
1536 * @cfg {String} html content of button
1539 * Create a new Navbar Button
1540 * @param {Object} config The config object
1544 Roo.bootstrap.Navbar.Button = function(config){
1545 Roo.bootstrap.Navbar.Button.superclass.constructor.call(this, config);
1548 Roo.extend(Roo.bootstrap.Navbar.Button, Roo.bootstrap.Component, {
1559 getAutoCreate : function(){
1569 html : this.html || ''
1593 * @class Roo.bootstrap.Navbar.Item
1594 * @extends Roo.bootstrap.Component
1595 * Bootstrap Navbar.Button class
1596 * @cfg {String} href link to
1597 * @cfg {String} html content of button
1598 * @cfg {String} badge text inside badge
1599 * @cfg {String} glyphicon name of glyphicon
1602 * Create a new Navbar Button
1603 * @param {Object} config The config object
1605 Roo.bootstrap.Navbar.Item = function(config){
1606 Roo.bootstrap.Navbar.Item.superclass.constructor.call(this, config);
1609 Roo.extend(Roo.bootstrap.Navbar.Item, Roo.bootstrap.Component, {
1617 getAutoCreate : function(){
1619 var cfg = Roo.apply({}, Roo.bootstrap.Navbar.Item.superclass.getAutoCreate.call(this));
1621 if (this.parent().parent().sidebar === true) {
1634 cfg.cn[0].html = this.html;
1638 this.cls += ' active';
1642 cfg.cn[0].cls += ' dropdown-toggle';
1643 cfg.cn[0].html = (cfg.cn[0].html || this.html) + '<span class="glyphicon glyphicon-chevron-down"></span>';
1647 cfg.cn[0].tag = 'a',
1648 cfg.cn[0].href = this.href;
1651 if (this.glyphicon) {
1652 cfg.cn[0].html = '<i class="glyphicon glyphicon-'+this.glyphicon+'"></i><span>' + cfg.cn[0].html || this.html + '</span>'
1668 if (this.glyphicon) {
1669 if(cfg.html){cfg.html = ' ' + this.html};
1673 cls: 'glyphicon glyphicon-' + this.glyphicon
1678 cfg.cn[0].html = this.html || cfg.cn[0].html ;
1682 cfg.cn[0].html += " <span class='caret'></span>";
1683 //}else if (!this.href) {
1684 // cfg.cn[0].tag='p';
1685 // cfg.cn[0].cls='navbar-text';
1688 cfg.cn[0].href=this.href||'#';
1689 cfg.cn[0].html=this.html;
1692 if (this.badge !== '') {
1695 cfg.cn[0].html + ' ',
1708 initEvents: function() {
1709 // Roo.log('init events?');
1710 // Roo.log(this.el.dom);
1711 this.el.select('a',true).on('click',
1713 this.fireEvent('click', this);
1730 * @class Roo.bootstrap.Row
1731 * @extends Roo.bootstrap.Component
1732 * Bootstrap Row class (contains columns...)
1736 * @param {Object} config The config object
1739 Roo.bootstrap.Row = function(config){
1740 Roo.bootstrap.Row.superclass.constructor.call(this, config);
1743 Roo.extend(Roo.bootstrap.Row, Roo.bootstrap.Component, {
1762 * @class Roo.bootstrap.Element
1763 * @extends Roo.bootstrap.Component
1764 * Bootstrap Element class
1765 * @cfg {String} html contents of the element
1766 * @cfg {String} tag tag of the element
1767 * @cfg {String} cls class of the element
1770 * Create a new Element
1771 * @param {Object} config The config object
1774 Roo.bootstrap.Element = function(config){
1775 Roo.bootstrap.Element.superclass.constructor.call(this, config);
1778 Roo.extend(Roo.bootstrap.Element, Roo.bootstrap.Component, {
1786 getAutoCreate : function(){
1787 var cfg = Roo.apply({}, Roo.bootstrap.Element.superclass.getAutoCreate.call(this));
1810 * @class Roo.bootstrap.Pagination
1811 * @extends Roo.bootstrap.Component
1812 * Bootstrap Pagination class
1813 * @cfg {String} size xs | sm | md | lg
1814 * @cfg {Boolean} inverse false | true
1815 * @cfg {Number} from pagination starting number
1816 * @cfg {Number} to pagination ending number
1817 * @cfg {String} align empty or left | right
1818 * @cfg {Number} active active page number
1821 * Create a new Pagination
1822 * @param {Object} config The config object
1825 Roo.bootstrap.Pagination = function(config){
1826 Roo.bootstrap.Pagination.superclass.constructor.call(this, config);
1829 Roo.extend(Roo.bootstrap.Pagination, Roo.bootstrap.Component, {
1839 getAutoCreate : function(){
1846 cfg.cls += ' inverse';
1864 var from=this.from>0?this.from:1;
1865 var to=this.to-from<=10?this.to:from+10;
1866 var active=this.active>=from&&this.active<=to?this.active:null;
1867 for (var i=from;i<=to;i++) {
1871 cls: active===i?'active':'',
1912 * @class Roo.bootstrap.Slider
1913 * @extends Roo.bootstrap.Component
1914 * Bootstrap Slider class
1917 * Create a new Slider
1918 * @param {Object} config The config object
1921 Roo.bootstrap.Slider = function(config){
1922 Roo.bootstrap.Slider.superclass.constructor.call(this, config);
1925 Roo.extend(Roo.bootstrap.Slider, Roo.bootstrap.Component, {
1927 getAutoCreate : function(){
1931 cls: 'slider slider-sample1 vertical-handler ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all',
1935 cls: 'ui-slider-handle ui-state-default ui-corner-all'
1953 * @class Roo.bootstrap.Table
1954 * @extends Roo.bootstrap.Component
1955 * Bootstrap Table class
1958 * Create a new Table
1959 * @param {Object} config The config object
1962 Roo.bootstrap.Table = function(config){
1963 Roo.bootstrap.Table.superclass.constructor.call(this, config);
1966 Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
1971 getAutoCreate : function(){
1972 var cfg = Roo.apply({}, Roo.bootstrap.Table.superclass.getAutoCreate.call(this));
2004 * @class Roo.bootstrap.TableCell
2005 * @extends Roo.bootstrap.Component
2006 * Bootstrap TableCell class
2009 * Create a new TableCell
2010 * @param {Object} config The config object
2013 Roo.bootstrap.TableCell = function(config){
2014 Roo.bootstrap.TableCell.superclass.constructor.call(this, config);
2017 Roo.extend(Roo.bootstrap.TableCell, Roo.bootstrap.Component, {
2019 getAutoCreate : function(){
2020 var cfg = Roo.apply({}, Roo.bootstrap.TableCell.superclass.getAutoCreate.call(this));
2047 * @class Roo.bootstrap.TableRow
2048 * @extends Roo.bootstrap.Component
2049 * Bootstrap TableRow class
2052 * Create a new TableRow
2053 * @param {Object} config The config object
2056 Roo.bootstrap.TableRow = function(config){
2057 Roo.bootstrap.TableRow.superclass.constructor.call(this, config);
2060 Roo.extend(Roo.bootstrap.TableRow, Roo.bootstrap.Component, {
2062 getAutoCreate : function(){
2063 var cfg = Roo.apply({}, Roo.bootstrap.TableRow.superclass.getAutoCreate.call(this));
2078 * Ext JS Library 1.1.1
2079 * Copyright(c) 2006-2007, Ext JS, LLC.
2081 * Originally Released Under LGPL - original licence link has changed is not relivant.
2084 * <script type="text/javascript">
2087 // as we use this in bootstrap.
2088 Roo.namespace('Roo.form');
2090 * @class Roo.form.Action
2091 * Internal Class used to handle form actions
2093 * @param {Roo.form.BasicForm} el The form element or its id
2094 * @param {Object} config Configuration options
2099 // define the action interface
2100 Roo.form.Action = function(form, options){
2102 this.options = options || {};
2105 * Client Validation Failed
2108 Roo.form.Action.CLIENT_INVALID = 'client';
2110 * Server Validation Failed
2113 Roo.form.Action.SERVER_INVALID = 'server';
2115 * Connect to Server Failed
2118 Roo.form.Action.CONNECT_FAILURE = 'connect';
2120 * Reading Data from Server Failed
2123 Roo.form.Action.LOAD_FAILURE = 'load';
2125 Roo.form.Action.prototype = {
2127 failureType : undefined,
2128 response : undefined,
2132 run : function(options){
2137 success : function(response){
2142 handleResponse : function(response){
2146 // default connection failure
2147 failure : function(response){
2149 this.response = response;
2150 this.failureType = Roo.form.Action.CONNECT_FAILURE;
2151 this.form.afterAction(this, false);
2154 processResponse : function(response){
2155 this.response = response;
2156 if(!response.responseText){
2159 this.result = this.handleResponse(response);
2163 // utility functions used internally
2164 getUrl : function(appendParams){
2165 var url = this.options.url || this.form.url || this.form.el.dom.action;
2167 var p = this.getParams();
2169 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
2175 getMethod : function(){
2176 return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
2179 getParams : function(){
2180 var bp = this.form.baseParams;
2181 var p = this.options.params;
2183 if(typeof p == "object"){
2184 p = Roo.urlEncode(Roo.applyIf(p, bp));
2185 }else if(typeof p == 'string' && bp){
2186 p += '&' + Roo.urlEncode(bp);
2189 p = Roo.urlEncode(bp);
2194 createCallback : function(){
2196 success: this.success,
2197 failure: this.failure,
2199 timeout: (this.form.timeout*1000),
2200 upload: this.form.fileUpload ? this.success : undefined
2205 Roo.form.Action.Submit = function(form, options){
2206 Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
2209 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
2212 haveProgress : false,
2213 uploadComplete : false,
2215 // uploadProgress indicator.
2216 uploadProgress : function()
2218 if (!this.form.progressUrl) {
2222 if (!this.haveProgress) {
2223 Roo.MessageBox.progress("Uploading", "Uploading");
2225 if (this.uploadComplete) {
2226 Roo.MessageBox.hide();
2230 this.haveProgress = true;
2232 var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
2234 var c = new Roo.data.Connection();
2236 url : this.form.progressUrl,
2241 success : function(req){
2242 //console.log(data);
2246 rdata = Roo.decode(req.responseText)
2248 Roo.log("Invalid data from server..");
2252 if (!rdata || !rdata.success) {
2254 Roo.MessageBox.alert(Roo.encode(rdata));
2257 var data = rdata.data;
2259 if (this.uploadComplete) {
2260 Roo.MessageBox.hide();
2265 Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
2266 Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
2269 this.uploadProgress.defer(2000,this);
2272 failure: function(data) {
2273 Roo.log('progress url failed ');
2284 // run get Values on the form, so it syncs any secondary forms.
2285 this.form.getValues();
2287 var o = this.options;
2288 var method = this.getMethod();
2289 var isPost = method == 'POST';
2290 if(o.clientValidation === false || this.form.isValid()){
2292 if (this.form.progressUrl) {
2293 this.form.findField('UPLOAD_IDENTIFIER').setValue(
2294 (new Date() * 1) + '' + Math.random());
2299 Roo.Ajax.request(Roo.apply(this.createCallback(), {
2300 form:this.form.el.dom,
2301 url:this.getUrl(!isPost),
2303 params:isPost ? this.getParams() : null,
2304 isUpload: this.form.fileUpload
2307 this.uploadProgress();
2309 }else if (o.clientValidation !== false){ // client validation failed
2310 this.failureType = Roo.form.Action.CLIENT_INVALID;
2311 this.form.afterAction(this, false);
2315 success : function(response)
2317 this.uploadComplete= true;
2318 if (this.haveProgress) {
2319 Roo.MessageBox.hide();
2323 var result = this.processResponse(response);
2324 if(result === true || result.success){
2325 this.form.afterAction(this, true);
2329 this.form.markInvalid(result.errors);
2330 this.failureType = Roo.form.Action.SERVER_INVALID;
2332 this.form.afterAction(this, false);
2334 failure : function(response)
2336 this.uploadComplete= true;
2337 if (this.haveProgress) {
2338 Roo.MessageBox.hide();
2341 this.response = response;
2342 this.failureType = Roo.form.Action.CONNECT_FAILURE;
2343 this.form.afterAction(this, false);
2346 handleResponse : function(response){
2347 if(this.form.errorReader){
2348 var rs = this.form.errorReader.read(response);
2351 for(var i = 0, len = rs.records.length; i < len; i++) {
2352 var r = rs.records[i];
2356 if(errors.length < 1){
2360 success : rs.success,
2366 ret = Roo.decode(response.responseText);
2370 errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
2380 Roo.form.Action.Load = function(form, options){
2381 Roo.form.Action.Load.superclass.constructor.call(this, form, options);
2382 this.reader = this.form.reader;
2385 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
2390 Roo.Ajax.request(Roo.apply(
2391 this.createCallback(), {
2392 method:this.getMethod(),
2393 url:this.getUrl(false),
2394 params:this.getParams()
2398 success : function(response){
2400 var result = this.processResponse(response);
2401 if(result === true || !result.success || !result.data){
2402 this.failureType = Roo.form.Action.LOAD_FAILURE;
2403 this.form.afterAction(this, false);
2406 this.form.clearInvalid();
2407 this.form.setValues(result.data);
2408 this.form.afterAction(this, true);
2411 handleResponse : function(response){
2412 if(this.form.reader){
2413 var rs = this.form.reader.read(response);
2414 var data = rs.records && rs.records[0] ? rs.records[0].data : null;
2416 success : rs.success,
2420 return Roo.decode(response.responseText);
2424 Roo.form.Action.ACTION_TYPES = {
2425 'load' : Roo.form.Action.Load,
2426 'submit' : Roo.form.Action.Submit
2435 * @class Roo.bootstrap.Form
2436 * @extends Roo.bootstrap.Component
2437 * Bootstrap Form class
2438 * @cfg {String} method GET | POST (default POST)
2439 * @cfg {String} labelAlign top | left (default top)
2440 * @cfg {String} align left | right - for navbars
2445 * @param {Object} config The config object
2449 Roo.bootstrap.Form = function(config){
2450 Roo.bootstrap.Form.superclass.constructor.call(this, config);
2453 * @event clientvalidation
2454 * If the monitorValid config option is true, this event fires repetitively to notify of valid state
2455 * @param {Form} this
2456 * @param {Boolean} valid true if the form has passed client-side validation
2458 clientvalidation: true,
2460 * @event beforeaction
2461 * Fires before any action is performed. Return false to cancel the action.
2462 * @param {Form} this
2463 * @param {Action} action The action to be performed
2467 * @event actionfailed
2468 * Fires when an action fails.
2469 * @param {Form} this
2470 * @param {Action} action The action that failed
2472 actionfailed : true,
2474 * @event actioncomplete
2475 * Fires when an action is completed.
2476 * @param {Form} this
2477 * @param {Action} action The action that completed
2479 actioncomplete : true
2484 Roo.extend(Roo.bootstrap.Form, Roo.bootstrap.Component, {
2487 * @cfg {String} method
2488 * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
2493 * The URL to use for form actions if one isn't supplied in the action options.
2496 * @cfg {Boolean} fileUpload
2497 * Set to true if this form is a file upload.
2501 * @cfg {Object} baseParams
2502 * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
2506 * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
2510 * @cfg {Sting} align (left|right) for navbar forms
2515 activeAction : null,
2518 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2519 * element by passing it or its id or mask the form itself by passing in true.
2522 waitMsgTarget : false,
2527 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
2528 * element by passing it or its id or mask the form itself by passing in true.
2532 getAutoCreate : function(){
2536 method : this.method || 'POST',
2537 id : this.id || Roo.id(),
2540 if (this.parent().xtype.match(/^Nav/)) {
2541 cfg.cls = 'navbar-form navbar-' + this.align;
2545 if (this.labelAlign == 'left' ) {
2546 cfg.cls += ' form-horizontal';
2552 initEvents : function()
2554 this.el.on('submit', this.onSubmit, this);
2559 onSubmit : function(e){
2564 * Returns true if client-side validation on the form is successful.
2567 isValid : function(){
2568 var items = this.getItems();
2570 items.each(function(f){
2579 * Returns true if any fields in this form have changed since their original load.
2582 isDirty : function(){
2584 var items = this.getItems();
2585 items.each(function(f){
2595 * Performs a predefined action (submit or load) or custom actions you define on this form.
2596 * @param {String} actionName The name of the action type
2597 * @param {Object} options (optional) The options to pass to the action. All of the config options listed
2598 * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
2599 * accept other config options):
2601 Property Type Description
2602 ---------------- --------------- ----------------------------------------------------------------------------------
2603 url String The url for the action (defaults to the form's url)
2604 method String The form method to use (defaults to the form's method, or POST if not defined)
2605 params String/Object The params to pass (defaults to the form's baseParams, or none if not defined)
2606 clientValidation Boolean Applies to submit only. Pass true to call form.isValid() prior to posting to
2607 validate the form on the client (defaults to false)
2609 * @return {BasicForm} this
2611 doAction : function(action, options){
2612 if(typeof action == 'string'){
2613 action = new Roo.form.Action.ACTION_TYPES[action](this, options);
2615 if(this.fireEvent('beforeaction', this, action) !== false){
2616 this.beforeAction(action);
2617 action.run.defer(100, action);
2623 beforeAction : function(action){
2624 var o = action.options;
2626 // not really supported yet.. ??
2628 //if(this.waitMsgTarget === true){
2629 this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
2630 //}else if(this.waitMsgTarget){
2631 // this.waitMsgTarget = Roo.get(this.waitMsgTarget);
2632 // this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
2634 // Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
2640 afterAction : function(action, success){
2641 this.activeAction = null;
2642 var o = action.options;
2644 //if(this.waitMsgTarget === true){
2646 //}else if(this.waitMsgTarget){
2647 // this.waitMsgTarget.unmask();
2649 // Roo.MessageBox.updateProgress(1);
2650 // Roo.MessageBox.hide();
2657 Roo.callback(o.success, o.scope, [this, action]);
2658 this.fireEvent('actioncomplete', this, action);
2662 // failure condition..
2663 // we have a scenario where updates need confirming.
2664 // eg. if a locking scenario exists..
2665 // we look for { errors : { needs_confirm : true }} in the response.
2667 (typeof(action.result) != 'undefined') &&
2668 (typeof(action.result.errors) != 'undefined') &&
2669 (typeof(action.result.errors.needs_confirm) != 'undefined')
2672 Roo.log("not supported yet");
2675 Roo.MessageBox.confirm(
2676 "Change requires confirmation",
2677 action.result.errorMsg,
2682 _t.doAction('submit', { params : { _submit_confirmed : 1 } } );
2692 Roo.callback(o.failure, o.scope, [this, action]);
2693 // show an error message if no failed handler is set..
2694 if (!this.hasListener('actionfailed')) {
2695 Roo.log("need to add dialog support");
2697 Roo.MessageBox.alert("Error",
2698 (typeof(action.result) != 'undefined' && typeof(action.result.errorMsg) != 'undefined') ?
2699 action.result.errorMsg :
2700 "Saving Failed, please check your entries or try again"
2705 this.fireEvent('actionfailed', this, action);
2710 * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
2711 * @param {String} id The value to search for
2714 findField : function(id){
2715 var items = this.getItems();
2716 var field = items.get(id);
2718 items.each(function(f){
2719 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
2726 return field || null;
2729 * Mark fields in this form invalid in bulk.
2730 * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
2731 * @return {BasicForm} this
2733 markInvalid : function(errors){
2734 if(errors instanceof Array){
2735 for(var i = 0, len = errors.length; i < len; i++){
2736 var fieldError = errors[i];
2737 var f = this.findField(fieldError.id);
2739 f.markInvalid(fieldError.msg);
2745 if(typeof errors[id] != 'function' && (field = this.findField(id))){
2746 field.markInvalid(errors[id]);
2750 //Roo.each(this.childForms || [], function (f) {
2751 // f.markInvalid(errors);
2758 * Set values for fields in this form in bulk.
2759 * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
2760 * @return {BasicForm} this
2762 setValues : function(values){
2763 if(values instanceof Array){ // array of objects
2764 for(var i = 0, len = values.length; i < len; i++){
2766 var f = this.findField(v.id);
2768 f.setValue(v.value);
2769 if(this.trackResetOnLoad){
2770 f.originalValue = f.getValue();
2774 }else{ // object hash
2777 if(typeof values[id] != 'function' && (field = this.findField(id))){
2779 if (field.setFromData &&
2781 field.displayField &&
2782 // combos' with local stores can
2783 // be queried via setValue()
2784 // to set their value..
2785 (field.store && !field.store.isLocal)
2789 sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
2790 sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
2791 field.setFromData(sd);
2794 field.setValue(values[id]);
2798 if(this.trackResetOnLoad){
2799 field.originalValue = field.getValue();
2805 //Roo.each(this.childForms || [], function (f) {
2806 // f.setValues(values);
2813 * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
2814 * they are returned as an array.
2815 * @param {Boolean} asString
2818 getValues : function(asString){
2819 //if (this.childForms) {
2820 // copy values from the child forms
2821 // Roo.each(this.childForms, function (f) {
2822 // this.setValues(f.getValues());
2828 var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
2829 if(asString === true){
2832 return Roo.urlDecode(fs);
2836 * Returns the fields in this form as an object with key/value pairs.
2837 * This differs from getValues as it calls getValue on each child item, rather than using dom data.
2840 getFieldValues : function(with_hidden)
2842 var items = this.getItems();
2844 items.each(function(f){
2848 var v = f.getValue();
2849 if (f.inputType =='radio') {
2850 if (typeof(ret[f.getName()]) == 'undefined') {
2851 ret[f.getName()] = ''; // empty..
2854 if (!f.el.dom.checked) {
2862 // not sure if this supported any more..
2863 if ((typeof(v) == 'object') && f.getRawValue) {
2864 v = f.getRawValue() ; // dates..
2866 // combo boxes where name != hiddenName...
2867 if (f.name != f.getName()) {
2868 ret[f.name] = f.getRawValue();
2870 ret[f.getName()] = v;
2877 * Clears all invalid messages in this form.
2878 * @return {BasicForm} this
2880 clearInvalid : function(){
2881 var items = this.getItems();
2883 items.each(function(f){
2894 * @return {BasicForm} this
2897 var items = this.getItems();
2898 items.each(function(f){
2902 Roo.each(this.childForms || [], function (f) {
2909 getItems : function()
2911 var r=new Roo.util.MixedCollection(false, function(o){
2912 return o.id || (o.id = Roo.id());
2914 var iter = function(el) {
2921 Roo.each(el.items,function(e) {
2940 * Ext JS Library 1.1.1
2941 * Copyright(c) 2006-2007, Ext JS, LLC.
2943 * Originally Released Under LGPL - original licence link has changed is not relivant.
2946 * <script type="text/javascript">
2949 * @class Roo.form.VTypes
2950 * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
2953 Roo.form.VTypes = function(){
2954 // closure these in so they are only created once.
2955 var alpha = /^[a-zA-Z_]+$/;
2956 var alphanum = /^[a-zA-Z0-9_]+$/;
2957 var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
2958 var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
2960 // All these messages and functions are configurable
2963 * The function used to validate email addresses
2964 * @param {String} value The email address
2966 'email' : function(v){
2967 return email.test(v);
2970 * The error text to display when the email validation function returns false
2973 'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
2975 * The keystroke filter mask to be applied on email input
2978 'emailMask' : /[a-z0-9_\.\-@]/i,
2981 * The function used to validate URLs
2982 * @param {String} value The URL
2984 'url' : function(v){
2988 * The error text to display when the url validation function returns false
2991 'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
2994 * The function used to validate alpha values
2995 * @param {String} value The value
2997 'alpha' : function(v){
2998 return alpha.test(v);
3001 * The error text to display when the alpha validation function returns false
3004 'alphaText' : 'This field should only contain letters and _',
3006 * The keystroke filter mask to be applied on alpha input
3009 'alphaMask' : /[a-z_]/i,
3012 * The function used to validate alphanumeric values
3013 * @param {String} value The value
3015 'alphanum' : function(v){
3016 return alphanum.test(v);
3019 * The error text to display when the alphanumeric validation function returns false
3022 'alphanumText' : 'This field should only contain letters, numbers and _',
3024 * The keystroke filter mask to be applied on alphanumeric input
3027 'alphanumMask' : /[a-z0-9_]/i
3037 * @class Roo.bootstrap.Input
3038 * @extends Roo.bootstrap.Component
3039 * Bootstrap Input class
3040 * @cfg {Boolean} disabled is it disabled
3041 * @cfg {String} fieldLabel - the label associated
3042 * @cfg {String} inputType button | checkbox | email | file | hidden | image | number | password | radio | range | reset | search | submit | text
3043 * @cfg {String} name name of the input
3044 * @cfg {string} fieldLabel - the label associated
3045 * @cfg {string} inputType - input / file submit ...
3046 * @cfg {string} placeholder - placeholder to put in text.
3047 * @cfg {string} before - input group add on before
3048 * @cfg {string} after - input group add on after
3049 * @cfg {string} size - (lg|sm) or leave empty..
3050 * @cfg {Number} xs colspan out of 12 for mobile-sized screens
3051 * @cfg {Number} sm colspan out of 12 for tablet-sized screens
3052 * @cfg {Number} md colspan out of 12 for computer-sized screens
3053 * @cfg {Number} lg colspan out of 12 for large computer-sized screens
3057 * Create a new Input
3058 * @param {Object} config The config object
3061 Roo.bootstrap.Input = function(config){
3062 Roo.bootstrap.Input.superclass.constructor.call(this, config);
3067 * Fires when this field receives input focus.
3068 * @param {Roo.form.Field} this
3073 * Fires when this field loses input focus.
3074 * @param {Roo.form.Field} this
3079 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
3080 * {@link Roo.EventObject#getKey} to determine which key was pressed.
3081 * @param {Roo.form.Field} this
3082 * @param {Roo.EventObject} e The event object
3087 * Fires just before the field blurs if the field value has changed.
3088 * @param {Roo.form.Field} this
3089 * @param {Mixed} newValue The new value
3090 * @param {Mixed} oldValue The original value
3095 * Fires after the field has been marked as invalid.
3096 * @param {Roo.form.Field} this
3097 * @param {String} msg The validation message
3102 * Fires after the field has been validated with no errors.
3103 * @param {Roo.form.Field} this
3108 * Fires after the key up
3109 * @param {Roo.form.Field} this
3110 * @param {Roo.EventObject} e The event Object
3116 Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component, {
3118 * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
3119 automatic validation (defaults to "keyup").
3121 validationEvent : "keyup",
3123 * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
3125 validateOnBlur : true,
3127 * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
3129 validationDelay : 250,
3131 * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
3133 focusClass : "x-form-focus", // not needed???
3137 * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
3139 invalidClass : "has-error",
3142 * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
3144 selectOnFocus : false,
3147 * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
3151 * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
3156 * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
3158 disableKeyFilter : false,
3161 * @cfg {Boolean} disabled True to disable the field (defaults to false).
3165 * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
3169 * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
3171 blankText : "This field is required",
3174 * @cfg {Number} minLength Minimum input field length required (defaults to 0)
3178 * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
3180 maxLength : Number.MAX_VALUE,
3182 * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
3184 minLengthText : "The minimum length for this field is {0}",
3186 * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
3188 maxLengthText : "The maximum length for this field is {0}",
3192 * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
3193 * If available, this function will be called only after the basic validators all return true, and will be passed the
3194 * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
3198 * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
3199 * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
3200 * current field value. If the test fails, the field will be marked invalid using {@link #regexText}.
3204 * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
3223 getAutoCreate : function(){
3225 var parent = this.parent();
3227 var align = parent.labelAlign;
3232 cls: 'form-group' //input-group
3238 type : this.inputType,
3239 cls : 'form-control',
3240 placeholder : this.placeholder || ''
3244 input.name = this.name;
3247 input.cls += ' input-' + this.size;
3250 ['xs','sm','md','lg'].map(function(size){
3251 if (settings[size]) {
3252 cfg.cls += ' col-' + size + '-' + settings[size];
3256 var inputblock = input;
3258 if (this.before || this.after) {
3261 cls : 'input-group',
3265 inputblock.cn.push({
3267 cls : 'input-group-addon',
3271 inputblock.cn.push(input);
3273 inputblock.cn.push({
3275 cls : 'input-group-addon',
3283 Roo.log(this.fieldLabel.length);
3285 if (align ==='left' && this.fieldLabel.length) {
3286 Roo.log("left and has label");
3292 cls : 'col-sm-2 control-label',
3293 html : this.fieldLabel
3304 } else if ( this.fieldLabel.length) {
3310 //cls : 'input-group-addon',
3311 html : this.fieldLabel
3321 Roo.log(" no label && no align");
3334 if (this.disabled) {
3335 input.disabled=true;
3341 * return the real input element.
3343 inputEl: function ()
3345 return this.el.select('input.form-control',true).first();
3347 setDisabled : function(v)
3349 var i = this.inputEl().dom;
3351 i.removeAttribute('disabled');
3355 i.setAttribute('disabled','true');
3357 initEvents : function()
3360 this.inputEl().on("keydown" , this.fireKey, this);
3361 this.inputEl().on("focus", this.onFocus, this);
3362 this.inputEl().on("blur", this.onBlur, this);
3363 this.inputEl().relayEvent('keyup', this);
3365 // reference to original value for reset
3366 this.originalValue = this.getValue();
3367 //Roo.form.TextField.superclass.initEvents.call(this);
3368 if(this.validationEvent == 'keyup'){
3369 this.validationTask = new Roo.util.DelayedTask(this.validate, this);
3370 this.inputEl().on('keyup', this.filterValidation, this);
3372 else if(this.validationEvent !== false){
3373 this.inputEl().on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
3376 if(this.selectOnFocus){
3377 this.on("focus", this.preFocus, this);
3380 if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
3381 this.inputEl().on("keypress", this.filterKeys, this);
3384 this.el.on("keyup", this.onKeyUp, this, {buffer:50});
3385 this.el.on("click", this.autoSize, this);
3388 if(this.inputEl().is('input[type=password]') && Roo.isSafari){
3389 this.inputEl().on('keydown', this.SafariOnKeyDown, this);
3393 filterValidation : function(e){
3394 if(!e.isNavKeyPress()){
3395 this.validationTask.delay(this.validationDelay);
3399 * Validates the field value
3400 * @return {Boolean} True if the value is valid, else false
3402 validate : function(){
3403 //if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
3404 if(this.disabled || this.validateValue(this.getRawValue())){
3405 this.clearInvalid();
3413 * Validates a value according to the field's validation rules and marks the field as invalid
3414 * if the validation fails
3415 * @param {Mixed} value The value to validate
3416 * @return {Boolean} True if the value is valid, else false
3418 validateValue : function(value){
3419 if(value.length < 1) { // if it's blank
3420 if(this.allowBlank){
3421 this.clearInvalid();
3424 this.markInvalid(this.blankText);
3428 if(value.length < this.minLength){
3429 this.markInvalid(String.format(this.minLengthText, this.minLength));
3432 if(value.length > this.maxLength){
3433 this.markInvalid(String.format(this.maxLengthText, this.maxLength));
3437 var vt = Roo.form.VTypes;
3438 if(!vt[this.vtype](value, this)){
3439 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
3443 if(typeof this.validator == "function"){
3444 var msg = this.validator(value);
3446 this.markInvalid(msg);
3450 if(this.regex && !this.regex.test(value)){
3451 this.markInvalid(this.regexText);
3460 fireKey : function(e){
3461 //Roo.log('field ' + e.getKey());
3462 if(e.isNavKeyPress()){
3463 this.fireEvent("specialkey", this, e);
3466 focus : function (selectText){
3468 this.inputEl().focus();
3469 if(selectText === true){
3470 this.inputEl().dom.select();
3476 onFocus : function(){
3477 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3478 // this.el.addClass(this.focusClass);
3481 this.hasFocus = true;
3482 this.startValue = this.getValue();
3483 this.fireEvent("focus", this);
3487 beforeBlur : Roo.emptyFn,
3491 onBlur : function(){
3493 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
3494 //this.el.removeClass(this.focusClass);
3496 this.hasFocus = false;
3497 if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
3500 var v = this.getValue();
3501 if(String(v) !== String(this.startValue)){
3502 this.fireEvent('change', this, v, this.startValue);
3504 this.fireEvent("blur", this);
3508 * Resets the current field value to the originally loaded value and clears any validation messages
3511 this.setValue(this.originalValue);
3512 this.clearInvalid();
3515 * Returns the name of the field
3516 * @return {Mixed} name The name field
3518 getName: function(){
3522 * Returns the normalized data value (undefined or emptyText will be returned as ''). To return the raw value see {@link #getRawValue}.
3523 * @return {Mixed} value The field value
3525 getValue : function(){
3526 var v = this.inputEl().getValue();
3530 * Returns the raw data value which may or may not be a valid, defined value. To return a normalized value see {@link #getValue}.
3531 * @return {Mixed} value The field value
3533 getRawValue : function(){
3534 var v = this.inputEl().getValue();
3539 * Sets a data value into the field and validates it. To set the value directly without validation see {@link #setRawValue}.
3540 * @param {Mixed} value The value to set
3542 setValue : function(v){
3545 this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
3551 processValue : function(value){
3552 if(this.stripCharsRe){
3553 var newValue = value.replace(this.stripCharsRe, '');
3554 if(newValue !== value){
3555 this.setRawValue(newValue);
3562 preFocus : function(){
3564 if(this.selectOnFocus){
3565 this.inputEl().dom.select();
3568 filterKeys : function(e){
3570 if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
3573 var c = e.getCharCode(), cc = String.fromCharCode(c);
3574 if(Roo.isIE && (e.isSpecialKey() || !cc)){
3577 if(!this.maskRe.test(cc)){
3582 * Clear any invalid styles/messages for this field
3584 clearInvalid : function(){
3586 if(!this.el || this.preventMark){ // not rendered
3589 this.el.removeClass(this.invalidClass);
3591 switch(this.msgTarget){
3593 this.el.dom.qtip = '';
3596 this.el.dom.title = '';
3600 Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
3605 this.errorIcon.dom.qtip = '';
3606 this.errorIcon.hide();
3607 this.un('resize', this.alignErrorIcon, this);
3611 var t = Roo.getDom(this.msgTarget);
3613 t.style.display = 'none';
3617 this.fireEvent('valid', this);
3620 * Mark this field as invalid
3621 * @param {String} msg The validation message
3623 markInvalid : function(msg){
3624 if(!this.el || this.preventMark){ // not rendered
3627 this.el.addClass(this.invalidClass);
3629 msg = msg || this.invalidText;
3630 switch(this.msgTarget){
3632 this.el.dom.qtip = msg;
3633 this.el.dom.qclass = 'x-form-invalid-tip';
3634 if(Roo.QuickTips){ // fix for floating editors interacting with DND
3635 Roo.QuickTips.enable();
3639 this.el.dom.title = msg;
3643 var elp = this.el.findParent('.x-form-element', 5, true);
3644 this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
3645 this.errorEl.setWidth(elp.getWidth(true)-20);
3647 this.errorEl.update(msg);
3648 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
3651 if(!this.errorIcon){
3652 var elp = this.el.findParent('.x-form-element', 5, true);
3653 this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
3655 this.alignErrorIcon();
3656 this.errorIcon.dom.qtip = msg;
3657 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
3658 this.errorIcon.show();
3659 this.on('resize', this.alignErrorIcon, this);
3662 var t = Roo.getDom(this.msgTarget);
3664 t.style.display = this.msgDisplay;
3668 this.fireEvent('invalid', this, msg);
3671 SafariOnKeyDown : function(event)
3673 // this is a workaround for a password hang bug on chrome/ webkit.
3675 var isSelectAll = false;
3677 if(this.inputEl().dom.selectionEnd > 0){
3678 isSelectAll = (this.inputEl().dom.selectionEnd - this.inputEl().dom.selectionStart - this.getValue().length == 0) ? true : false;
3680 if(((event.getKey() == 8 || event.getKey() == 46) && this.getValue().length ==1)){ // backspace and delete key
3681 event.preventDefault();
3686 if(isSelectAll){ // backspace and delete key
3688 event.preventDefault();
3689 // this is very hacky as keydown always get's upper case.
3691 var cc = String.fromCharCode(event.getCharCode());
3692 this.setValue( event.shiftKey ? cc : cc.toLowerCase());
3704 * trigger field - base class for combo..
3709 * @class Roo.bootstrap.TriggerField
3710 * @extends Roo.bootstrap.Input
3711 * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
3712 * The trigger has no default action, so you must assign a function to implement the trigger click handler by
3713 * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox
3714 * for which you can provide a custom implementation. For example:
3716 var trigger = new Roo.bootstrap.TriggerField();
3717 trigger.onTriggerClick = myTriggerFn;
3718 trigger.applyTo('my-field');
3721 * However, in general you will most likely want to use TriggerField as the base class for a reusable component.
3722 * {@link Roo.bootstrap.DateField} and {@link Roo.bootstrap.ComboBox} are perfect examples of this.
3723 * @cfg {String} triggerClass An additional CSS class used to style the trigger button. The trigger will always get the
3724 * class 'x-form-trigger' by default and triggerClass will be <b>appended</b> if specified.
3726 * Create a new TriggerField.
3727 * @param {Object} config Configuration options (valid {@Roo.bootstrap.Input} config options will also be applied
3728 * to the base TextField)
3730 Roo.bootstrap.TriggerField = function(config){
3731 this.mimicing = false;
3732 Roo.bootstrap.TriggerField.superclass.constructor.call(this, config);
3735 Roo.extend(Roo.bootstrap.TriggerField, Roo.bootstrap.Input, {
3737 * @cfg {String} triggerClass A CSS class to apply to the trigger
3740 * @cfg {Boolean} hideTrigger True to hide the trigger element and display only the base text field (defaults to false)
3744 /** @cfg {Boolean} grow @hide */
3745 /** @cfg {Number} growMin @hide */
3746 /** @cfg {Number} growMax @hide */
3752 autoSize: Roo.emptyFn,
3759 actionMode : 'wrap',
3763 getAutoCreate : function(){
3765 var parent = this.parent();
3767 var align = parent.labelAlign;
3772 cls: 'form-group' //input-group
3779 type : this.inputType,
3780 cls : 'form-control',
3781 autocomplete: 'off',
3782 placeholder : this.placeholder || ''
3786 input.name = this.name;
3789 input.cls += ' input-' + this.size;
3792 cls: 'combobox-container input-group',
3797 cls: 'form-hidden-field'
3802 cls : 'typeahead typeahead-long dropdown-menu',
3803 style : 'display:none'
3807 cls : 'input-group-addon btn dropdown-toggle',
3815 cls: 'combobox-clear',
3832 if (align ==='left' && this.fieldLabel.length) {
3836 Roo.log("left and has label");
3842 cls : 'col-sm-2 control-label',
3843 html : this.fieldLabel
3854 } else if ( this.fieldLabel.length) {
3860 //cls : 'input-group-addon',
3861 html : this.fieldLabel
3871 Roo.log(" no label && no align");
3878 ['xs','sm','md','lg'].map(function(size){
3879 if (settings[size]) {
3880 cfg.cls += ' col-' + size + '-' + settings[size];
3886 if (this.disabled) {
3887 input.disabled=true;
3896 onResize : function(w, h){
3897 Roo.boostrap.TriggerField.superclass.onResize.apply(this, arguments);
3898 if(typeof w == 'number'){
3899 var x = w - this.trigger.getWidth();
3900 this.inputEl().setWidth(this.adjustWidth('input', x));
3901 this.trigger.setStyle('left', x+'px');
3906 adjustSize : Roo.BoxComponent.prototype.adjustSize,
3909 getResizeEl : function(){
3910 return this.inputEl();
3914 getPositionEl : function(){
3915 return this.inputEl();
3919 alignErrorIcon : function(){
3920 this.errorIcon.alignTo(this.inputEl(), 'tl-tr', [2, 0]);
3924 initEvents : function(){
3926 //this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
3928 this.trigger = this.el.select('span.dropdown-toggle',true).first();
3929 if(this.hideTrigger){
3930 this.trigger.setDisplayed(false);
3932 this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});
3933 //this.trigger.addClassOnOver('x-form-trigger-over');
3934 //this.trigger.addClassOnClick('x-form-trigger-click');
3937 // this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
3942 initTrigger : function(){
3947 onDestroy : function(){
3949 this.trigger.removeAllListeners();
3950 // this.trigger.remove();
3953 // this.wrap.remove();
3955 Roo.bootstrap.TriggerField.superclass.onDestroy.call(this);
3959 onFocus : function(){
3960 Roo.bootstrap.TriggerField.superclass.onFocus.call(this);
3963 this.wrap.addClass('x-trigger-wrap-focus');
3964 this.mimicing = true;
3965 Roo.get(Roo.isIE ? document.body : document).on("mousedown", this.mimicBlur, this);
3966 if(this.monitorTab){
3967 this.el.on("keydown", this.checkTab, this);
3974 checkTab : function(e){
3975 if(e.getKey() == e.TAB){
3981 onBlur : function(){
3986 mimicBlur : function(e, t){
3988 if(!this.wrap.contains(t) && this.validateBlur()){
3995 triggerBlur : function(){
3996 this.mimicing = false;
3997 Roo.get(Roo.isIE ? document.body : document).un("mousedown", this.mimicBlur);
3998 if(this.monitorTab){
3999 this.el.un("keydown", this.checkTab, this);
4001 //this.wrap.removeClass('x-trigger-wrap-focus');
4002 Roo.bootstrap.TriggerField.superclass.onBlur.call(this);
4006 // This should be overriden by any subclass that needs to check whether or not the field can be blurred.
4007 validateBlur : function(e, t){
4012 onDisable : function(){
4013 Roo.bootstrap.TriggerField.superclass.onDisable.call(this);
4015 // this.wrap.addClass('x-item-disabled');
4020 onEnable : function(){
4021 Roo.bootstrap.TriggerField.superclass.onEnable.call(this);
4023 // this.el.removeClass('x-item-disabled');
4028 onShow : function(){
4029 var ae = this.getActionEl();
4032 ae.dom.style.display = '';
4033 ae.dom.style.visibility = 'visible';
4039 onHide : function(){
4040 var ae = this.getActionEl();
4041 ae.dom.style.display = 'none';
4045 * The function that should handle the trigger's click event. This method does nothing by default until overridden
4046 * by an implementing function.
4048 * @param {EventObject} e
4050 onTriggerClick : Roo.emptyFn
4058 * @class Roo.bootstrap.ComboBox
4059 * @extends Roo.bootstrap.TriggerField
4060 * A combobox control with support for autocomplete, remote-loading, paging and many other features.
4062 * Create a new ComboBox.
4063 * @param {Object} config Configuration options
4065 Roo.bootstrap.ComboBox = function(config){
4066 Roo.bootstrap.ComboBox.superclass.constructor.call(this, config);
4070 * Fires when the dropdown list is expanded
4071 * @param {Roo.bootstrap.ComboBox} combo This combo box
4076 * Fires when the dropdown list is collapsed
4077 * @param {Roo.bootstrap.ComboBox} combo This combo box
4081 * @event beforeselect
4082 * Fires before a list item is selected. Return false to cancel the selection.
4083 * @param {Roo.bootstrap.ComboBox} combo This combo box
4084 * @param {Roo.data.Record} record The data record returned from the underlying store
4085 * @param {Number} index The index of the selected item in the dropdown list
4087 'beforeselect' : true,
4090 * Fires when a list item is selected
4091 * @param {Roo.bootstrap.ComboBox} combo This combo box
4092 * @param {Roo.data.Record} record The data record returned from the underlying store (or false on clear)
4093 * @param {Number} index The index of the selected item in the dropdown list
4097 * @event beforequery
4098 * Fires before all queries are processed. Return false to cancel the query or set cancel to true.
4099 * The event object passed has these properties:
4100 * @param {Roo.bootstrap.ComboBox} combo This combo box
4101 * @param {String} query The query
4102 * @param {Boolean} forceAll true to force "all" query
4103 * @param {Boolean} cancel true to cancel the query
4104 * @param {Object} e The query event object
4106 'beforequery': true,
4109 * Fires when the 'add' icon is pressed (add a listener to enable add button)
4110 * @param {Roo.bootstrap.ComboBox} combo This combo box
4115 * Fires when the 'edit' icon is pressed (add a listener to enable add button)
4116 * @param {Roo.bootstrap.ComboBox} combo This combo box
4117 * @param {Roo.data.Record|false} record The data record returned from the underlying store (or false on nothing selected)
4125 throw "can not find store for combo";
4127 this.store = Roo.factory(this.store, Roo.data);
4130 this.selectedIndex = -1;
4131 if(this.mode == 'local'){
4132 if(config.queryDelay === undefined){
4133 this.queryDelay = 10;
4135 if(config.minChars === undefined){
4141 Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
4144 * @cfg {Boolean} lazyRender True to prevent the ComboBox from rendering until requested (should always be used when
4145 * rendering into an Roo.Editor, defaults to false)
4148 * @cfg {Boolean/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to:
4149 * {tag: "input", type: "text", size: "24", autocomplete: "off"})
4152 * @cfg {Roo.data.Store} store The data store to which this combo is bound (defaults to undefined)
4155 * @cfg {String} title If supplied, a header element is created containing this text and added into the top of
4156 * the dropdown list (defaults to undefined, with no header element)
4160 * @cfg {String/Roo.Template} tpl The template to use to render the output
4164 * @cfg {Number} listWidth The width in pixels of the dropdown list (defaults to the width of the ComboBox field)
4166 listWidth: undefined,
4168 * @cfg {String} displayField The underlying data field name to bind to this CombBox (defaults to undefined if
4169 * mode = 'remote' or 'text' if mode = 'local')
4171 displayField: undefined,
4173 * @cfg {String} valueField The underlying data value name to bind to this CombBox (defaults to undefined if
4174 * mode = 'remote' or 'value' if mode = 'local').
4175 * Note: use of a valueField requires the user make a selection
4176 * in order for a value to be mapped.
4178 valueField: undefined,
4182 * @cfg {String} hiddenName If specified, a hidden form field with this name is dynamically generated to store the
4183 * field's data value (defaults to the underlying DOM element's name)
4185 hiddenName: undefined,
4187 * @cfg {String} listClass CSS class to apply to the dropdown list element (defaults to '')
4191 * @cfg {String} selectedClass CSS class to apply to the selected item in the dropdown list (defaults to 'x-combo-selected')
4193 selectedClass: 'active',
4196 * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop" for bottom-right
4200 * @cfg {String} listAlign A valid anchor position value. See {@link Roo.Element#alignTo} for details on supported
4201 * anchor positions (defaults to 'tl-bl')
4203 listAlign: 'tl-bl?',
4205 * @cfg {Number} maxHeight The maximum height in pixels of the dropdown list before scrollbars are shown (defaults to 300)
4209 * @cfg {String} triggerAction The action to execute when the trigger field is activated. Use 'all' to run the
4210 * query specified by the allQuery config option (defaults to 'query')
4212 triggerAction: 'query',
4214 * @cfg {Number} minChars The minimum number of characters the user must type before autocomplete and typeahead activate
4215 * (defaults to 4, does not apply if editable = false)
4219 * @cfg {Boolean} typeAhead True to populate and autoselect the remainder of the text being typed after a configurable
4220 * delay (typeAheadDelay) if it matches a known value (defaults to false)
4224 * @cfg {Number} queryDelay The length of time in milliseconds to delay between the start of typing and sending the
4225 * query to filter the dropdown list (defaults to 500 if mode = 'remote' or 10 if mode = 'local')
4229 * @cfg {Number} pageSize If greater than 0, a paging toolbar is displayed in the footer of the dropdown list and the
4230 * filter queries will execute with page start and limit parameters. Only applies when mode = 'remote' (defaults to 0)
4234 * @cfg {Boolean} selectOnFocus True to select any existing text in the field immediately on focus. Only applies
4235 * when editable = true (defaults to false)
4237 selectOnFocus:false,
4239 * @cfg {String} queryParam Name of the query as it will be passed on the querystring (defaults to 'query')
4241 queryParam: 'query',
4243 * @cfg {String} loadingText The text to display in the dropdown list while data is loading. Only applies
4244 * when mode = 'remote' (defaults to 'Loading...')
4246 loadingText: 'Loading...',
4248 * @cfg {Boolean} resizable True to add a resize handle to the bottom of the dropdown list (defaults to false)
4252 * @cfg {Number} handleHeight The height in pixels of the dropdown list resize handle if resizable = true (defaults to 8)
4256 * @cfg {Boolean} editable False to prevent the user from typing text directly into the field, just like a
4257 * traditional select (defaults to true)
4261 * @cfg {String} allQuery The text query to send to the server to return all records for the list with no filtering (defaults to '')
4265 * @cfg {String} mode Set to 'local' if the ComboBox loads local data (defaults to 'remote' which loads from the server)
4269 * @cfg {Number} minListWidth The minimum width of the dropdown list in pixels (defaults to 70, will be ignored if
4270 * listWidth has a higher value)
4274 * @cfg {Boolean} forceSelection True to restrict the selected value to one of the values in the list, false to
4275 * allow the user to set arbitrary text into the field (defaults to false)
4277 forceSelection:false,
4279 * @cfg {Number} typeAheadDelay The length of time in milliseconds to wait until the typeahead text is displayed
4280 * if typeAhead = true (defaults to 250)
4282 typeAheadDelay : 250,
4284 * @cfg {String} valueNotFoundText When using a name/value combo, if the value passed to setValue is not found in
4285 * the store, valueNotFoundText will be displayed as the field text if defined (defaults to undefined)
4287 valueNotFoundText : undefined,
4289 * @cfg {Boolean} blockFocus Prevents all focus calls, so it can work with things like HTML edtor bar
4294 * @cfg {Boolean} disableClear Disable showing of clear button.
4296 disableClear : false,
4298 * @cfg {Boolean} alwaysQuery Disable caching of results, and always send query
4300 alwaysQuery : false,
4306 // element that contains real text value.. (when hidden is used..)
4309 initEvents: function(){
4310 Roo.bootstrap.ComboBox.superclass.initEvents.call(this);
4313 if(this.hiddenName){
4315 this.hiddenField = this.el.select('input.form-hidden-field',true).first();
4317 this.hiddenField.dom.value =
4318 this.hiddenValue !== undefined ? this.hiddenValue :
4319 this.value !== undefined ? this.value : '';
4321 // prevent input submission
4322 this.el.dom.removeAttribute('name');
4323 this.hiddenField.dom.setAttribute('name', this.hiddenName);
4328 // this.el.dom.setAttribute('autocomplete', 'off');
4331 var cls = 'x-combo-list';
4332 this.list = this.el.select('ul',true).first();
4334 //this.list = new Roo.Layer({
4335 // shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
4338 var lw = this.listWidth || Math.max(this.inputEl().getWidth(), this.minListWidth);
4339 this.list.setWidth(lw);
4341 this.list.swallowEvent('mousewheel');
4342 this.assetHeight = 0;
4345 this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
4346 this.assetHeight += this.header.getHeight();
4349 this.innerList = this.list.createChild({cls:cls+'-inner'});
4350 this.innerList.on('mouseover', this.onViewOver, this);
4351 this.innerList.on('mousemove', this.onViewMove, this);
4352 this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
4354 if(this.allowBlank && !this.pageSize && !this.disableClear){
4355 this.footer = this.list.createChild({cls:cls+'-ft'});
4356 this.pageTb = new Roo.Toolbar(this.footer);
4360 this.footer = this.list.createChild({cls:cls+'-ft'});
4361 this.pageTb = new Roo.PagingToolbar(this.footer, this.store,
4362 {pageSize: this.pageSize});
4366 if (this.pageTb && this.allowBlank && !this.disableClear) {
4368 this.pageTb.add(new Roo.Toolbar.Fill(), {
4369 cls: 'x-btn-icon x-btn-clear',
4375 _this.onSelect(false, -1);
4380 this.assetHeight += this.footer.getHeight();
4385 this.tpl = '<li><a href="#">{' + this.displayField + '}</a></li>';
4388 this.view = new Roo.View(this.el.select('ul',true).first(), this.tpl, {
4389 singleSelect:true, store: this.store, selectedClass: this.selectedClass
4391 //this.view.wrapEl.setDisplayed(false);
4392 this.view.on('click', this.onViewClick, this);
4396 this.store.on('beforeload', this.onBeforeLoad, this);
4397 this.store.on('load', this.onLoad, this);
4398 this.store.on('loadexception', this.onLoadException, this);
4401 this.resizer = new Roo.Resizable(this.list, {
4402 pinned:true, handles:'se'
4404 this.resizer.on('resize', function(r, w, h){
4405 this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
4407 this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
4408 this.restrictHeight();
4410 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
4414 this.editable = true;
4415 this.setEditable(false);
4420 if (typeof(this.events.add.listeners) != 'undefined') {
4422 this.addicon = this.wrap.createChild(
4423 {tag: 'img', src: Roo.BLANK_IMAGE_URL, cls: 'x-form-combo-add' });
4425 this.addicon.on('click', function(e) {
4426 this.fireEvent('add', this);
4429 if (typeof(this.events.edit.listeners) != 'undefined') {
4431 this.editicon = this.wrap.createChild(
4432 {tag: 'img', src: Roo.BLANK_IMAGE_URL, cls: 'x-form-combo-edit' });
4434 this.editicon.setStyle('margin-left', '40px');
4436 this.editicon.on('click', function(e) {
4438 // we fire even if inothing is selected..
4439 this.fireEvent('edit', this, this.lastData );
4446 this.keyNav = new Roo.KeyNav(this.inputEl(), {
4448 this.inKeyMode = true;
4452 "down" : function(e){
4453 if(!this.isExpanded()){
4454 this.onTriggerClick();
4456 this.inKeyMode = true;
4461 "enter" : function(e){
4466 "esc" : function(e){
4470 "tab" : function(e){
4471 this.onViewClick(false);
4472 this.fireEvent("specialkey", this, e);
4478 doRelay : function(foo, bar, hname){
4479 if(hname == 'down' || this.scope.isExpanded()){
4480 return Roo.KeyNav.prototype.doRelay.apply(this, arguments);
4489 this.queryDelay = Math.max(this.queryDelay || 10,
4490 this.mode == 'local' ? 10 : 250);
4493 this.dqTask = new Roo.util.DelayedTask(this.initQuery, this);
4496 this.taTask = new Roo.util.DelayedTask(this.onTypeAhead, this);
4498 if(this.editable !== false){
4499 this.inputEl().on("keyup", this.onKeyUp, this);
4501 if(this.forceSelection){
4502 this.on('blur', this.doForce, this);
4506 onDestroy : function(){
4508 this.view.setStore(null);
4509 this.view.el.removeAllListeners();
4510 this.view.el.remove();
4511 this.view.purgeListeners();
4514 this.list.dom.innerHTML = '';
4517 this.store.un('beforeload', this.onBeforeLoad, this);
4518 this.store.un('load', this.onLoad, this);
4519 this.store.un('loadexception', this.onLoadException, this);
4521 Roo.bootstrap.ComboBox.superclass.onDestroy.call(this);
4525 fireKey : function(e){
4526 if(e.isNavKeyPress() && !this.list.isVisible()){
4527 this.fireEvent("specialkey", this, e);
4532 onResize: function(w, h){
4533 Roo.bootstrap.ComboBox.superclass.onResize.apply(this, arguments);
4535 if(typeof w != 'number'){
4536 // we do not handle it!?!?
4539 var tw = this.trigger.getWidth();
4540 // tw += this.addicon ? this.addicon.getWidth() : 0;
4541 // tw += this.editicon ? this.editicon.getWidth() : 0;
4543 this.inputEl().setWidth( this.adjustWidth('input', x));
4545 //this.trigger.setStyle('left', x+'px');
4547 if(this.list && this.listWidth === undefined){
4548 var lw = Math.max(x + this.trigger.getWidth(), this.minListWidth);
4549 this.list.setWidth(lw);
4550 this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
4558 * Allow or prevent the user from directly editing the field text. If false is passed,
4559 * the user will only be able to select from the items defined in the dropdown list. This method
4560 * is the runtime equivalent of setting the 'editable' config option at config time.
4561 * @param {Boolean} value True to allow the user to directly edit the field text
4563 setEditable : function(value){
4564 if(value == this.editable){
4567 this.editable = value;
4569 this.inputEl().dom.setAttribute('readOnly', true);
4570 this.inputEl().on('mousedown', this.onTriggerClick, this);
4571 this.inputEl().addClass('x-combo-noedit');
4573 this.inputEl().dom.setAttribute('readOnly', false);
4574 this.inputEl().un('mousedown', this.onTriggerClick, this);
4575 this.inputEl().removeClass('x-combo-noedit');
4580 onBeforeLoad : function(){
4584 //this.innerList.update(this.loadingText ?
4585 // '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
4586 this.list.dom.innerHTML = '<li class="loading-indicator">'+(this.loadingText||'loading')+'</li>' ;
4588 this.restrictHeight();
4589 this.selectedIndex = -1;
4593 onLoad : function(){
4597 if(this.store.getCount() > 0){
4599 this.restrictHeight();
4600 if(this.lastQuery == this.allQuery){
4602 this.inputEl().dom.select();
4604 if(!this.selectByValue(this.value, true)){
4605 this.select(0, true);
4609 if(this.typeAhead && this.lastKey != Roo.EventObject.BACKSPACE && this.lastKey != Roo.EventObject.DELETE){
4610 this.taTask.delay(this.typeAheadDelay);
4614 this.onEmptyResults();
4619 onLoadException : function()
4622 Roo.log(this.store.reader.jsonData);
4623 if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
4625 //Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
4631 onTypeAhead : function(){
4632 if(this.store.getCount() > 0){
4633 var r = this.store.getAt(0);
4634 var newValue = r.data[this.displayField];
4635 var len = newValue.length;
4636 var selStart = this.getRawValue().length;
4637 if(selStart != len){
4638 this.setRawValue(newValue);
4639 this.selectText(selStart, newValue.length);
4645 onSelect : function(record, index){
4646 if(this.fireEvent('beforeselect', this, record, index) !== false){
4647 this.setFromData(index > -1 ? record.data : false);
4649 this.fireEvent('select', this, record, index);
4654 * Returns the currently selected field value or empty string if no value is set.
4655 * @return {String} value The selected value
4657 getValue : function(){
4658 if(this.valueField){
4659 return typeof this.value != 'undefined' ? this.value : '';
4661 return Roo.bootstrap.ComboBox.superclass.getValue.call(this);
4666 * Clears any text/value currently set in the field
4668 clearValue : function(){
4669 if(this.hiddenField){
4670 this.hiddenField.dom.value = '';
4673 this.setRawValue('');
4674 this.lastSelectionText = '';
4679 * Sets the specified value into the field. If the value finds a match, the corresponding record text
4680 * will be displayed in the field. If the value does not match the data value of an existing item,
4681 * and the valueNotFoundText config option is defined, it will be displayed as the default field text.
4682 * Otherwise the field will be blank (although the value will still be set).
4683 * @param {String} value The value to match
4685 setValue : function(v){
4687 if(this.valueField){
4688 var r = this.findRecord(this.valueField, v);
4690 text = r.data[this.displayField];
4691 }else if(this.valueNotFoundText !== undefined){
4692 text = this.valueNotFoundText;
4695 this.lastSelectionText = text;
4696 if(this.hiddenField){
4697 this.hiddenField.dom.value = v;
4699 Roo.bootstrap.ComboBox.superclass.setValue.call(this, text);
4703 * @property {Object} the last set data for the element
4708 * Sets the value of the field based on a object which is related to the record format for the store.
4709 * @param {Object} value the value to set as. or false on reset?
4711 setFromData : function(o){
4712 var dv = ''; // display value
4713 var vv = ''; // value value..
4715 if (this.displayField) {
4716 dv = !o || typeof(o[this.displayField]) == 'undefined' ? '' : o[this.displayField];
4718 // this is an error condition!!!
4719 Roo.log('no displayField value set for '+ (this.name ? this.name : this.id));
4722 if(this.valueField){
4723 vv = !o || typeof(o[this.valueField]) == 'undefined' ? dv : o[this.valueField];
4725 if(this.hiddenField){
4726 this.hiddenField.dom.value = vv;
4728 this.lastSelectionText = dv;
4729 Roo.bootstrap.ComboBox.superclass.setValue.call(this, dv);
4733 // no hidden field.. - we store the value in 'value', but still display
4734 // display field!!!!
4735 this.lastSelectionText = dv;
4736 Roo.bootstrap.ComboBox.superclass.setValue.call(this, dv);
4743 // overridden so that last data is reset..
4744 this.setValue(this.originalValue);
4745 this.clearInvalid();
4746 this.lastData = false;
4748 this.view.clearSelections();
4752 findRecord : function(prop, value){
4754 if(this.store.getCount() > 0){
4755 this.store.each(function(r){
4756 if(r.data[prop] == value){
4768 // returns hidden if it's set..
4769 if (!this.rendered) {return ''};
4770 return !this.hiddenName && this.inputEl().dom.name ? this.inputEl().dom.name : (this.hiddenName || '');
4774 onViewMove : function(e, t){
4775 this.inKeyMode = false;
4779 onViewOver : function(e, t){
4780 if(this.inKeyMode){ // prevent key nav and mouse over conflicts
4783 var item = this.view.findItemFromChild(t);
4785 var index = this.view.indexOf(item);
4786 this.select(index, false);
4791 onViewClick : function(doFocus)
4793 var index = this.view.getSelectedIndexes()[0];
4794 var r = this.store.getAt(index);
4796 this.onSelect(r, index);
4798 if(doFocus !== false && !this.blockFocus){
4799 this.inputEl().focus();
4804 restrictHeight : function(){
4805 //this.innerList.dom.style.height = '';
4806 //var inner = this.innerList.dom;
4807 //var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
4808 //this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
4809 //this.list.beginUpdate();
4810 //this.list.setHeight(this.innerList.getHeight()+this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight);
4811 this.list.alignTo(this.inputEl(), this.listAlign);
4812 //this.list.endUpdate();
4816 onEmptyResults : function(){
4821 * Returns true if the dropdown list is expanded, else false.
4823 isExpanded : function(){
4824 return this.list.isVisible();
4828 * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.
4829 * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
4830 * @param {String} value The data value of the item to select
4831 * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
4832 * selected item if it is not currently in view (defaults to true)
4833 * @return {Boolean} True if the value matched an item in the list, else false
4835 selectByValue : function(v, scrollIntoView){
4836 if(v !== undefined && v !== null){
4837 var r = this.findRecord(this.valueField || this.displayField, v);
4839 this.select(this.store.indexOf(r), scrollIntoView);
4847 * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire.
4848 * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
4849 * @param {Number} index The zero-based index of the list item to select
4850 * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
4851 * selected item if it is not currently in view (defaults to true)
4853 select : function(index, scrollIntoView){
4854 this.selectedIndex = index;
4855 this.view.select(index);
4856 if(scrollIntoView !== false){
4857 var el = this.view.getNode(index);
4859 //this.innerList.scrollChildIntoView(el, false);
4866 selectNext : function(){
4867 var ct = this.store.getCount();
4869 if(this.selectedIndex == -1){
4871 }else if(this.selectedIndex < ct-1){
4872 this.select(this.selectedIndex+1);
4878 selectPrev : function(){
4879 var ct = this.store.getCount();
4881 if(this.selectedIndex == -1){
4883 }else if(this.selectedIndex != 0){
4884 this.select(this.selectedIndex-1);
4890 onKeyUp : function(e){
4891 if(this.editable !== false && !e.isSpecialKey()){
4892 this.lastKey = e.getKey();
4893 this.dqTask.delay(this.queryDelay);
4898 validateBlur : function(){
4899 return !this.list || !this.list.isVisible();
4903 initQuery : function(){
4904 this.doQuery(this.getRawValue());
4908 doForce : function(){
4909 if(this.el.dom.value.length > 0){
4911 this.lastSelectionText === undefined ? '' : this.lastSelectionText;
4917 * Execute a query to filter the dropdown list. Fires the beforequery event prior to performing the
4918 * query allowing the query action to be canceled if needed.
4919 * @param {String} query The SQL query to execute
4920 * @param {Boolean} forceAll True to force the query to execute even if there are currently fewer characters
4921 * in the field than the minimum specified by the minChars config option. It also clears any filter previously
4922 * saved in the current store (defaults to false)
4924 doQuery : function(q, forceAll){
4925 if(q === undefined || q === null){
4934 if(this.fireEvent('beforequery', qe)===false || qe.cancel){
4938 forceAll = qe.forceAll;
4939 if(forceAll === true || (q.length >= this.minChars)){
4940 if(this.lastQuery != q || this.alwaysQuery){
4942 if(this.mode == 'local'){
4943 this.selectedIndex = -1;
4945 this.store.clearFilter();
4947 this.store.filter(this.displayField, q);
4951 this.store.baseParams[this.queryParam] = q;
4953 params: this.getParams(q)
4958 this.selectedIndex = -1;
4965 getParams : function(q){
4967 //p[this.queryParam] = q;
4970 p.limit = this.pageSize;
4976 * Hides the dropdown list if it is currently expanded. Fires the 'collapse' event on completion.
4978 collapse : function(){
4979 if(!this.isExpanded()){
4983 Roo.get(document).un('mousedown', this.collapseIf, this);
4984 Roo.get(document).un('mousewheel', this.collapseIf, this);
4985 if (!this.editable) {
4986 Roo.get(document).un('keydown', this.listKeyPress, this);
4988 this.fireEvent('collapse', this);
4992 collapseIf : function(e){
4993 if(!e.within(this.el) && !e.within(this.el)){
4999 * Expands the dropdown list if it is currently hidden. Fires the 'expand' event on completion.
5001 expand : function(){
5003 if(this.isExpanded() || !this.hasFocus){
5006 this.list.alignTo(this.inputEl(), this.listAlign);
5008 Roo.get(document).on('mousedown', this.collapseIf, this);
5009 Roo.get(document).on('mousewheel', this.collapseIf, this);
5010 if (!this.editable) {
5011 Roo.get(document).on('keydown', this.listKeyPress, this);
5014 this.fireEvent('expand', this);
5018 // Implements the default empty TriggerField.onTriggerClick function
5019 onTriggerClick : function()
5021 Roo.log('trigger click');
5026 if(this.isExpanded()){
5028 if (!this.blockFocus) {
5029 this.inputEl().focus();
5033 this.hasFocus = true;
5034 if(this.triggerAction == 'all') {
5035 this.doQuery(this.allQuery, true);
5037 this.doQuery(this.getRawValue());
5039 if (!this.blockFocus) {
5040 this.inputEl().focus();
5044 listKeyPress : function(e)
5046 //Roo.log('listkeypress');
5047 // scroll to first matching element based on key pres..
5048 if (e.isSpecialKey()) {
5051 var k = String.fromCharCode(e.getKey()).toUpperCase();
5054 var csel = this.view.getSelectedNodes();
5055 var cselitem = false;
5057 var ix = this.view.indexOf(csel[0]);
5058 cselitem = this.store.getAt(ix);
5059 if (!cselitem.get(this.displayField) || cselitem.get(this.displayField).substring(0,1).toUpperCase() != k) {
5065 this.store.each(function(v) {
5067 // start at existing selection.
5068 if (cselitem.id == v.id) {
5074 if (v.get(this.displayField) && v.get(this.displayField).substring(0,1).toUpperCase() == k) {
5075 match = this.store.indexOf(v);
5081 if (match === false) {
5082 return true; // no more action?
5085 this.view.select(match);
5086 var sn = Roo.get(this.view.getSelectedNodes()[0])
5087 //sn.scrollIntoView(sn.dom.parentNode, false);
5091 * @cfg {Boolean} grow
5095 * @cfg {Number} growMin
5099 * @cfg {Number} growMax