`
langgufu
  • 浏览: 2312645 次
  • 性别: 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下拉多选组件multicombo

    通过深入学习EXTJS的"ext下拉多选组件multicombo",开发者可以掌握如何在自己的应用中实现多选下拉功能,提升用户体验。同时,对源码的研究有助于增强EXTJS框架的理解,从而更好地进行组件的扩展和定制,满足特定...

    extjs实现下拉框多选

    最后,`multiCombox` 文件名可能指的是一个包含实现多选下拉框功能的代码或示例的文件。如果你有这个文件,可以参考其中的内容,结合上述讲解来理解和学习多选ComboBox的实现。在实践中,不断探索和调试,你将更熟练...

    级联H桥SVG无功补偿系统在不平衡电网中的三层控制策略:电压电流双闭环PI控制、相间与相内电压均衡管理,级联H桥SVG无功补偿系统在不平衡电网中的三层控制策略:电压电流双闭环PI控制、相间与相内电压均

    级联H桥SVG无功补偿系统在不平衡电网中的三层控制策略:电压电流双闭环PI控制、相间与相内电压均衡管理,级联H桥SVG无功补偿系统在不平衡电网中的三层控制策略:电压电流双闭环PI控制、相间与相内电压均衡管理,不平衡电网下的svg无功补偿,级联H桥svg无功补偿statcom,采用三层控制策略。 (1)第一层采用电压电流双闭环pi控制,电压电流正负序分离,电压外环通过产生基波正序有功电流三相所有H桥模块直流侧平均电压恒定,电流内环采用前馈解耦控制; (2)第二层相间电压均衡控制,注入零序电压,控制通过注入零序电压维持相间电压平衡; (3)第三层相内电压均衡控制,使其所有子模块吸收的有功功率与其损耗补,从而保证所有H桥子模块直流侧电压值等于给定值。 有参考资料。 639,核心关键词: 1. 不平衡电网下的SVG无功补偿 2. 级联H桥SVG无功补偿STATCOM 3. 三层控制策略 4. 电压电流双闭环PI控制 5. 电压电流正负序分离 6. 直流侧平均电压恒定 7. 前馈解耦控制 8. 相间电压均衡控制 9. 零序电压注入 10. 相内电压均衡控制 以上十个关键词用分号分隔的格式为:不

    GTX 1080 PCB图纸

    GTX 1080 PCB图纸,内含图纸查看软件

    深度优化与应用:提升DeepSeek润色指令的有效性和灵活性指南

    内容概要:本文档详细介绍了利用 DeepSeek 进行文本润色和问答交互时提高效果的方法和技巧,涵盖了从明确需求、提供适当上下文到尝试开放式问题以及多轮对话的十个要点。每一部分内容都提供了具体的示范案例,如指定回答格式、分步骤提问等具体实例,旨在指导用户更好地理解和运用 DeepSeek 提升工作效率和交流质量。同时文中还强调了根据不同应用场景调整提示词语气和风格的重要性和方法。 适用人群:适用于希望通过优化提问技巧以获得高质量反馈的企业员工、科研人员以及一般公众。 使用场景及目标:本文针对所有期望提高 DeepSeek 使用效率的人群,帮助他们在日常工作中快速获取精准的答案或信息,特别是在撰写报告、研究材料准备和技术咨询等方面。此外还鼓励用户通过不断尝试不同形式的问题表述来进行有效沟通。 其他说明:该文档不仅关注实际操作指引,同样重视用户思维模式转变——由简单索取答案向引导 AI 辅助创造性解决问题的方向发展。

    基于FPGA与W5500实现的TCP网络通信测试平台开发-Zynq扩展口Verilog编程实践,基于FPGA与W5500芯片的TCP网络通信测试及多路Socket实现基于zynq开发平台和Vivad

    基于FPGA与W5500实现的TCP网络通信测试平台开发——Zynq扩展口Verilog编程实践,基于FPGA与W5500芯片的TCP网络通信测试及多路Socket实现基于zynq开发平台和Vivado 2019软件的扩展开发,基于FPGA和W5500的TCP网络通信 测试平台 zynq扩展口开发 软件平台 vivado2019.2,纯Verilog可移植 测试环境 压力测试 cmd命令下ping电脑ip,同时采用上位机进行10ms发包回环测试,不丢包(内部数据回环,需要时间处理) 目前实现单socket功能,多路可支持 ,基于FPGA; W5500; TCP网络通信; Zynq扩展口开发; 纯Verilog可移植; 测试平台; 压力测试; 10ms发包回环测试; 单socket功能; 多路支持。,基于FPGA与W5500的Zynq扩展口TCP通信测试:可移植Verilog实现的高效网络通信

    Labview液压比例阀伺服阀试验台多功能程序:PLC通讯、液压动画模拟、手动控制与调试、传感器标定、报警及记录、自动实验、数据处理与查询存储,报表生成与打印一体化解决方案 ,Labview液压比例阀

    Labview液压比例阀伺服阀试验台多功能程序:PLC通讯、液压动画模拟、手动控制与调试、传感器标定、报警及记录、自动实验、数据处理与查询存储,报表生成与打印一体化解决方案。,Labview液压比例阀伺服阀试验台多功能程序:PLC通讯、液压动画模拟、手动控制与调试、传感器标定、报警管理及实验自动化,labview液压比例阀伺服阀试验台程序:功能包括,同PLC通讯程序,液压动画,手动控制及调试,传感器标定,报警设置及报警记录,自动实验,数据处理曲线处理,数据库存储及查询,报表自动生成及打印,扫码枪扫码及信号录入等~ ,核心关键词:PLC通讯; 液压动画; 手动控制及调试; 传感器标定; 报警设置及记录; 自动实验; 数据处理及曲线处理; 数据库存储及查询; 报表生成及打印; 扫码枪扫码。,Labview驱动的智能液压阀测试系统:多功能控制与数据处理

    华为、腾讯、万科员工职业发展体系建设与实践.pptx

    华为、腾讯、万科员工职业发展体系建设与实践.pptx

    基于遗传算法的柔性车间调度优化 附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    电网不对称故障下VSG峰值电流限制的柔性控制策略:实现电流平衡与功率容量的优化利用,电网不对称故障下VSG峰值电流限制的柔性控制策略:兼顾平衡电流与功率控制切换的动态管理,电网不对称故障下VSG峰值电

    电网不对称故障下VSG峰值电流限制的柔性控制策略:实现电流平衡与功率容量的优化利用,电网不对称故障下VSG峰值电流限制的柔性控制策略:兼顾平衡电流与功率控制切换的动态管理,电网不对称故障下VSG峰值电流限制的柔性不平衡控制(文章完全复现)。 提出一种在不平衡运行条件下具有峰值电流限制的可变不平衡电流控制方法,可灵活地满足不同操作需求,包括电流平衡、有功或无功恒定运行(即电流控制、有功控制或无功控制之间的相互切),注入电流保持在安全值内,以更好的利用VSG功率容量。 关键词:VSG、平衡电流控制、有功功率控制、无功功率控制。 ,VSG; 峰值电流限制; 柔性不平衡控制; 电流平衡控制; 有功功率控制; 无功功率控制。,VSG柔性控制:在电网不对称故障下的峰值电流限制与平衡管理

    libpinyin-tools-0.9.93-4.el7.x64-86.rpm.tar.gz

    1、文件内容:libpinyin-tools-0.9.93-4.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/libpinyin-tools-0.9.93-4.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊

    机器学习(预测模型):动漫《龙珠》相关的数据集

    数据集是一个以经典动漫《龙珠》为主题的多维度数据集,广泛应用于数据分析、机器学习和图像识别等领域。该数据集由多个来源整合而成,涵盖了角色信息、战斗力、剧情片段、台词以及角色图像等多个方面。数据集的核心内容包括: 角色信息:包含《龙珠》系列中的主要角色及其属性,如名称、种族、所属系列(如《龙珠》《龙珠Z》《龙珠超》等)、战斗力等级等。 图像数据:提供角色的图像资源,可用于图像分类和角色识别任务。这些图像来自动画剧集、漫画和相关衍生作品。 剧情与台词:部分数据集还包含角色在不同故事中的台词和剧情片段,可用于文本分析和自然语言处理任务。 战斗数据:记录角色在不同剧情中的战斗力变化和战斗历史,为研究角色成长和剧情发展提供支持。 数据集特点 多样性:数据集整合了角色、图像、文本等多种类型的数据,适用于多种研究场景。 深度:不仅包含角色的基本信息,还涵盖了角色的成长历程、技能描述和与其他角色的互动关系。 实用性:支持多种编程语言(如Python、R)的数据处理和分析,提供了详细的文档和示例代码。

    基于protues仿真的多功公交站播报系统设计(仿真图、源代码)

    基于protues仿真的多功公交站播报系统设计(仿真图、源代码) 该设计为基于protues仿真的多功公交站播报系统,实现温度显示、时间显示、和系统公交站播报功能; 具体功能如下: 1、系统使用51单片机为核心设计; 2、时钟芯片进行时间和日期显示; 3、温度传感器进行温度读取; 4、LCD12864液晶屏进行相关显示; 5、按键设置调节时间; 6、按键设置报站; 7、仿真图、源代码; 操作说明: 1、下行控制报站:首先按下(下行设置按键),(下行指示灯)亮,然后按下(手动播报)按键控制播报下一站; 2、上行控制报站:首先按上(上行设置按键),(上行指示灯)亮,然后按下(手动播报)按键控制播报下一站; 3、按下关闭播报按键,则关闭播报功能和清除显示

    基于微信小程序的琴房管理系统的设计与实现.zip

    采用Java后台技术和MySQL数据库,在前台界面为提升用户体验,使用Jquery、Ajax、CSS等技术进行布局。 系统包括两类用户:学生、管理员。 学生用户 学生用户只要实现了前台信息的查看,打开首页,查看网站介绍、琴房信息、在线留言、轮播图信息公告等,通过点击首页的菜单跳转到对应的功能页面菜单,包括网站首页、琴房信息、注册登录、个人中心、后台登录。 学生用户通过账户账号登录,登录后具有所有的操作权限,如果没有登录,不能在线预约。学生用户退出系统将注销个人的登录信息。 管理员通过后台的登录页面,选择管理员权限后进行登录,管理员的权限包括轮播公告管理、老师学生信息管理和信息审核管理,管理员管理后点击退出,注销登录信息。 管理员用户具有在线交流的管理,琴房信息管理、琴房预约管理。 在线交流是对前台用户留言内容进行管理,删除留言信息,查看留言信息。

    界面GUI设计MATLAB教室人数统计.zip

    MATLAB可以用于开发人脸识别考勤系统。下面是一个简单的示例流程: 1. 数据采集:首先收集员工的人脸图像作为训练数据集。可以要求员工提供多张照片以获得更好的训练效果。 2. 图像预处理:使用MATLAB的图像处理工具对采集到的人脸图像进行预处理,例如灰度化、裁剪、缩放等操作。 3. 特征提取:利用MATLAB的人脸识别工具包,如Face Recognition Toolbox,对处理后的图像提取人脸特征,常用的方法包括主成分分析(PCA)和线性判别分析(LDA)等。 4. 训练模型:使用已提取的人脸特征数据集训练人脸识别模型,可以选择支持向量机(SVM)、卷积神经网络(CNN)等算法。 5. 考勤系统:在员工打卡时,将摄像头捕获的人脸图像输入到训练好的模型中进行识别,匹配员工信息并记录考勤数据。 6. 结果反馈:根据识别结果,可以自动生成考勤报表或者实时显示员工打卡情况。 以上只是一个简单的步骤,实际开发过程中需根据具体需求和系统规模进行定制和优化。MATLAB提供了丰富的图像处理和机器学习工具,是开发人脸识别考勤系统的一个很好选择。

    hjbvbnvhjhjg

    hjbvbnvhjhjg

    HCIP、软考相关学习PPT

    HCIP、软考相关学习PPT提供下载

    绿豆BOX UI8版:反编译版六个全新UI+最新后台直播管理源码

    绿豆BOX UI8版:反编译版六个全新UI+最新后台直播管理源码 最新绿豆BOX反编译版六个UI全新绿豆盒子UI8版本 最新后台支持直播管理 作为UI6的升级版,UI8不仅修复了前一版本中存在的一些BUG,还提供了6套不同的UI界面供用户选择,该版本有以下特色功能: 在线管理TVBOX解析 在线自定义TVBOX 首页布局批量添加会员信息 并支持导出批量生成卡密 并支持导出直播列表管理功能

    vue3的一些语法以及知识点

    vue3的一些语法以及知识点

    西门子大型Fanuc机器人汽车焊装自动生产线程序经典解析:PLC博图编程与MES系统通讯实战指南,西门子PLC博图汽车焊装自动生产线FANUC机器人程序经典结构解析与MES系统通讯,西门子1500 大

    西门子大型Fanuc机器人汽车焊装自动生产线程序经典解析:PLC博图编程与MES系统通讯实战指南,西门子PLC博图汽车焊装自动生产线FANUC机器人程序经典结构解析与MES系统通讯,西门子1500 大型程序fanuc 机器人汽车焊装自动生产线程序 MES 系统通讯 大型程序fanuc机器人汽车焊装自动生产线程序程序经典结构清晰,SCL算法堆栈,梯形图和 SCL混编使用博图 V14以上版本打开 包括: 1、 PLC 博图程序 2 触摸屏程序 ,西门子1500; 大型程序; fanuc机器人; 汽车焊装自动生产线; MES系统通讯; SCL算法; 梯形图; SCL混编; 博图V14以上版本。,西门子博图大型程序:汽车焊装自动生产线MES系统通讯与机器人控制

Global site tag (gtag.js) - Google Analytics