`
langgufu
  • 浏览: 2306932 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Ext 多选下拉 MultiComBox

阅读更多

下面介绍MultiComboBox的使用方式,大家先看看下面的代码:

Java代码
  1. Ext.onReady(function(){
  2. var formPanel = new Ext.FormPanel({
  3. height : 100,// 表单面板的高度
  4. width : 400,// 表单面板的宽度
  5. labelWidth : 120,// 字段标签宽度
  6. labelAlign : "right",// 字段标签对齐方式
  7. fileUpload: true,//支持文件上传
  8. defaults : {// 默认form元素类型为textfield
  9. xtype : "textfield",// 默认类型为textfield
  10. width : 150 // 默认宽度
  11. },
  12. items : [{
  13. xtype:'multicombo',
  14. width:250,
  15. store: new Ext.data.SimpleStore({
  16. fields: ["name","value"],
  17. data:[['测试菜单1',1],['测试菜单2',2],['测试菜单3',3],['测试菜单4',4]]}),
  18. valueField :"value",
  19. displayField: "name",
  20. labelSeparator:':',
  21. displaySeparator:';',
  22. valueSeparator:',',
  23. mode: 'local',
  24. value:'1,2',
  25. forceSelection: true,
  26. hiddenName:'test',
  27. editable: true,
  28. triggerAction: 'all',
  29. allowBlank:false,
  30. emptyText:'请选择',
  31. fieldLabel: '多选下拉ComBo'
  32. }],
  33. buttons : [{
  34. text : '提交',
  35. type : 'submit',
  36. handler : function() {
  37. }
  38. }]
  39. });
  40. formPanel.render("multicombo-div");
  41. });
  1. <span class="hilite1">Ext</span>
  2. .onReady(function(){
  3. var formPanel = new <span class="hilite1">Ext</span>
  4. .FormPanel({
  5. height : 100,// 表单面板的高度
  6. width : 400,// 表单面板的宽度
  7. labelWidth : 120,// 字段标签宽度
  8. labelAlign : "right",// 字段标签对齐方式
  9. fileUpload: true,//支持文件上传
  10. defaults : {// 默认form元素类型为textfield
  11. xtype : "textfield",// 默认类型为textfield
  12. width : 150 // 默认宽度
  13. },
  14. items : [{
  15. xtype:'multicombo',
  16. width:250,
  17. store: new <span class="hilite1">Ext</span>
  18. .data.SimpleStore({
  19. fields: ["name","value"],
  20. data:[['测试菜单1',1],['测试菜单2',2],['测试菜单3',3],['测试菜单4',4]]}),
  21. valueField :"value",
  22. displayField: "name",
  23. labelSeparator:':',
  24. displaySeparator:';',
  25. valueSeparator:',',
  26. mode: 'local',
  27. value:'1,2',
  28. forceSelection: true,
  29. hiddenName:'test',
  30. editable: true,
  31. triggerAction: 'all',
  32. allowBlank:false,
  33. emptyText:'请选择',
  34. fieldLabel: '多选下拉ComBo'
  35. }],
  36. buttons : [{
  37. text : '提交',
  38. type : 'submit',
  39. handler : function() {
  40. }
  41. }]
  42. });
  43. formPanel.render("multicombo-div");
  44. });
Ext
.onReady(function(){
   	  	  var formPanel = new Ext
.FormPanel({
			height : 100,// 表单面板的高度
			width : 400,// 表单面板的宽度
			labelWidth : 120,// 字段标签宽度
			labelAlign : "right",// 字段标签对齐方式
			fileUpload: true,//支持文件上传
			defaults : {// 默认form元素类型为textfield
				xtype : "textfield",// 默认类型为textfield
				width : 150 // 默认宽度
			},
			items : [{
			   xtype:'multicombo',
			   width:250,
			   store: new Ext
.data.SimpleStore({
			       fields: ["name","value"],
			       data:[['测试菜单1',1],['测试菜单2',2],['测试菜单3',3],['测试菜单4',4]]}),
			   valueField :"value",
			   displayField: "name",
			   labelSeparator:':',
			   displaySeparator:';',
			   valueSeparator:',',
			   mode: 'local',
			   value:'1,2',
			   forceSelection: true,
			   hiddenName:'test',
			   editable: true,
			   triggerAction: 'all',
			   allowBlank:false,
			   emptyText:'请选择',
			   fieldLabel: '多选下拉ComBo'
			}],		
			buttons : [{
				text : '提交',
				type : 'submit',
				handler : function() {
					
				}
			}]
		});
		formPanel.render("multicombo-div");
});



由上面代码可以看到用法大致和ComboBox一样,不相同的地方是:

Java代码
  1. xtype:'multicombo',//MultiComboBox注册类型名称
  2. displaySeparator:';',//多选显示分隔字符
  3. valueSeparator:',',//多选提交到后台的值分隔符
  4. value:'1,2',// 多值通过","分隔,与valueSeparator相对应,表示默认选择了"测试菜单1'"和"测试菜单2"
  1. xtype:'multicombo',//MultiComboBox注册类型名称
  2. displaySeparator:';',//多选显示分隔字符
  3. valueSeparator:',',//多选提交到后台的值分隔符
  4. value:'1,2',// 多值通过","分隔,与valueSeparator相对应,表示默认选择了"测试菜单1'"和"测试菜单2"
xtype:'multicombo',//MultiComboBox注册类型名称
displaySeparator:';',//多选显示分隔字符
valueSeparator:',',//多选提交到后台的值分隔符
value:'1,2',//  多值通过","分隔,与valueSeparator相对应,表示默认选择了"测试菜单1'"和"测试菜单2"



由于添加了多选CheckBox图标,所以需要在ext-all.css文件最后添加两行支持样式:

Java代码
  1. .checked{background-image:url(../images/default/menu/checked.gif)}
  2. .unchecked{background-image:url(../images/default/menu/unchecked.gif)}
  1. .checked{background-image:url(../images/default/menu/checked.gif)}
  2. .unchecked{background-image:url(../images/default/menu/unchecked.gif)}
.checked{background-image:url(../images/default/menu/checked.gif)}
.unchecked{background-image:url(../images/default/menu/unchecked.gif)}



MultiComboBox的源代码:

Java代码
  1. Ext.form.MultiComboBox = Ext.extend(Ext.form.TriggerField, {
  2. defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
  3. listClass: '',
  4. selectedClass: 'x-combo-selected',
  5. triggerClass : 'x-form-arrow-trigger',
  6. shadow:'sides',
  7. listAlign: 'tl-bl?',
  8. maxHeight: 300,
  9. triggerAction: 'query',
  10. minChars : 4,
  11. typeAhead: false,
  12. queryDelay: 500,
  13. pageSize: 0,
  14. selectOnFocus:false,
  15. queryParam: 'query',
  16. loadingText: 'Loading...',
  17. resizable: false,
  18. handleHeight : 8,
  19. editable: true,
  20. allQuery: '',
  21. mode: 'remote',
  22. minListWidth : 70,
  23. forceSelection:false,
  24. typeAheadDelay : 250,
  25. displaySeparator:';',
  26. valueSeparator:',',
  27. lazyInit : true,
  28. initComponent : function(){
  29. Ext.form.ComboBox.superclass.initComponent.call(this);
  30. this.addEvents(
  31. 'expand',
  32. 'collapse',
  33. 'beforeselect',
  34. 'select',
  35. 'beforequery'
  36. );
  37. if(this.transform){
  38. this.allowDomMove = false;
  39. var s = Ext.getDom(this.transform);
  40. if(!this.hiddenName){
  41. this.hiddenName = s.name;
  42. }
  43. if(!this.store){
  44. this.mode = 'local';
  45. var d = [], opts = s.options;
  46. for(var i = 0, len = opts.length;i < len; i++){
  47. var o = opts[i];
  48. var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;
  49. if(o.selected) {
  50. this.value = value;
  51. }
  52. d.push([value, o.text]);
  53. }
  54. this.store = new Ext.data.SimpleStore({
  55. 'id': 0,
  56. fields: ['value', 'text'],
  57. data : d
  58. });
  59. this.valueField = 'value';
  60. this.displayField = 'text';
  61. }
  62. s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference
  63. if(!this.lazyRender){
  64. this.target = true;
  65. this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
  66. Ext.removeNode(s); // remove it
  67. this.render(this.el.parentNode);
  68. }else{
  69. Ext.removeNode(s); // remove it
  70. }
  71. }
  72. this.selectedIndex = -1;
  73. if(this.mode == 'local'){
  74. if(this.initialConfig.queryDelay === undefined){
  75. this.queryDelay = 10;
  76. }
  77. if(this.initialConfig.minChars === undefined){
  78. this.minChars = 0;
  79. }
  80. }
  81. },
  82. // private
  83. onRender : function(ct, position){
  84. Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
  85. var disValue="";
  86. if(this.hiddenName){
  87. this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
  88. 'before', true);
  89. var hvalue=this.hiddenValue !== undefined ? this.hiddenValue :
  90. this.value !== undefined ? this.value : '';
  91. var hvalueArray=hvalue.split(this.valueSeparator);
  92. for(var i=0;i<this.store.data.length;i++){
  93. var r = this.store.getAt(i);
  94. var newValue = r.data[this.displayField];
  95. var v=r.data[this.valueField];
  96. for(var j=0;j<hvalueArray.length;j++){
  97. if(hvalueArray[j]==v){
  98. disValue+=newValue+this.displaySeparator;
  99. }
  100. }
  101. }
  102. this.hiddenField.value =this.hiddenValue !== undefined ? this.hiddenValue :
  103. this.value !== undefined ? this.value : '';
  104. this.el.dom.removeAttribute('name');
  105. }
  106. if(Ext.isGecko){
  107. this.el.dom.setAttribute('autocomplete', 'off');
  108. }
  109. if(!this.lazyInit){
  110. this.initList();
  111. }else{
  112. this.on('focus', this.initList, this, {single: true});
  113. }
  114. if(!this.editable){
  115. this.editable = true;
  116. this.setEditable(false);
  117. }
  118. this.setValue(disValue);
  119. },
  120. initList : function(){
  121. if(!this.list){
  122. var cls = 'x-combo-list';
  123. this.list = new Ext.Layer({
  124. shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
  125. });
  126. var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
  127. this.list.setWidth(lw);
  128. this.list.swallowEvent('mousewheel');
  129. this.assetHeight = 0;
  130. if(this.title){
  131. this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
  132. this.assetHeight += this.header.getHeight();
  133. }
  134. this.innerList = this.list.createChild({cls:cls+'-inner'});
  135. this.innerList.on('mouseover', this.onViewOver, this);
  136. this.innerList.on('mousemove', this.onViewMove, this);
  137. this.innerList.setWidth(lw - this.list.getFrameWidth('lr'))
  138. if(this.pageSize){
  139. this.footer = this.list.createChild({cls:cls+'-ft'});
  140. this.pageTb = new Ext.PagingToolbar({
  141. store:this.store,
  142. pageSize: this.pageSize,
  143. renderTo:this.footer
  144. });
  145. this.assetHeight += this.footer.getHeight();
  146. }
  147. if(!this.tpl){
  148. //alert(cls);
  149. //x-combo-list-item
  150. this.tpl = '<tpl for="."><div class="'+cls+'-item"><span class="unchecked" id="checkBox_{' + this.displayField + '}"+ width="20">&nbsp;&nbsp;&nbsp;&nbsp;</span>{' + this.displayField + '}</div></tpl>';
  151. }
  152. this.view = new Ext.DataView({
  153. applyTo: this.innerList,
  154. tpl: this.tpl,
  155. singleSelect: true,
  156. selectedClass: this.selectedClass,
  157. itemSelector: this.itemSelector || '.' + cls + '-item'
  158. });
  159. this.view.on('click', this.onViewClick, this);
  160. this.bindStore(this.store, true);
  161. if(this.resizable){
  162. this.resizer = new Ext.Resizable(this.list, {
  163. pinned:true, handles:'se'
  164. });
  165. this.resizer.on('resize', function(r, w, h){
  166. this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
  167. this.listWidth = w;
  168. this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
  169. this.restrictHeight();
  170. }, this);
  171. this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
  172. }
  173. }
  174. },
  175. bindStore : function(store, initial){
  176. if(this.store && !initial){
  177. this.store.un('beforeload', this.onBeforeLoad, this);
  178. this.store.un('load', this.onLoad, this);
  179. this.store.un('loadexception', this.collapse, this);
  180. if(!store){
  181. this.store = null;
  182. if(this.view){
  183. this.view.setStore(null);
  184. }
  185. }
  186. }
  187. if(store){
  188. this.store = Ext.StoreMgr.lookup(store);
  189. this.store.on('beforeload', this.onBeforeLoad, this);
  190. this.store.on('load', this.onLoad, this);
  191. this.store.on('loadexception', this.collapse, this);
  192. if(this.view){
  193. this.view.setStore(store);
  194. }
  195. }
  196. },
  197. // private
  198. initEvents : function(){
  199. Ext.form.ComboBox.superclass.initEvents.call(this);
  200. this.keyNav = new Ext.KeyNav(this.el, {
  201. "up" : function(e){
  202. this.inKeyMode = true;
  203. this.selectPrev();
  204. },
  205. "down" : function(e){
  206. if(!this.isExpanded()){
  207. this.onTriggerClick();
  208. }else{
  209. this.inKeyMode = true;
  210. this.selectNext();
  211. }
  212. },
  213. "enter" : function(e){
  214. this.onViewClick();
  215. //return true;
  216. },
  217. "esc" : function(e){
  218. this.collapse();
  219. },
  220. "tab" : function(e){
  221. this.onViewClick(false);
  222. return true;
  223. },
  224. scope : this,
  225. doRelay : function(foo, bar, hname){
  226. if(hname == 'down' || this.scope.isExpanded()){
  227. return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
  228. }
  229. return true;
  230. },
  231. forceKeyDown : true
  232. });
  233. this.queryDelay = Math.max(this.queryDelay || 10,
  234. this.mode == 'local' ? 10 : 250);
  235. this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
  236. if(this.typeAhead){
  237. this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
  238. }
  239. if(this.editable !== false){
  240. this.el.on("keyup", this.onKeyUp, this);
  241. }
  242. if(this.forceSelection){
  243. this.on('blur', this.doForce, this);
  244. }
  245. },
  246. onDestroy : function(){
  247. if(this.view){
  248. this.view.el.removeAllListeners();
  249. this.view.el.remove();
  250. this.view.purgeListeners();
  251. }
  252. if(this.list){
  253. this.list.destroy();
  254. }
  255. this.bindStore(null);
  256. Ext.form.ComboBox.superclass.onDestroy.call(this);
  257. },
  258. // private
  259. fireKey : function(e){
  260. if(e.isNavKeyPress() && !this.list.isVisible()){
  261. this.fireEvent("specialkey", this, e);
  262. }
  263. },
  264. // private
  265. onResize: function(w, h){
  266. Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
  267. if(this.list && this.listWidth === undefined){
  268. var lw = Math.max(w, this.minListWidth);
  269. this.list.setWidth(lw);
  270. this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
  271. }
  272. },
  273. // private
  274. onDisable: function(){
  275. Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
  276. if(this.hiddenField){
  277. this.hiddenField.disabled = this.disabled;
  278. }
  279. },
  280. setEditable : function(value){
  281. if(value == this.editable){
  282. return;
  283. }
  284. this.editable = value;
  285. if(!value){
  286. this.el.dom.setAttribute('readOnly', true);
  287. this.el.on('mousedown', this.onTriggerClick, this);
  288. this.el.addClass('x-combo-noedit');
  289. }else{
  290. this.el.dom.setAttribute('readOnly', false);
  291. this.el.un('mousedown', this.onTriggerClick, this);
  292. this.el.removeClass('x-combo-noedit');
  293. }
  294. },
  295. // private
  296. onBeforeLoad : function(){
  297. if(!this.hasFocus){
  298. return;
  299. }
  300. this.innerList.update(this.loadingText ?
  301. '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
  302. this.restrictHeight();
  303. this.selectedIndex = -1;
  304. },
  305. // private
  306. onLoad : function(){
  307. if(!this.hasFocus){
  308. return;
  309. }
  310. if(this.store.getCount() > 0){
  311. this.expand();
  312. this.restrictHeight();
  313. if(this.lastQuery == this.allQuery){
  314. if(this.editable){
  315. this.el.dom.select();
  316. }
  317. if(!this.selectByValue(this.value, true)){
  318. this.select(0, true);
  319. }
  320. }else{
  321. this.selectNext();
  322. if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
  323. this.taTask.delay(this.typeAheadDelay);
  324. }
  325. }
  326. }else{
  327. this.onEmptyResults();
  328. }
  329. },
  330. // private
  331. onTypeAhead : function(){
  332. if(this.store.getCount() > 0){
  333. var r = this.store.getAt(0);
  334. var newValue = r.data[this.displayField];
  335. var len = newValue.length;
  336. var selStart = this.getRawValue().length;
  337. if(selStart != len){
  338. this.setRawValue(newValue);
  339. this.selectText(selStart, newValue.length);
  340. }
  341. }
  342. },
  343. // private
  344. onSelect : function(record, index){
  345. if(this.fireEvent('beforeselect', this, record, index) !== false){
  346. var r = this.store.getAt(index);
  347. var newValue = r.data[this.displayField];
  348. var check=document.getElementById("checkBox_"+newValue);
  349. if(check.className=="checked"){
  350. check.className="unchecked"
  351. }else{
  352. check.className="checked"
  353. }
  354. var value="";
  355. var hiddenValue="";
  356. for(var i=0;i<this.store.data.length;i++){
  357. var r = this.store.getAt(i);
  358. newValue = r.data[this.displayField];
  359. check=document.getElementById("checkBox_"+newValue);
  360. if(check.className=="checked"){
  361. value+= r.data[this.displayField]+this.displaySeparator;
  362. hiddenValue+= r.data[this.valueField]+this.valueSeparator;
  363. }
  364. }
  365. if(value.length>1){
  366. value=value.substring(0,value.length-this.displaySeparator.length);
  367. }
  368. if(hiddenValue.length>1){
  369. hiddenValue=hiddenValue.substring(0,value.length-this.valueSeparator.length);
  370. }
  371. this.setValue(value);
  372. this.hiddenField.value=hiddenValue;
  373. this.fireEvent('select', this, record, index);
  374. }
  375. },
  376. getValue : function(){
  377. if(this.valueField){
  378. return typeof this.value != 'undefined' ? this.value : '';
  379. }else{
  380. return Ext.form.ComboBox.superclass.getValue.call(this);
  381. }
  382. },
  383. /**
  384. * Clears any text/value currently set in the field
  385. */
  386. clearValue : function(){
  387. if(this.hiddenField){
  388. this.hiddenField.value = '';
  389. }
  390. this.setRawValue('');
  391. this.lastSelectionText = '';
  392. this.applyEmptyText();
  393. },
  394. setValue : function(v){
  395. var text = v;
  396. if(this.valueField){
  397. var r = this.findRecord(this.valueField, v);
  398. if(r){
  399. text = r.data[this.displayField];
  400. }else if(this.valueNotFoundText !== undefined){
  401. text = this.valueNotFoundText;
  402. }
  403. }
  404. this.lastSelectionText = text;
  405. Ext.form.ComboBox.superclass.setValue.call(this, text);
  406. this.value = v;
  407. },
  408. // private
  409. findRecord : function(prop, value){
  410. var record;
  411. if(this.store.getCount() > 0){
  412. this.store.each(function(r){
  413. if(r.data[prop] == value){
  414. record = r;
  415. return false;
  416. }
  417. });
  418. }
  419. return record;
  420. },
  421. // private
  422. onViewMove : function(e, t){
  423. this.inKeyMode = false;
  424. },
  425. // private
  426. onViewOver : function(e, t){
  427. if(this.inKeyMode){ // prevent key nav and mouse over conflicts
  428. return;
  429. }
  430. var item = this.view.findItemFromChild(t);
  431. if(item){
  432. var index = this.view.indexOf(item);
  433. this.select(index, false);
  434. }
  435. },
  436. // private
  437. onViewClick : function(doFocus){
  438. var index = this.view.getSelectedIndexes()[0];
  439. var r = this.store.getAt(index);
  440. if(r){
  441. this.onSelect(r, index);
  442. }
  443. if(doFocus !== false){
  444. this.el.focus();
  445. }
  446. },
  447. // private
  448. restrictHeight : function(){
  449. this.innerList.dom.style.height = '';
  450. var inner = this.innerList.dom;
  451. var fw = this.list.getFrameWidth('tb');
  452. var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
  453. this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
  454. this.list.beginUpdate();
  455. this.list.setHeight(this.innerList.getHeight()+fw+(this.resizable?this.handleHeight:0)+this.assetHeight);
  456. this.list.alignTo(this.el, this.listAlign);
  457. this.list.endUpdate();
  458. },
  459. // private
  460. onEmptyResults : function(){
  461. this.collapse();
  462. },
  463. /**
  464. * Returns true if the dropdown list is expanded, else false.
  465. */
  466. isExpanded : function(){
  467. return this.list && this.list.isVisible();
  468. },
  469. selectByValue : function(v, scrollIntoView){
  470. if(v !== undefined && v !== null){
  471. var r = this.findRecord(this.valueField || this.displayField, v);
  472. if(r){
  473. this.select(this.store.indexOf(r), scrollIntoView);
  474. return true;
  475. }
  476. }
  477. return false;
  478. },
  479. select : function(index, scrollIntoView){
  480. this.selectedIndex = index;
  481. this.view.select(index);
  482. if(scrollIntoView !== false){
  483. var el = this.view.getNode(index);
  484. if(el){
  485. this.innerList.scrollChildIntoView(el, false);
  486. }
  487. }
  488. },
  489. // private
  490. selectNext : function(){
  491. var ct = this.store.getCount();
  492. if(ct > 0){
  493. if(this.selectedIndex == -1){
  494. this.select(0);
  495. }else if(this.selectedIndex < ct-1){
  496. this.select(this.selectedIndex+1);
  497. }
  498. }
  499. },
  500. // private
  501. selectPrev : function(){
  502. var ct = this.store.getCount();
  503. if(ct > 0){
  504. if(this.selectedIndex == -1){
  505. this.select(0);
  506. }else if(this.selectedIndex != 0){
  507. this.select(this.selectedIndex-1);
  508. }
  509. }
  510. },
  511. // private
  512. onKeyUp : function(e){
  513. if(this.editable !== false && !e.isSpecialKey()){
  514. this.lastKey = e.getKey();
  515. this.dqTask.delay(this.queryDelay);
  516. }
  517. },
  518. // private
  519. validateBlur : function(){
  520. return !this.list || !this.list.isVisible();
  521. },
  522. // private
  523. initQuery : function(){
  524. this.doQuery(this.getRawValue());
  525. },
  526. // private
  527. doForce : function(){
  528. if(this.el.dom.value.length > 0){
  529. this.el.dom.value =
  530. this.lastSelectionText === undefined ? '' : this.lastSelectionText;
  531. this.applyEmptyText();
  532. }
  533. },
  534. doQuery : function(q, forceAll){
  535. if(q === undefined || q === null){
  536. q = '';
  537. }
  538. var qe = {
  539. query: q,
  540. forceAll: forceAll,
  541. combo: this,
  542. cancel:false
  543. };
  544. if(this.fireEvent('beforequery', qe)===false || qe.cancel){
  545. return false;
  546. }
  547. q = qe.query;
  548. forceAll = qe.forceAll;
  549. if(forceAll === true || (q.length >= this.minChars)){
  550. if(this.lastQuery !== q){
  551. this.lastQuery = q;
  552. if(this.mode == 'local'){
  553. this.selectedIndex = -1;
  554. if(forceAll){
  555. this.store.clearFilter();
  556. }else{
  557. this.store.filter(this.displayField, q);
  558. }
  559. this.onLoad();
  560. }else{
  561. this.store.baseParams[this.queryParam] = q;
  562. this.store.load({
  563. params: this.getParams(q)
  564. });
  565. this.expand();
  566. }
  567. }else{
  568. this.selectedIndex = -1;
  569. this.onLoad();
  570. }
  571. }
  572. },
  573. // private
  574. getParams : function(q){
  575. var p = {};
  576. //p[this.queryParam] = q;
  577. if(this.pageSize){
  578. p.start = 0;
  579. p.limit = this.pageSize;
  580. }
  581. return p;
  582. },
  583. /**
  584. * Hides the dropdown list if it is currently expanded. Fires the 'collapse' event on completion.
  585. */
  586. collapse : function(){
  587. if(!this.isExpanded()){
  588. return;
  589. }
  590. this.list.hide();
  591. Ext.getDoc().un('mousewheel', this.collapseIf, this);
  592. Ext.getDoc().un('mousedown', this.collapseIf, this);
  593. this.fireEvent('collapse', this);
  594. },
  595. // private
  596. collapseIf : function(e){
  597. if(!e.within(this.wrap) && !e.within(this.list)){
  598. this.collapse();
  599. }
  600. },
  601. /**
  602. * Expands the dropdown list if it is currently hidden. Fires the 'expand' event on completion.
  603. */
  604. expand : function(){
  605. if(this.isExpanded() || !this.hasFocus){
  606. return;
  607. }
  608. this.list.alignTo(this.wrap, this.listAlign);
  609. var hvalueArray=this.hiddenField.value.split(this.valueSeparator);
  610. for(var i=0;i<this.store.data.length;i++){
  611. var r = this.store.getAt(i);
  612. var newValue = r.data[this.displayField];
  613. var v=r.data[this.valueField];
  614. for(var j=0;j<hvalueArray.length;j++){
  615. if(hvalueArray[j]==v){
  616. document.getElementById("checkBox_"+newValue).className="checked";
  617. }
  618. }
  619. }
  620. this.list.show();
  621. Ext.getDoc().on('mousewheel', this.collapseIf, this);
  622. Ext.getDoc().on('mousedown', this.collapseIf, this);
  623. this.fireEvent('expand', this);
  624. },
  625. // private
  626. // Implements the default empty TriggerField.onTriggerClick function
  627. onTriggerClick : function(){
  628. if(this.disabled){
  629. return;
  630. }
  631. if(this.isExpanded()){
  632. this.collapse();
  633. this.el.focus();
  634. }else {
  635. this.onFocus({});
  636. if(this.triggerAction == 'all') {
  637. this.doQuery(this.allQuery, true);
  638. } else {
  639. this.doQuery(this.getRawValue());
  640. }
  641. this.el.focus();
  642. }
  643. }
  644. });
  645. Ext.reg('multicombo', Ext.form.MultiComboBox);
  1. <span class="hilite1">Ext</span>
  2. .form.MultiComboBox = <span class="hilite1">Ext</span>
  3. .extend(<span class="hilite1">Ext</span>
  4. .form.TriggerField, {
  5. defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
  6. listClass: '',
  7. selectedClass: 'x-combo-selected',
  8. triggerClass : 'x-form-arrow-trigger',
  9. shadow:'sides',
  10. listAlign: 'tl-bl?',
  11. maxHeight: 300,
  12. triggerAction: 'query',
  13. minChars : 4,
  14. typeAhead: false,
  15. queryDelay: 500,
  16. pageSize: 0,
  17. selectOnFocus:false,
  18. queryParam: 'query',
  19. loadingText: 'Loading...',
  20. resizable: false,
  21. handleHeight : 8,
  22. editable: true,
  23. allQuery: '',
  24. mode: 'remote',
  25. minListWidth : 70,
  26. forceSelection:false,
  27. typeAheadDelay : 250,
  28. displaySeparator:';',
  29. valueSeparator:',',
  30. lazyInit : true,
  31. initComponent : function(){
  32. <span class="hilite1">Ext</span>
  33. .form.ComboBox.superclass.initComponent.call(this);
  34. this.addEvents(
  35. 'expand',
  36. 'collapse',
  37. 'beforeselect',
  38. 'select',
  39. 'beforequery'
  40. );
  41. if(this.transform){
  42. this.allowDomMove = false;
  43. var s = <span class="hilite1">Ext</span>
  44. .getDom(this.transform);
  45. if(!this.hiddenName){
  46. this.hiddenName = s.name;
  47. }
  48. if(!this.store){
  49. this.mode = 'local';
  50. var d = [], opts = s.options;
  51. for(var i = 0, len = opts.length;i < len; i++){
  52. var o = opts[i];
  53. var value = (<span class="hilite1">Ext</span>
  54. .isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;
  55. if(o.selected) {
  56. this.value = value;
  57. }
  58. d.push([value, o.text]);
  59. }
  60. this.store = new <span class="hilite1">Ext</span>
  61. .data.SimpleStore({
  62. 'id': 0,
  63. fields: ['value', 'text'],
  64. data : d
  65. });
  66. this.valueField = 'value';
  67. this.displayField = 'text';
  68. }
  69. s.name = <span class="hilite1">Ext</span>
  70. .id(); // wipe out the name in case somewhere else they have a reference
  71. if(!this.lazyRender){
  72. this.target = true;
  73. this.el = <span class="hilite1">Ext</span>
  74. .DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
  75. <span class="hilite1">Ext</span>
  76. .removeNode(s); // remove it
  77. this.render(this.el.parentNode);
  78. }else{
  79. <span class="hilite1">Ext</span>
  80. .removeNode(s); // remove it
  81. }
  82. }
  83. this.selectedIndex = -1;
  84. if(this.mode == 'local'){
  85. if(this.initialConfig.queryDelay === undefined){
  86. this.queryDelay = 10;
  87. }
  88. if(this.initialConfig.minChars === undefined){
  89. this.minChars = 0;
  90. }
  91. }
  92. },
  93. // private
  94. onRender : function(ct, position){
  95. <span class="hilite1">Ext</span>
  96. .form.ComboBox.superclass.onRender.call(this, ct, position);
  97. var disValue="";
  98. if(this.hiddenName){
  99. this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
  100. 'before', true);
  101. var hvalue=this.hiddenValue !== undefined ? this.hiddenValue :
  102. this.value !== undefined ? this.value : '';
  103. var hvalueArray=hvalue.split(this.valueSeparator);
  104. for(var i=0;i<this.store.data.length;i++){
  105. var r = this.store.getAt(i);
  106. var newValue = r.data[this.displayField];
  107. var v=r.data[this.valueField];
  108. for(var j=0;j<hvalueArray.length;j++){
  109. if(hvalueArray[j]==v){
  110. disValue+=newValue+this.displaySeparator;
  111. }
  112. }
  113. }
  114. this.hiddenField.value =this.hiddenValue !== undefined ? this.hiddenValue :
  115. this.value !== undefined ? this.value : '';
  116. this.el.dom.removeAttribute('name');
  117. }
  118. if(<span class="hilite1">Ext</span>
  119. .isGecko){
  120. this.el.dom.setAttribute('autocomplete', 'off');
  121. }
  122. if(!this.lazyInit){
  123. this.initList();
  124. }else{
  125. this.on('focus', this.initList, this, {single: true});
  126. }
  127. if(!this.editable){
  128. this.editable = true;
  129. this.setEditable(false);
  130. }
  131. this.setValue(disValue);
  132. },
  133. initList : function(){
  134. if(!this.list){
  135. var cls = 'x-combo-list';
  136. this.list = new <span class="hilite1">Ext</span>
  137. .Layer({
  138. shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
  139. });
  140. var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
  141. this.list.setWidth(lw);
  142. this.list.swallowEvent('mousewheel');
  143. this.assetHeight = 0;
  144. if(this.title){
  145. this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
  146. this.assetHeight += this.header.getHeight();
  147. }
  148. this.innerList = this.list.createChild({cls:cls+'-inner'});
  149. this.innerList.on('mouseover', this.onViewOver, this);
  150. this.innerList.on('mousemove', this.onViewMove, this);
  151. this.innerList.setWidth(lw - this.list.getFrameWidth('lr'))
  152. if(this.pageSize){
  153. this.footer = this.list.createChild({cls:cls+'-ft'});
  154. this.pageTb = new <span class="hilite1">Ext</span>
  155. .PagingToolbar({
  156. store:this.store,
  157. pageSize: this.pageSize,
  158. renderTo:this.footer
  159. });
  160. this.assetHeight += this.footer.getHeight();
  161. }
  162. if(!this.tpl){
  163. //alert(cls);
  164. //x-combo-list-item
  165. this.tpl = '<tpl for="."><div class="'+cls+'-item"><span class="unchecked" id="checkBox_{' + this.displayField + '}"+ width="20">&nbsp;&nbsp;&nbsp;&nbsp;</span>{' + this.displayField + '}</div></tpl>';
  166. }
  167. this.view = new <span class="hilite1">Ext</span>
  168. .DataView({
  169. applyTo: this.innerList,
  170. tpl: this.tpl,
  171. singleSelect: true,
  172. selectedClass: this.selectedClass,
  173. itemSelector: this.itemSelector || '.' + cls + '-item'
  174. });
  175. this.view.on('click', this.onViewClick, this);
  176. this.bindStore(this.store, true);
  177. if(this.resizable){
  178. this.resizer = new <span class="hilite1">Ext</span>
  179. .Resizable(this.list, {
  180. pinned:true, handles:'se'
  181. });
  182. this.resizer.on('resize', function(r, w, h){
  183. this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
  184. this.listWidth = w;
  185. this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
  186. this.restrictHeight();
  187. }, this);
  188. this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
  189. }
  190. }
  191. },
  192. bindStore : function(store, initial){
  193. if(this.store && !initial){
  194. this.store.un('beforeload', this.onBeforeLoad, this);
  195. this.store.un('load', this.onLoad, this);
  196. this.store.un('loadexception', this.collapse, this);
  197. if(!store){
  198. this.store = null;
  199. if(this.view){
  200. this.view.setStore(null);
  201. }
  202. }
  203. }
  204. if(store){
  205. this.store = <span class="hilite1">Ext</span>
  206. .StoreMgr.lookup(store);
  207. this.store.on('beforeload', this.onBeforeLoad, this);
  208. this.store.on('load', this.onLoad, this);
  209. this.store.on('loadexception', this.collapse, this);
  210. if(this.view){
  211. this.view.setStore(store);
  212. }
  213. }
  214. },
  215. // private
  216. initEvents : function(){
  217. <span class="hilite1">Ext</span>
  218. .form.ComboBox.superclass.initEvents.call(this);
  219. this.keyNav = new <span class="hilite1">Ext</span>
  220. .KeyNav(this.el, {
  221. "up" : function(e){
  222. this.inKeyMode = true;
  223. this.selectPrev();
  224. },
  225. "down" : function(e){
  226. if(!this.isExpanded()){
  227. this.onTriggerClick();
  228. }else{
  229. this.inKeyMode = true;
  230. this.selectNext();
  231. }
  232. },
  233. "enter" : function(e){
  234. this.onViewClick();
  235. //return true;
  236. },
  237. "esc" : function(e){
  238. this.collapse();
  239. },
  240. "tab" : function(e){
  241. this.onViewClick(false);
  242. return true;
  243. },
  244. scope : this,
  245. doRelay : function(foo, bar, hname){
  246. if(hname == 'down' || this.scope.isExpanded()){
  247. return <span class="hilite1">Ext</span>
  248. .KeyNav.prototype.doRelay.apply(this, arguments);
  249. }
  250. return true;
  251. },
  252. forceKeyDown : true
  253. });
  254. this.queryDelay = Math.max(this.queryDelay || 10,
  255. this.mode == 'local' ? 10 : 250);
  256. this.dqTask = new <span class="hilite1">Ext</span>
  257. .util.DelayedTask(this.initQuery, this);
  258. if(this.typeAhead){
  259. this.taTask = new <span class="hilite1">Ext</span>
  260. .util.DelayedTask(this.onTypeAhead, this);
  261. }
  262. if(this.editable !== false){
  263. this.el.on("keyup", this.onKeyUp, this);
  264. }
  265. if(this.forceSelection){
  266. this.on('blur', this.doForce, this);
  267. }
  268. },
  269. onDestroy : function(){
  270. if(this.view){
  271. this.view.el.removeAllListeners();
  272. this.view.el.remove();
  273. this.view.purgeListeners();
  274. }
  275. if(this.list){
  276. this.list.destroy();
  277. }
  278. this.bindStore(null);
  279. <span class="hilite1">Ext</span>
  280. .form.ComboBox.superclass.onDestroy.call(this);
  281. },
  282. // private
  283. fireKey : function(e){
  284. if(e.isNavKeyPress() && !this.list.isVisible()){
  285. this.fireEvent("specialkey", this, e);
  286. }
  287. },
  288. // private
  289. onResize: function(w, h){
  290. <span class="hilite1">Ext</span>
  291. .form.ComboBox.superclass.onResize.apply(this, arguments);
  292. if(this.list && this.listWidth === undefined){
  293. var lw = Math.max(w, this.minListWidth);
  294. this.list.setWidth(lw);
  295. this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
  296. }
  297. },
  298. // private
  299. onDisable: function(){
  300. <span class="hilite1">Ext</span>
  301. .form.ComboBox.superclass.onDisable.apply(this, arguments);
  302. if(this.hiddenField){
  303. this.hiddenField.disabled = this.disabled;
  304. }
  305. },
  306. setEditable : function(value){
  307. if(value == this.editable){
  308. return;
  309. }
  310. this.editable = value;
  311. if(!value){
  312. this.el.dom.setAttribute('readOnly', true);
  313. this.el.on('mousedown', this.onTriggerClick, this);
  314. this.el.addClass('x-combo-noedit');
  315. }else{
  316. this.el.dom.setAttribute('readOnly', false);
  317. this.el.un('mousedown', this.onTriggerClick, this);
  318. this.el.removeClass('x-combo-noedit');
  319. }
  320. },
  321. // private
  322. onBeforeLoad : function(){
  323. if(!this.hasFocus){
  324. return;
  325. }
  326. this.innerList.update(this.loadingText ?
  327. '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
  328. this.restrictHeight();
  329. this.selectedIndex = -1;
  330. },
  331. // private
  332. onLoad : function(){
  333. if(!this.hasFocus){
  334. return;
  335. }
  336. if(this.store.getCount() > 0){
  337. this.expand();
  338. this.restrictHeight();
  339. if(this.lastQuery == this.allQuery){
  340. if(this.editable){
  341. this.el.dom.select();
  342. }
  343. if(!this.selectByValue(this.value, true)){
  344. this.select(0, true);
  345. }
  346. }else{
  347. this.selectNext();
  348. if(this.typeAhead && this.lastKey != <span class="hilite1">Ext</span>
  349. .EventObject.BACKSPACE && this.lastKey != <span class="hilite1">Ext</span>
  350. .EventObject.DELETE){
  351. this.taTask.delay(this.typeAheadDelay);
  352. }
  353. }
  354. }else{
  355. this.onEmptyResults();
  356. }
  357. },
  358. // private
  359. onTypeAhead : function(){
  360. if(this.store.getCount() > 0){
  361. var r = this.store.getAt(0);
  362. var newValue = r.data[this.displayField];
  363. var len = newValue.length;
  364. var selStart = this.getRawValue().length;
  365. if(selStart != len){
  366. this.setRawValue(newValue);
  367. this.selectText(selStart, newValue.length);
  368. }
  369. }
  370. },
  371. // private
  372. onSelect : function(record, index){
  373. if(this.fireEvent('beforeselect', this, record, index) !== false){
  374. var r = this.store.getAt(index);
  375. var newValue = r.data[this.displayField];
  376. var check=document.getElementById("checkBox_"+newValue);
  377. if(check.className=="checked"){
  378. check.className="unchecked"
  379. }else{
  380. check.className="checked"
  381. }
  382. var value="";
  383. var hiddenValue="";
  384. for(var i=0;i<this.store.data.length;i++){
  385. var r = this.store.getAt(i);
  386. newValue = r.data[this.displayField];
  387. check=document.getElementById("checkBox_"+newValue);
  388. if(check.className=="checked"){
  389. value+= r.data[this.displayField]+this.displaySeparator;
  390. hiddenValue+= r.data[this.valueField]+this.valueSeparator;
  391. }
  392. }
  393. if(value.length>1){
  394. value=value.substring(0,value.length-this.displaySeparator.length);
  395. }
  396. if(hiddenValue.length>1){
  397. hiddenValue=hiddenValue.substring(0,value.length-this.valueSeparator.length);
  398. }
  399. this.setValue(value);
  400. this.hiddenField.value=hiddenValue;
  401. this.fireEvent('select', this, record, index);
  402. }
  403. },
  404. getValue : function(){
  405. if(this.valueField){
  406. return typeof this.value != 'undefined' ? this.value : '';
  407. }else{
  408. return <span class="hilite1">Ext</span>
  409. .form.ComboBox.superclass.getValue.call(this);
  410. }
  411. },
  412. /**
  413. * Clears any text/value currently set in the field
  414. */
  415. clearValue : function(){
  416. if(this.hiddenField){
  417. this.hiddenField.value = '';
  418. }
  419. this.setRawValue('');
  420. this.lastSelectionText = '';
  421. this.applyEmptyText();
  422. },
  423. setValue : function(v){
  424. var text = v;
  425. if(this.valueField){
  426. var r = this.findRecord(this.valueField, v);
  427. if(r){
  428. text = r.data[this.displayField];
  429. }else if(this.valueNotFoundText !== undefined){
  430. text = this.valueNotFoundText;
  431. }
  432. }
  433. this.lastSelectionText = text;
  434. <span class="hilite1">Ext</span>
  435. .form.ComboBox.superclass.setValue.call(this, text);
  436. this.value = v;
  437. },
  438. // private
  439. findRecord : function(prop, value){
  440. var record;
  441. if(this.store.getCount() > 0){
  442. this.store.each(function(r){
  443. if(r.data[prop] == value){
  444. record = r;
  445. return false;
  446. }
  447. });
  448. }
  449. return record;
  450. },
  451. // private
  452. onViewMove : function(e, t){
  453. this.inKeyMode = false;
  454. },
  455. // private
  456. onViewOver : function(e, t){
  457. if(this.inKeyMode){ // prevent key nav and mouse over conflicts
  458. return;
  459. }
  460. var item = this.view.findItemFromChild(t);
  461. if(item){
  462. var index = this.view.indexOf(item);
  463. this.select(index, false);
  464. }
  465. },
  466. // private
  467. onViewClick : function(doFocus){
  468. var index = this.view.getSelectedIndexes()[0];
  469. var r = this.store.getAt(index);
  470. if(r){
  471. this.onSelect(r, index);
  472. }
  473. if(doFocus !== false){
  474. this.el.focus();
  475. }
  476. },
  477. // private
  478. restrictHeight : function(){
  479. this.innerList.dom.style.height = '';
  480. var inner = this.innerList.dom;
  481. var fw = this.list.getFrameWidth('tb');
  482. var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
  483. this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
  484. this.list.beginUpdate();
  485. this.list.setHeight(this.innerList.getHeight()+fw+(this.resizable?this.handleHeight:0)+this.assetHeight);
  486. this.list.alignTo(this.el, this.listAlign);
  487. this.list.endUpdate();
  488. },
  489. // private
  490. onEmptyResults : function(){
  491. this.collapse();
  492. },
  493. /**
  494. * Returns true if the dropdown list is expanded, else false.
  495. */
  496. isExpanded : function(){
  497. return this.list && this.list.isVisible();
  498. },
  499. selectByValue : function(v, scrollIntoView){
  500. if(v !== undefined && v !== null){
  501. var r = this.findRecord(this.valueField || this.displayField, v);
  502. if(r){
  503. this.select(this.store.indexOf(r), scrollIntoView);
  504. return true;
  505. }
  506. }
  507. return false;
  508. },
  509. select : function(index, scrollIntoView){
  510. this.selectedIndex = index;
  511. this.view.select(index);
  512. if(scrollIntoView !== false){
  513. var el = this.view.getNode(index);
  514. if(el){
  515. this.innerList.scrollChildIntoView(el, false);
  516. }
  517. }
  518. },
  519. // private
  520. selectNext : function(){
  521. var ct = this.store.getCount();
  522. if(ct > 0){
  523. if(this.selectedIndex == -1){
  524. this.select(0);
  525. }else if(this.selectedIndex < ct-1){
  526. this.select(this.selectedIndex+1);
  527. }
  528. }
  529. },
  530. // private
  531. selectPrev : function(){
  532. var ct = this.store.getCount();
  533. if(ct > 0){
  534. if(this.selectedIndex == -1){
  535. this.select(0);
  536. }else if(this.selectedIndex != 0){
  537. this.select(this.selectedIndex-1);
  538. }
  539. }
  540. },
  541. // private
  542. onKeyUp : function(e){
  543. if(this.editable !== false && !e.isSpecialKey()){
  544. this.lastKey = e.getKey();
  545. this.dqTask.delay(this.queryDelay);
  546. }
  547. },
  548. // private
  549. validateBlur : function(){
  550. return !this.list || !this.list.isVisible();
  551. },
  552. // private
  553. initQuery : function(){
  554. this.doQuery(this.getRawValue());
  555. },
  556. // private
  557. doForce : function(){
  558. if(this.el.dom.value.length > 0){
  559. this.el.dom.value =
  560. this.lastSelectionText === undefined ? '' : this.lastSelectionText;
  561. this.applyEmptyText();
  562. }
  563. },
  564. doQuery : function(q, forceAll){
  565. if(q === undefined || q === null){
  566. q = '';
  567. }
  568. var qe = {
  569. query: q,
  570. forceAll: forceAll,
  571. combo: this,
  572. cancel:false
  573. };
  574. if(this.fireEvent('beforequery', qe)===false || qe.cancel){
  575. return false;
  576. }
  577. q = qe.query;
  578. forceAll = qe.forceAll;
  579. if(forceAll === true || (q.length >= this.minChars)){
  580. if(this.lastQuery !== q){
  581. this.lastQuery = q;
  582. if(this.mode == 'local'){
  583. this.selectedIndex = -1;
  584. if(forceAll){
  585. this.store.clearFilter();
  586. }else{
  587. this.store.filter(this.displayField, q);
  588. }
  589. this.onLoad();
  590. }else{
  591. this.store.baseParams[this.queryParam] = q;
  592. this.store.load({
  593. params: this.getParams(q)
  594. });
  595. this.expand();
  596. }
  597. }else{
  598. this.selectedIndex = -1;
  599. this.onLoad();
  600. }
  601. }
  602. },
  603. // private
  604. getParams : function(q){
  605. var p = {};
  606. //p[this.queryParam] = q;
  607. if(this.pageSize){
  608. p.start = 0;
  609. p.limit = this.pageSize;
  610. }
  611. return p;
  612. },
  613. /**
  614. * Hides the dropdown list if it is currently expanded. Fires the 'collapse' event on completion.
  615. */
  616. collapse : function(){
  617. if(!this.isExpanded()){
  618. return;
  619. }
  620. this.list.hide();
  621. <span class="hilite1">Ext</span>
  622. .getDoc().un('mousewheel', this.collapseIf, this);
  623. <span class="hilite1">Ext</span>
  624. .getDoc().un('mousedown', this.collapseIf, this);
  625. this.fireEvent('collapse', this);
  626. },
  627. // private
  628. collapseIf : function(e){
  629. if(!e.within(this.wrap) && !e.within(this.list)){
  630. this.collapse();
  631. }
  632. },
  633. /**
  634. * Expands the dropdown list if it is currently hidden. Fires the 'expand' event on completion.
  635. */
  636. expand : function(){
  637. if(this.isExpanded() || !this.hasFocus){
  638. return;
  639. }
  640. this.list.alignTo(this.wrap, this.listAlign);
  641. var hvalueArray=this.hiddenField.value.split(this.valueSeparator);
  642. for(var i=0;i<this.store.data.length;i++){
  643. var r = this.store.getAt(i);
  644. var newValue = r.data[this.displayField];
  645. var v=r.data[this.valueField];
  646. for(var j=0;j<hvalueArray.length;j++){
  647. if(hvalueArray[j]==v){
  648. document.getElementById("checkBox_"+newValue).className="checked";
  649. }
  650. }
  651. }
  652. this.list.show();
  653. <span class="hilite1">Ext</span>
  654. .getDoc().on('mousewheel', this.collapseIf, this);
  655. <span class="hilite1">Ext</span>
  656. .getDoc().on('mousedown', this.collapseIf, this);
  657. this.fireEvent('expand', this);
  658. },
  659. // private
  660. // Implements the default empty TriggerField.onTriggerClick function
  661. onTriggerClick : function(){
  662. if(this.disabled){
  663. return;
  664. }
  665. if(this.isExpanded()){
  666. this.collapse();
  667. this.el.focus();
  668. }else {
  669. this.onFocus({});
  670. if(this.triggerAction == 'all') {
  671. this.doQuery(this.allQuery, true);
  672. } else {
  673. this.doQuery(this.getRawValue());
  674. }
  675. this.el.focus();
  676. }
  677. }
  678. });
  679. <span class="hilite1">Ext</span>
  680. .reg('multicombo', <span class="hilite1">Ext</span>
  681. .form.MultiComboBox);

ext-all.css文件最后添加两行支持样式:

1.checked{background-image:url(../images/default/menu/checked.gif)}

2.unchecked{background-image:url(../images/default/menu/unchecked.gif)}

分享到:
评论

相关推荐

    ext多选下拉列表的全选功能实现

    "ext多选下拉列表的全选功能实现"这个主题聚焦于一个特定的UI组件——ExtJS库中的MultiComboBox,这是一种允许用户多选的下拉列表控件。在实际应用中,全选功能常常被用来快速选择所有选项,极大地提高了用户的操作...

    伊兰COMBO (强大的Ext单多选下拉列表控件;带详细示例)

    强大的Ext单多选下拉列表控件;基于 LovCombo ; * 作者:中国.湖南.长沙.任文敏 * * 功能: * 1. 支持:★ 多选|单选 (isSingle:'N|Y') * 2. 多选支持: 全选/全不选 * 3. ★ 多选且分页支持: 全部清除 * 4...

    ext下拉多选组件multicombo

    "ext下拉多选组件multicombo"是一种专为EXTJS框架设计的组件,EXTJS是一个强大的JavaScript库,用于创建桌面级的富客户端应用。这个组件扩展了EXTJS的原生下拉框(ComboBox)功能,增加了多选特性,使得用户可以在下...

    Extjs4 多选下拉树

    在ExtJS4中,多选下拉树(Multi Select Tree)是一种用户界面组件,它结合了下拉菜单和树形结构,允许用户从层级结构中选择多个项目。这个组件在数据管理、分类选择等场景中非常实用。 在实现多选下拉树时,我们...

    EXT3.2 多选下拉框

    EXT3.2 多选下拉框是一种在EXT JS框架中实现的用户界面组件,它允许用户在下拉菜单中选择多个选项。EXT JS是一个基于JavaScript的富客户端应用开发框架,用于构建桌面级的Web应用。EXT3.2是EXT JS的一个版本,尽管...

    EXT多选COMBO

    在EXTJS中,ComboBox是基于Ext.form.field.ComboBox类创建的,通常用于显示一个可搜索的下拉列表。多选功能则是通过扩展ComboBox的基本行为来实现的。这可能涉及到监听用户的交互事件,如点击或键盘操作,以及处理...

    ext js 下拉树

    下拉树(Dropdown Tree)是Ext JS中的一种特殊控件,它结合了下拉列表和树结构的功能,通常用于展示层次化的数据,并让用户从中选择一个或多个项。 下拉树的基本结构由两部分组成:一个文本框和一个关联的下拉面板...

    Ext combobox 下拉多选框带搜索功能

    在给定的标题“Ext ComboBox 下拉多选框带搜索功能”中,我们关注的是一个特别的ComboBox实现,它不仅允许用户从下拉列表中选择多个选项,还具备搜索功能,使得用户可以更高效地找到他们想要的选择项。 ComboBox在...

    Ext多选下拉框

    在Ext JS这个强大的JavaScript框架中,多选下拉框(Multi Select ComboBox)是一种常见的组件,用于提供用户在多个选项中进行选择的功能。这种组件在数据输入、筛选或配置设置等场景中非常实用。本篇文章将深入探讨...

    Ext模拟下拉多选checkbox

    Extjs 模拟下拉多选checkbox

    ext多选下拉框(代码及例子)

    在"ext多选下拉框(代码及例子)"这个主题中,主要涉及到的知识点有: 1. **EXTJS的Combo组件**:Combo是EXTJS中的一种表单组件,它提供了下拉列表的功能,可以用于输入或者选择数据。它既可以作为单选也可以作为...

    Extjs下拉多选树

    在ExtJS中,"下拉多选树"(Combobox Tree)是一种结合了下拉框和树形结构的组件,它允许用户在下拉菜单中选择多个树节点,提供了一种高效且直观的用户交互方式。 1. **下拉树组件**:在ExtJS中,树形组件...

    Extjs4.X下comboboxTree下拉树型菜单,完美支持多选、单选,绝对好用

    这种组件在数据选择上非常实用,尤其当数据层级关系复杂时,可以方便地进行多选或单选操作。下面我们将深入探讨ComboboxTree的实现原理、主要功能以及如何在实际项目中应用。 1. **ComboboxTree的基本概念** ...

    EXT 多选

    EXT 多选是一种在网页应用中常见的用户交互功能,它允许用户在一组选项中选择多个条目。EXT 是一个基于 JavaScript 的富客户端框架,由 Sencha 公司开发,主要用于构建复杂的、数据驱动的 Web 应用程序。EXT 提供了...

    ext-----多选下拉框

    在EXT框架中,"多选下拉框"是一种常见的组件,它允许用户在下拉列表中选择多个选项,而不是仅限于单选。 在EXT中实现多选下拉框,主要涉及到EXT的`ComboBox`组件和`multiSelect`配置项。`ComboBox`是一个灵活的输入...

    Extjs3 多选下拉框LovCombo

    在ExtJS 3中,多选下拉框(LovCombo)是一种复合组件,它结合了下拉列表和“爱好者选择”(LOV,Lookup Value)的功能,允许用户在多个选项中进行复选选择。在Web应用中,这种组件常用于数据输入,特别是在数据库...

    combobox Ext之扩展组件多选下拉框

    - `store`:用于存储下拉选项的数据源,可以是数组或Ext.data.Store对象。 2. **多选事件处理**: - `select`事件:在多选模式下,当用户添加或移除选项时,这个事件会被触发。我们需要监听此事件来处理值的改变...

    Ext 带多选的Tree

    "Ext 带多选的Tree"指的是在EXT JS的Tree组件中集成了多选功能,允许用户通过复选框来选择多个树节点,从而实现批量操作或者进行多级数据的选择。 在EXT JS中,Tree组件通常是通过`Ext.tree.Panel`类创建的,它提供...

    extjs多选下拉框

    ExtJS社区提供了很多插件,如`Ext.ux.MultiSelect`,可以帮助实现多选下拉框功能,减轻开发负担。如果`MultiComboBox.js`是这样的一个插件,那么它可能封装了上述功能并提供了一些额外的特性,如拖放排序、搜索过滤...

Global site tag (gtag.js) - Google Analytics