💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
支持Form颜色选择组件、日期时间选择组件、带图标的下拉列表、多选下来列表、动态下拉列表树等组件 开发环境: System:Windows WebBrowser:IE6+、Firefox3+ JavaEE Server:tomcat5.0.2.8、tomcat6 IDE:eclipse、MyEclipse 8 开发依赖库: JavaEE5、ext 2.2.2 Email:hoojo_@126.com Blog:[http://blog.csdn.net/IBM_hoojo](http://blog.csdn.net/IBM_hoojo) [http://hoojo.cnblogs.com/](http://hoojo.cnblogs.com/) ### 一、ColoFieldr组件 可以选择一些常用的颜色 ![](https://box.kancloud.cn/2016-04-01_56fe1229e2976.gif) 需要用到的文件 ColorField组件文件:Ext.form.ColorField.js ColorField运行示例文件:Ext.hoo.for.ColorField.js 代码如下 Color.html ~~~ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>form Component -- DateTimeField</title> <meta http-equiv="pragma" content="no-cache"/> <meta http-equiv="cache-control" content="no-cache"/> <meta http-equiv="expires" content="0"/> <meta http-equiv="content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="author" content="hoojo"/> <meta http-equiv="email" content="hoojo_@126.com"/> <meta http-equiv="ext-lib" content="version 2.2"/> <meta http-equiv="blog" content="http://blog.csdn.net/IBM_hoojo"/> <link rel="stylesheet" type="text/css" href="../ext2/resources/css/ext-all.css"/> <script type="text/javascript" src="../ext2/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext2/ext-all.js"></script> <script type="text/javascript" src="../ext2/build/locale/ext-lang-zh_CN-min.js"></script> <script type="text/javascript" src="Ext.form.ColorField.js"></script> <script type="text/javascript" src="Ext.hoo.for.ColorField.js"></script> </head> <body> <div id="show" style="float: left; margin: 100px 0 0 100px;"></div> </body> </html> ~~~   Ext.form.ColorField.js ~~~ /** * @class Ext.form.ColorField * @extends Ext.form.TriggerField * Provides a very simple color form field with a ColorMenu dropdown. * Values are stored as a six-character hex value without the '#'. * I.e. 'ffffff' * @constructor * Create a new ColorField * <br />Example: * <pre><code> var cf = new Ext.form.ColorField({ fieldLabel: 'Color', hiddenName:'pref_sales', showHexValue:true }); </code></pre> * @param {Object} config */ Ext.form.ColorField = function(config){ Ext.form.ColorField.superclass.constructor.call(this, config); //this.on('render', this.handleRender); }; Ext.extend(Ext.form.ColorField, Ext.form.TriggerField, { /** * @cfg {Boolean} showHexValue * True to display the HTML Hexidecimal Color Value in the field * so it is manually editable. */ showHexValue : false, /** * @cfg {String} triggerClass * An additional CSS class used to style the trigger button. The trigger will always get the * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified (defaults to 'x-form-color-trigger' * which displays a calendar icon). */ triggerClass : 'x-form-color-trigger', /** * @cfg {String/Object} autoCreate * A DomHelper element spec, or true for a default element spec (defaults to * {tag: "input", type: "text", size: "10", autocomplete: "off"}) */ // private defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off", maxlength:"6"}, /** * @cfg {String} lengthText * A string to be displayed when the length of the input field is * not 3 or 6, i.e. 'fff' or 'ffccff'. */ lengthText: "Color hex values must be either 3 or 6 characters.", //text to use if blank and allowBlank is false blankText: "Must have a hexidecimal value in the format ABCDEF.", /** * @cfg {String} color * A string hex value to be used as the default color. Defaults * to 'FFFFFF' (white). */ defaultColor: 'FFFFFF', maskRe: /[a-f0-9]/i, // These regexes limit input and validation to hex values regex: /[a-f0-9]/i, //private curColor: 'ffffff', initComponent:function(){ Ext.form.ColorField.superclass.initComponent.call(this); this.addEvents('click','change', 'select'); }, onChange: function (field, newVal, oldVal) { alert(newVal); }, onRender : function(ct, position){ Ext.form.ColorField.superclass.onRender.call(this, ct, position); this.handleRender(); }, // private validateValue : function(value){ if(!this.showHexValue) { return true; } if(value.length<1) { this.el.setStyle({ 'background-color':'#' + this.defaultColor }); if(!this.allowBlank) { this.markInvalid(String.format(this.blankText, value)); return false } return true; } if(value.length!=3 && value.length!=6 ) { this.markInvalid(String.format(this.lengthText, value)); return false; } this.setColor(value); return true; }, // private validateBlur : function(){ return !this.menu || !this.menu.isVisible(); }, // Manually apply the invalid line image since the background // was previously cleared so the color would show through. markInvalid : function( msg ) { Ext.form.ColorField.superclass.markInvalid.call(this, msg); this.el.setStyle({ 'background-image': 'url(../lib/resources/images/default/grid/invalid_line.gif)' }); }, /** * Returns the current color value of the color field * @return {String} value The hexidecimal color value */ getValue : function(){ return this.curValue || this.defaultValue || "FFFFFF"; }, /** * Sets the value of the color field. Format as hex value 'FFFFFF' * without the '#'. * @param {String} hex The color value */ setValue : function(hex){ Ext.form.ColorField.superclass.setValue.call(this, hex); this.setColor(hex); }, /** * Sets the current color and changes the background. * Does *not* change the value of the field. * @param {String} hex The color value. */ setColor : function(hex) { this.curColor = hex; this.el.setStyle( { 'background-color': '#' + hex, 'background-image': 'none' }); if(!this.showHexValue) { this.el.setStyle({ 'text-indent': '-100px' }); if(Ext.isIE) { this.el.setStyle({ 'margin-left': '100px' }); } } }, handleRender: function() { this.setDefaultColor(); }, setDefaultColor : function() { this.setValue(this.defaultColor); }, // private menuListeners : { select: function(m, d){ this.setValue(d); }, show : function(){ // retain focus styling this.onFocus(); }, hide : function(){ this.focus(); var ml = this.menuListeners; this.menu.un("select", ml.select, this); this.menu.un("show", ml.show, this); this.menu.un("hide", ml.hide, this); } }, //private handleSelect : function(palette, selColor) { this.setValue(selColor); this.fireEvent("click", this, selColor); this.fireEvent("change", this, selColor); this.fireEvent("select", this, selColor); }, // private // Implements the default empty TriggerField.onTriggerClick function to display the ColorPicker onTriggerClick : function(){ if(this.disabled){ return; } if(this.menu == null){ this.menu = new Ext.menu.ColorMenu(); this.menu.palette.on('select', this.handleSelect, this ); } this.menu.on(Ext.apply({}, this.menuListeners, { scope:this })); this.menu.show(this.el, "tl-bl?"); } }); ~~~   Ext.hoo.for.ColorField.js ~~~ /** * @function 颜色选择器 * @auhor: hoojo * @createDate: Sep 11, 2010 10:35:15 PM * @blog: blog.csdn.net/IBM_hoojo * @email: hoojo_@126.com * @class Ext.hoo.form.ColorField * @extends Ext.form.ColorField */ Ext.ns("Ext.hoo.form"); Ext.hoo.form.ColorField = Ext.extend(Ext.form.ColorField, { constructor: function () { Ext.hoo.form.ColorField.superclass.constructor.call(this, { //fieldLabel: "plase selected", renderTo: "show", width: 160, defaultColor: "00FF00", curColor: "00FF00", showHexValue: true, listeners: { "select": function (f, v) { alert(this.getValue() + "##" + v); } } }); } }); Ext.onReady(function () { Ext.BLANK_IMAGE_URL = "../ext2/resources/images/default/s.gif"; Ext.QuickTips.init(); Ext.form.Field.prototype.msgTarget = "qtip"; new Ext.hoo.form.ColorField(); }); ~~~ ### 二、日期时间选择控件 可以选择日期、时间 ![](https://box.kancloud.cn/2016-04-01_56fe122a1a9ce.gif) 需要用到的文件 Spinner.js Spinner.css SpinnerField.js 日期时间组件:Ext.ux.form.DateTimeField.js 示例:Ext.hoo.form.DateTimeField.js 代码如下 dateTimeFieldExample.htm ~~~ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>form Component -- MultiComboBox</title> <meta http-equiv="pragma" content="no-cache"/> <meta http-equiv="cache-control" content="no-cache"/> <meta http-equiv="expires" content="0"/> <meta http-equiv="content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="author" content="hoojo"/> <meta http-equiv="email" content="hoojo_@126.com"/> <meta http-equiv="ext-lib" content="version 3.2"/> <meta http-equiv="blog" content="http://blog.csdn.net/IBM_hoojo"/> <link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css"/> <link rel="stylesheet" type="text/css" href="../css/Spinner.css"/> <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext/ext-all.js"></script> <script type="text/javascript" src="../ext/build/locale/ext-lang-zh_CN-min.js"></script> <script type="text/javascript" src="Spinner.js"></script> <script type="text/javascript" src="SpinnerField.js"></script> <script type="text/javascript" src="Ext.ux.form.DateTimeField.js"></script> <script type="text/javascript" src="Ext.hoo.form.DateTimeField.js"></script> </head> <body> <div id="show" style="float: left; margin: 100px 0 0 100px;"></div> </body> </html> ~~~ Spinner.css ~~~ /*! * Ext JS Library 3.1.1 * Copyright(c) 2006-2010 Ext JS, LLC * licensing@extjs.com * http://www.extjs.com/license */ .x-form-spinner-proxy{ /*background-color:#ff00cc;*/ } .x-form-field-wrap .x-form-spinner-trigger { background:transparent url('../images/spinner.gif') no-repeat 0 0; } .x-form-field-wrap .x-form-spinner-overup{ background-position:-17px 0; } .x-form-field-wrap .x-form-spinner-clickup{ background-position:-34px 0; } .x-form-field-wrap .x-form-spinner-overdown{ background-position:-51px 0; } .x-form-field-wrap .x-form-spinner-clickdown{ background-position:-68px 0; } .x-trigger-wrap-focus .x-form-spinner-trigger{ background-position:-85px 0; } .x-trigger-wrap-focus .x-form-spinner-overup{ background-position:-102px 0; } .x-trigger-wrap-focus .x-form-spinner-clickup{ background-position:-119px 0; } .x-trigger-wrap-focus .x-form-spinner-overdown{ background-position:-136px 0; } .x-trigger-wrap-focus .x-form-spinner-clickdown{ background-position:-153px 0; } .x-trigger-wrap-focus .x-form-trigger{ border-bottom: 1px solid #7eadd9; } .x-form-field-wrap .x-form-spinner-splitter { line-height:1px; font-size:1px; background:transparent url('../images/spinner-split.gif') no-repeat 0 0; position:absolute; cursor: n-resize; } .x-trigger-wrap-focus .x-form-spinner-splitter{ background-position:-14px 0; } .x-date-bottom { font-size: 12px; } .x-date-menu { height: 200px; } ~~~ 图片 spinner.gif ![](https://box.kancloud.cn/2016-04-01_56fe122a492ab.gif) spinner-split.gif ![](https://box.kancloud.cn/2016-04-01_56fe122a668ab.gif) Spinner.js ~~~ /*! * Ext JS Library 3.1.1 * Copyright(c) 2006-2010 Ext JS, LLC * licensing@extjs.com * http://www.extjs.com/license */ /** * @class Ext.ux.Spinner * @extends Ext.util.Observable * Creates a Spinner control utilized by Ext.ux.form.SpinnerField */ Ext.ux.Spinner = Ext.extend(Ext.util.Observable, { incrementValue: 1, alternateIncrementValue: 5, triggerClass: 'x-form-spinner-trigger', splitterClass: 'x-form-spinner-splitter', alternateKey: Ext.EventObject.shiftKey, defaultValue: 0, accelerate: false, constructor: function(config){ Ext.ux.Spinner.superclass.constructor.call(this, config); Ext.apply(this, config); this.mimicing = false; }, init: function(field){ this.field = field; field.afterMethod('onRender', this.doRender, this); field.afterMethod('onEnable', this.doEnable, this); field.afterMethod('onDisable', this.doDisable, this); field.afterMethod('afterRender', this.doAfterRender, this); field.afterMethod('onResize', this.doResize, this); field.afterMethod('onFocus', this.doFocus, this); field.beforeMethod('onDestroy', this.doDestroy, this); }, doRender: function(ct, position){ var el = this.el = this.field.getEl(); var f = this.field; if (!f.wrap) { f.wrap = this.wrap = el.wrap({ cls: "x-form-field-wrap" }); } else { this.wrap = f.wrap.addClass('x-form-field-wrap'); } this.trigger = this.wrap.createChild({ tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass }); if (!f.width) { this.wrap.setWidth(el.getWidth() + this.trigger.getWidth()); } this.splitter = this.wrap.createChild({ tag: 'div', cls: this.splitterClass, style: 'width:13px; height:2px;' }); this.splitter.setRight((Ext.isIE) ? 1 : 2).setTop(10).show(); this.proxy = this.trigger.createProxy('', this.splitter, true); this.proxy.addClass("x-form-spinner-proxy"); this.proxy.setStyle('left', '0px'); this.proxy.setSize(14, 1); this.proxy.hide(); this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", { dragElId: this.proxy.id }); this.initTrigger(); this.initSpinner(); }, doAfterRender: function(){ var y; if (Ext.isIE && this.el.getY() != (y = this.trigger.getY())) { this.el.position(); this.el.setY(y); } }, doEnable: function(){ if (this.wrap) { this.wrap.removeClass(this.field.disabledClass); } }, doDisable: function(){ if (this.wrap) { this.wrap.addClass(this.field.disabledClass); this.el.removeClass(this.field.disabledClass); } }, doResize: function(w, h){ if (typeof w == 'number') { this.el.setWidth(w - this.trigger.getWidth()); } this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth()); }, doFocus: function(){ if (!this.mimicing) { this.wrap.addClass('x-trigger-wrap-focus'); this.mimicing = true; Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, { delay: 10 }); this.el.on('keydown', this.checkTab, this); } }, // private checkTab: function(e){ if (e.getKey() == e.TAB) { this.triggerBlur(); } }, // private mimicBlur: function(e){ if (!this.wrap.contains(e.target) && this.field.validateBlur(e)) { this.triggerBlur(); } }, // private triggerBlur: function(){ this.mimicing = false; Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this); this.el.un("keydown", this.checkTab, this); this.field.beforeBlur(); this.wrap.removeClass('x-trigger-wrap-focus'); this.field.onBlur.call(this.field); }, initTrigger: function(){ this.trigger.addClassOnOver('x-form-trigger-over'); this.trigger.addClassOnClick('x-form-trigger-click'); }, initSpinner: function(){ this.field.addEvents({ 'spin': true, 'spinup': true, 'spindown': true }); this.keyNav = new Ext.KeyNav(this.el, { "up": function(e){ e.preventDefault(); this.onSpinUp(); }, "down": function(e){ e.preventDefault(); this.onSpinDown(); }, "pageUp": function(e){ e.preventDefault(); this.onSpinUpAlternate(); }, "pageDown": function(e){ e.preventDefault(); this.onSpinDownAlternate(); }, scope: this }); this.repeater = new Ext.util.ClickRepeater(this.trigger, { accelerate: this.accelerate }); this.field.mon(this.repeater, "click", this.onTriggerClick, this, { preventDefault: true }); this.field.mon(this.trigger, { mouseover: this.onMouseOver, mouseout: this.onMouseOut, mousemove: this.onMouseMove, mousedown: this.onMouseDown, mouseup: this.onMouseUp, scope: this, preventDefault: true }); this.field.mon(this.wrap, "mousewheel", this.handleMouseWheel, this); this.dd.setXConstraint(0, 0, 10) this.dd.setYConstraint(1500, 1500, 10); this.dd.endDrag = this.endDrag.createDelegate(this); this.dd.startDrag = this.startDrag.createDelegate(this); this.dd.onDrag = this.onDrag.createDelegate(this); }, onMouseOver: function(){ if (this.disabled) { return; } var middle = this.getMiddle(); this.tmpHoverClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown'; this.trigger.addClass(this.tmpHoverClass); }, //private onMouseOut: function(){ this.trigger.removeClass(this.tmpHoverClass); }, //private onMouseMove: function(){ if (this.disabled) { return; } var middle = this.getMiddle(); if (((Ext.EventObject.getPageY() > middle) && this.tmpHoverClass == "x-form-spinner-overup") || ((Ext.EventObject.getPageY() < middle) && this.tmpHoverClass == "x-form-spinner-overdown")) { } }, //private onMouseDown: function(){ if (this.disabled) { return; } var middle = this.getMiddle(); this.tmpClickClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown'; this.trigger.addClass(this.tmpClickClass); }, //private onMouseUp: function(){ this.trigger.removeClass(this.tmpClickClass); }, //private onTriggerClick: function(){ if (this.disabled || this.el.dom.readOnly) { return; } var middle = this.getMiddle(); var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down'; this['onSpin' + ud](); }, //private getMiddle: function(){ var t = this.trigger.getTop(); var h = this.trigger.getHeight(); var middle = t + (h / 2); return middle; }, //private //checks if control is allowed to spin isSpinnable: function(){ if (this.disabled || this.el.dom.readOnly) { Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly return false; } return true; }, handleMouseWheel: function(e){ //disable scrolling when not focused if (this.wrap.hasClass('x-trigger-wrap-focus') == false) { return; } var delta = e.getWheelDelta(); if (delta > 0) { this.onSpinUp(); e.stopEvent(); } else if (delta < 0) { this.onSpinDown(); e.stopEvent(); } }, //private startDrag: function(){ this.proxy.show(); this._previousY = Ext.fly(this.dd.getDragEl()).getTop(); }, //private endDrag: function(){ this.proxy.hide(); }, //private onDrag: function(){ if (this.disabled) { return; } var y = Ext.fly(this.dd.getDragEl()).getTop(); var ud = ''; if (this._previousY > y) { ud = 'Up'; } //up if (this._previousY < y) { ud = 'Down'; } //down if (ud != '') { this['onSpin' + ud](); } this._previousY = y; }, //private onSpinUp: function(){ if (this.isSpinnable() == false) { return; } if (Ext.EventObject.shiftKey == true) { this.onSpinUpAlternate(); return; } else { this.spin(false, false); } this.field.fireEvent("spin", this); this.field.fireEvent("spinup", this); }, //private onSpinDown: function(){ if (this.isSpinnable() == false) { return; } if (Ext.EventObject.shiftKey == true) { this.onSpinDownAlternate(); return; } else { this.spin(true, false); } this.field.fireEvent("spin", this); this.field.fireEvent("spindown", this); }, //private onSpinUpAlternate: function(){ if (this.isSpinnable() == false) { return; } this.spin(false, true); this.field.fireEvent("spin", this); this.field.fireEvent("spinup", this); }, //private onSpinDownAlternate: function(){ if (this.isSpinnable() == false) { return; } this.spin(true, true); this.field.fireEvent("spin", this); this.field.fireEvent("spindown", this); }, spin: function(down, alternate){ var v = parseFloat(this.field.getValue()); var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue; (down == true) ? v -= incr : v += incr; v = (isNaN(v)) ? this.defaultValue : v; v = this.fixBoundries(v); this.field.setRawValue(v); }, fixBoundries: function(value){ var v = value; if (this.field.minValue != undefined && v < this.field.minValue) { v = this.field.minValue; } if (this.field.maxValue != undefined && v > this.field.maxValue) { v = this.field.maxValue; } return this.fixPrecision(v); }, // private fixPrecision: function(value){ var nan = isNaN(value); if (!this.field.allowDecimals || this.field.decimalPrecision == -1 || nan || !value) { return nan ? '' : value; } return parseFloat(parseFloat(value).toFixed(this.field.decimalPrecision)); }, doDestroy: function(){ if (this.trigger) { this.trigger.remove(); } if (this.wrap) { this.wrap.remove(); delete this.field.wrap; } if (this.splitter) { this.splitter.remove(); } if (this.dd) { this.dd.unreg(); this.dd = null; } if (this.proxy) { this.proxy.remove(); } if (this.repeater) { this.repeater.purgeListeners(); } } }); //backwards compat Ext.form.Spinner = Ext.ux.Spinner; ~~~ SpinnerField.js ~~~ /*! * Ext JS Library 3.1.1 * Copyright(c) 2006-2010 Ext JS, LLC * licensing@extjs.com * http://www.extjs.com/license */ Ext.ns('Ext.ux.form'); /** * @class Ext.ux.form.SpinnerField * @extends Ext.form.NumberField * Creates a field utilizing Ext.ux.Spinner * @xtype spinnerfield */ Ext.ux.form.SpinnerField = Ext.extend(Ext.form.NumberField, { actionMode: 'wrap', deferHeight: true, autoSize: Ext.emptyFn, onBlur: Ext.emptyFn, adjustSize: Ext.BoxComponent.prototype.adjustSize, constructor: function(config) { var spinnerConfig = Ext.copyTo({}, config, 'incrementValue,alternateIncrementValue,accelerate,defaultValue,triggerClass,splitterClass'); var spl = this.spinner = new Ext.ux.Spinner(spinnerConfig); var plugins = config.plugins ? (Ext.isArray(config.plugins) ? config.plugins.push(spl) : [config.plugins, spl]) : spl; Ext.ux.form.SpinnerField.superclass.constructor.call(this, Ext.apply(config, {plugins: plugins})); }, // private getResizeEl: function(){ return this.wrap; }, // private getPositionEl: function(){ return this.wrap; }, // private alignErrorIcon: function(){ if (this.wrap) { this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]); } }, validateBlur: function(){ return true; } }); Ext.reg('spinnerfield', Ext.ux.form.SpinnerField); //backwards compat Ext.form.SpinnerField = Ext.ux.form.SpinnerField; ~~~ Ext.ux.form.DateTimeField.js ~~~ Ext.ns('Ext.ux.form'); Ext.ux.form.TimePickerField = function(config){ Ext.ux.form.TimePickerField.superclass.constructor.call(this, config); } Ext.extend(Ext.ux.form.TimePickerField, Ext.form.Field, { defaultAutoCreate: { tag: 'div' }, cls: 'x-form-timepickerfield', hoursSpinner: null, minutesSpinner: null, secondsSpinner: null, spinnerCfg: { width: 40 }, spinnerFixBoundries: function(value){ if (value < this.field.minValue) { value = this.field.maxValue; } if (value > this.field.maxValue) { value = this.field.minValue; } return this.fixPrecision(value); }, onRender: function(ct, position){ Ext.ux.form.TimePickerField.superclass.onRender.call(this, ct, position); this.rendered = false; this.date = new Date(); var values = {}; if (this.value) { values = this._valueSplit(this.value); this.date.setHours(values.h); this.date.setMinutes(values.m); this.date.setSeconds(values.s); delete this.value; } else { values = { h: this.date.getHours(), m: this.date.getMinutes(), s: this.date.getSeconds() }; } var spinnerWrap = Ext.DomHelper.append(this.el, { tag: 'div' }); var cfg = Ext.apply({}, this.spinnerCfg, { renderTo: spinnerWrap, readOnly: this.readOnly, disabled: this.disabled, listeners: { spin: { fn: this.onSpinnerChange, scope: this }, valid: { fn: this.onSpinnerChange, scope: this }, afterrender: { fn: function(spinner){ spinner.wrap.applyStyles('float: left'); }, single: true } } }); this.hoursSpinner = new Ext.ux.form.SpinnerField(Ext.apply({}, cfg, { minValue: 0, maxValue: 23, cls: 'first', value: values.h })); this.minutesSpinner = new Ext.ux.form.SpinnerField(Ext.apply({}, cfg, { minValue: 0, maxValue: 59, value: values.m })); this.secondsSpinner = new Ext.ux.form.SpinnerField(Ext.apply({}, cfg, { minValue: 0, maxValue: 59, value: values.s })); Ext.DomHelper.append(spinnerWrap, { tag: 'div', cls: 'x-form-clear-left' }); this.rendered = true; }, _valueSplit: function(v){ var split = v.split(':'); return { h: split.length > 0 ? split[0] : 0, m: split.length > 1 ? split[1] : 0, s: split.length > 2 ? split[2] : 0 }; }, onSpinnerChange: function(){ if (!this.rendered) { return; } this.fireEvent('change', this, this.getRawValue()); }, disable: function(){ Ext.ux.form.TimePickerField.superclass.disable.call(this); this.hoursSpinner.disable(); this.minutesSpinner.disable(); this.secondsSpinner.disable(); }, enable: function(){ Ext.ux.form.TimePickerField.superclass.enable.call(this); this.hoursSpinner.enable(); this.minutesSpinner.enable(); this.secondsSpinner.enable(); }, setReadOnly: function(r){ Ext.ux.form.TimePickerField.superclass.setReadOnly.call(this, r); this.hoursSpinner.setReadOnly(r); this.minutesSpinner.setReadOnly(r); this.secondsSpinner.setReadOnly(r); }, clearInvalid: function(){ Ext.ux.form.TimePickerField.superclass.clearInvalid.call(this); this.hoursSpinner.clearInvalid(); this.minutesSpinner.clearInvalid(); this.secondsSpinner.clearInvalid(); }, getRawValue: function(){ if (!this.hoursSpinner) { this.date = new Date(); return { h: this.date.getHours(), m: this.date.getMinutes(), s: this.date.getSeconds() }; } else { return { h: this.hoursSpinner.getValue(), m: this.minutesSpinner.getValue(), s: this.secondsSpinner.getValue() }; } }, setRawValue: function(v){ this.hoursSpinner.setValue(v.h); this.minutesSpinner.setValue(v.m); this.secondsSpinner.setValue(v.s); }, isValid: function(preventMark){ return this.hoursSpinner.isValid(preventMark) && this.minutesSpinner.isValid(preventMark) && this.secondsSpinner.isValid(preventMark); }, validate: function(){ return this.hoursSpinner.validate() && this.minutesSpinner.validate() && this.secondsSpinner.validate(); }, getValue: function(){ var v = this.getRawValue(); return String.leftPad(v.h, 2, '0') + ':' + String.leftPad(v.m, 2, '0') + ':' + String.leftPad(v.s, 2, '0'); }, setValue: function(value){ if (!this.rendered) { this.value = value; return; } value = this._valueSplit(value); this.setRawValue(value); this.validate(); } }); Ext.form.TimePickerField = Ext.ux.form.TimePickerField; Ext.reg('timepickerfield', Ext.form.TimePickerField); Ext.ns('Ext.ux.form'); Ext.DateTimePicker = Ext.extend(Ext.DatePicker, { timeFormat: 'g:i:s A', timeLabel: '时间', timeWidth: 100, initComponent: function(){ Ext.DateTimePicker.superclass.initComponent.call(this); this.id = Ext.id(); }, onRender: function(container, position){ Ext.DateTimePicker.superclass.onRender.apply(this, arguments); var table = Ext.get(Ext.DomQuery.selectNode('table tbody', container.dom)); var tfEl = Ext.DomHelper.insertBefore(table.last(), { tag: 'tr', children: [{ tag: 'td', cls: 'x-date-bottom', html: this.timeLabel, style: 'width:30;' }, { tag: 'td', cls: 'x-date-bottom ux-timefield', style: "height: 20px;", colspan: '2' }] }, true); this.tf.render(table.child('td.ux-timefield')); var p = this.getEl().parent('div.x-layer'); if (p) { p.setStyle("height", p.getHeight() + 31); } }, setValue: function(value){ var old = this.value; if (!this.tf) { this.tf = new Ext.ux.form.TimePickerField(); this.tf.ownerCt = this; } this.value = this.getDateTime(value); }, getDateTime: function(value){ if (this.tf) { var dt = new Date(); var timeval = this.tf.getValue(); value = Date.parseDate(value.format(this.dateFormat) + ' ' + this.tf.getValue(), this.format); } return value; }, selectToday: function(){ if (this.todayBtn && !this.todayBtn.disabled) { this.value = this.getDateTime(new Date()); this.fireEvent("select", this, this.value); } } }); Ext.reg('datetimepickerfield', Ext.DateTimePicker); if (parseInt(Ext.version.substr(0, 1), 10) > 2) { Ext.menu.DateTimeItem = Ext.DateTimePicker; Ext.override(Ext.menu.DateMenu, { initComponent: function(){ this.on('beforeshow', this.onBeforeShow, this); if (this.strict = (Ext.isIE7 && Ext.isStrict)) { this.on('show', this.onShow, this, { single: true, delay: 20 }); } Ext.apply(this, { plain: true, showSeparator: false, items: this.picker = new Ext.DatePicker(Ext.apply({ internalRender: this.strict || !Ext.isIE, ctCls: 'x-menu-date-item' }, this.initialConfig)) }); Ext.menu.DateMenu.superclass.initComponent.call(this); this.relayEvents(this.picker, ["select"]); this.on('select', this.menuHide, this); if (this.handler) { this.on('select', this.handler, this.scope || this); } } }); } else { Ext.menu.DateTimeItem = function(config){ Ext.menu.DateTimeItem.superclass.constructor.call(this, new Ext.DateTimePicker(config), config); this.picker = this.component; alert(this.picker); this.addEvents('select'); this.picker.on("render", function(picker){ picker.getEl().swallowEvent("click"); picker.container.addClass("x-menu-date-item"); }); this.picker.on("select", this.onSelect, this); }; Ext.extend(Ext.menu.DateTimeItem, Ext.menu.DateMenu, { onSelect: function(picker, date){ this.fireEvent("select", this, date, picker); Ext.menu.DateTimeItem.superclass.handleClick.call(this); } }); } Ext.menu.DateTimeMenu = function(config){ Ext.menu.DateTimeMenu.superclass.constructor.call(this, config); this.plain = true; var di = new Ext.menu.DateTimeItem(config); this.add(di); this.picker = di; this.relayEvents(di, ["select"]); this.on('beforeshow', function(){ if (this.picker) { this.picker.hideMonthPicker(true); } }, this); }; Ext.extend(Ext.menu.DateTimeMenu, Ext.menu.Menu, { cls: 'x-date-menu', beforeDestroy: function(){ this.picker.destroy(); }, hide: function(deep){ if (this.picker.tf.innerList) { if ((Ext.EventObject.within(this.picker.tf.innerList)) || (Ext.get(Ext.EventObject.getTarget()) == this.picker.tf.innerList)) return false; } if (this.el && this.isVisible()) { this.fireEvent("beforehide", this); if (this.activeItem) { this.activeItem.deactivate(); this.activeItem = null; } this.el.hide(); this.hidden = true; this.fireEvent("hide", this); } if (deep === true && this.parentMenu) { this.parentMenu.hide(true); } } }); Ext.ux.form.DateTimeField = Ext.extend(Ext.form.DateField, { dateFormat: 'Y-m-d', timeFormat: 'H:i:s', defaultAutoCreate: { tag: "input", type: "text", size: "20", autocomplete: "off" }, initComponent: function(){ Ext.ux.form.DateTimeField.superclass.initComponent.call(this); this.format = this.dateFormat + ' ' + this.timeFormat; this.afterMethod('afterRender', function(){ this.getEl().applyStyles('top:0'); }); }, getValue: function(){ return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || ''; }, onTriggerClick: function(){ if (this.disabled) { return; } if (this.menu == null) { this.menu = new Ext.menu.DateTimeMenu(); } Ext.apply(this.menu.picker, { minDate: this.minValue, maxDate: this.maxValue, disabledDatesRE: this.ddMatch, disabledDatesText: this.disabledDatesText, disabledDays: this.disabledDays, disabledDaysText: this.disabledDaysText, format: this.format, timeFormat: this.timeFormat, dateFormat: this.dateFormat, showToday: this.showToday, minText: String.format(this.minText, this.formatDate(this.minValue)), maxText: String.format(this.maxText, this.formatDate(this.maxValue)) }); if (this.menuEvents) { this.menuEvents('on'); } else { this.menu.on(Ext.apply({}, this.menuListeners, { scope: this })); } this.menu.picker.setValue(this.getValue() || new Date()); this.menu.show(this.el, "tl-bl?"); } }); Ext.reg('datetimefield', Ext.ux.form.DateTimeField); ~~~ Ext.hoo.form.DateTimeField.js ~~~ /** * @function 可以选择日期的DateTimeField * @auhor: hoojo * @createDate: Sep 16, 2010 9:25:12 PM * @blog: blog.csdn.net/IBM_hoojo * @email: hoojo_@126.com * @class Ext.hoo.form.DateTimeField * @extends Ext.ux.form.DateTimeField */ Ext.ns("Ext.hoo.form"); Ext.hoo.form.DateTimeField = Ext.extend(Ext.ux.form.DateTimeField, { constructor: function () { Ext.hoo.form.DateTimeField.superclass.constructor.call(this, { renderTo: "show", height: 222, dateFormat: 'Y-m-d', timeFormat: 'H:i:s', listeners: { select: function () { alert(this.getValue() + "##" + this.getRawValue()); } } }); } }); Ext.onReady(function () { Ext.BLANK_IMAGE_URL = "../ext2/resources/images/default/s.gif"; Ext.QuickTips.init(); Ext.form.Field.prototype.msgTarget = "qtip"; new Ext.hoo.form.DateTimeField(); }); ~~~ ### 三、带图标的下列列表 效果图如下 ![](https://box.kancloud.cn/2016-04-01_56fe122a8a7fa.gif) 需要的文件 combo_icon.gif iconCombobox 插件文件: Ext.ux.IconCombo.js 示例文件: Ext.hoo.form.WebBroserIconComboBox.js   代码如下 ~~~ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>form Component -- iconCombo</title> <meta http-equiv="pragma" content="no-cache"/> <meta http-equiv="cache-control" content="no-cache"/> <meta http-equiv="expires" content="0"/> <meta http-equiv="content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="author" content="hoojo"/> <meta http-equiv="email" content="hoojo_@126.com"/> <meta http-equiv="ext-lib" content="version 2.2"/> <meta http-equiv="blog" content="http://blog.csdn.net/IBM_hoojo"/> <link rel="stylesheet" type="text/css" href="../ext2/resources/css/ext-all.css"/> <link rel="stylesheet" type="text/css" href="../css/iconCombo.css"/> <style type="text/css"> .ffCls { background: url(../images/combo_icon.gif) no-repeat 1px -15px; } .ieCls { background: url(../images/combo_icon.gif) no-repeat 1px 2px; } .operaCls { background: url(../images/combo_icon.gif) no-repeat 1px -68px; } .chromeCls { background: url(../images/combo_icon.gif) no-repeat 1px -85px; } .maxCls { background: url(../images/combo_icon.gif) no-repeat 1px -32px; } .ttCls { background: url(../images/combo_icon.gif) no-repeat 1px -50px; } .sfCls { background: url(../images/combo_icon.gif) no-repeat 1px -103px; } .twCls { background: url(../images/combo_icon.gif) no-repeat 1px -121px; } .flockCls { background: url(../images/combo_icon.gif) no-repeat 1px -139px; } </style> <script type="text/javascript" src="../ext2/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext2/ext-all.js"></script> <script type="text/javascript" src="../ext2/build/locale/ext-lang-zh_CN-min.js"></script> <script type="text/javascript" src="Ext.ux.IconCombo.js"></script> <script type="text/javascript" src="Ext.hoo.form.WebBroserIconComboBox.js"></script> </head> <body> <div id="show" style="padding: 100px 0 0 300px;"></div> </body> </html> ~~~   Ext.ux.IconCombo.js 文件代码 ~~~ /** * @class Ext.ux.IconCombo * @extends Ext.form.ComboBox * @param {Object} config Configuration options */ Ext.ux.IconCombo = function(config) { // call parent constructor Ext.ux.IconCombo.superclass.constructor.call(this, config); this.tpl = config.tpl || '<tpl for="."><div class="x-combo-list-item">' + '<table><tbody><tr>' + '<td>' + '<div class="{' + this.iconClsField + '}"></div></td>' + '<td>{' + this.displayField + '}</td>' + '</tr></tbody></table>' + '</div></tpl>'; }; Ext.extend(Ext.ux.IconCombo, Ext.form.ComboBox, { defaultIconCls: "ux-icon-combo-icon", emptyText: "plase selected", setIconCls : function() { var record = this.store.query(this.valueField, this.getValue()).itemAt(0); if (record) { this.flag.className = record.get(this.iconClsField) || defaultIconCls || "ux-icon-combo-icon"; //this.flag.style.backgroundImage = rec.get(this.iconClsField); } }, setValue : function(value) { Ext.ux.IconCombo.superclass.setValue.call(this, value); this.setIconCls(); }, onRender: function(ct, position) { Ext.ux.IconCombo.superclass.onRender.call(this, ct, position); var wrap = this.el.up("div.x-form-field-wrap"); this.wrap.applyStyles({ position : "relative" }); this.el.addClass("ux-icon-combo-input"); //textfield中显示的图片div this.flag = Ext.DomHelper.append(wrap, { tag : "div", style : "position:absolute; left: 5px; top: 1px;" }); //默认图片样式 this.flag.className = this.defaultIconCls; } }); ~~~ Ext.hoo.form.WebBroserIconComboBox.js ~~~ /** * @function 带图片的combobox * @auhor: hoojo * @createDate: Sep 10, 2010 11:16:12 PM * @blog: blog.csdn.net/IBM_hoojo * @email: hoojo_@126.com * @class Ext.hoo.form.WebBroserIconComboBox * @extends Ext.ux.IconCombo */ Ext.ns("Ext.hoo.form"); Ext.hoo.form.WebBroserIconComboBox = Ext.extend(Ext.ux.IconCombo, { constructor: function () { Ext.hoo.form.WebBroserIconComboBox.superclass.constructor.call(this, { /*fieldLabel: "web broser type", labelWidth: 73,*/ renderTo: /*Ext.getBody(),*/"show", width: 200, store: new Ext.data.SimpleStore({ fields: ["shortName", "name", "iconCls"], data: [ ["ff", "Mozilla Firefox" , "ffCls"], ["IE", "Internet Explorer" , "IECls"], ["opera", "Opera" , "operaCls"], ["chrome", "Google Chrome" , "chromeCls"], ["max", "Maxthon" , "maxCls"], ["tt", "TecentTraveler" , "ttCls"], ["sf", "Safari" , "sfCls"], ["tw", "TheWorld" , "twCls"], ["flock", "Flock" , "flockCls"] ] }), valueField: "shortName", displayField: "name", iconClsField: "iconCls", triggerAction: "all", editable: false, mode: "local" }); this.on("select", function (field, e) { alert(field.getValue() + "###" + field.getRawValue()); }, this); } }); Ext.onReady(function () { Ext.BLANK_IMAGE_URL = "../ext2/resources/images/default/s.gif"; Ext.QuickTips.init(); Ext.form.Field.prototype.msgTarget = "qtip"; new Ext.hoo.form.WebBroserIconComboBox(); }); ~~~ ### 四、多选下列列表组件 可以同时选择多个选项 ![](https://box.kancloud.cn/2016-04-01_56fe122aab618.gif) 核心文件 多选下拉列表组件:Ext.form.MultiComboBox.js 示例文件:Ext.hoo.form.InterestMultiComboBox.js   代码如下 ~~~ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>form Component -- MultiComboBox</title> <meta http-equiv="pragma" content="no-cache"/> <meta http-equiv="cache-control" content="no-cache"/> <meta http-equiv="expires" content="0"/> <meta http-equiv="content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="author" content="hoojo"/> <meta http-equiv="email" content="hoojo_@126.com"/> <meta http-equiv="ext-lib" content="version 2.2"/> <meta http-equiv="blog" content="http://blog.csdn.net/IBM_hoojo"/> <link rel="stylesheet" type="text/css" href="../ext2/resources/css/ext-all.css"/> <style type="text/css"> .checked{ background-image: url("../ext2/resources/images/default/menu/checked.gif"); } .unchecked{ background-image: url("../ext2/resources/images/default/menu/unchecked.gif"); } .x-combo-list-item { line-height: 18px; } </style> <script type="text/javascript" src="../ext2/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext2/ext-all.js"></script> <script type="text/javascript" src="../ext2/build/locale/ext-lang-zh_CN-min.js"></script> <script type="text/javascript" src="Ext.form.MultiComboBox.js"></script> <script type="text/javascript" src="Ext.hoo.form.InterestMultiComboBox.js"></script> </head> <body> <center> <div id="show" style="padding-top: 200px;"></div> </center> </body> </html> ~~~   Ext.form.MultiComboBox.js ~~~ Ext.form.MultiComboBox = Ext.extend(Ext.form.TriggerField, { defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"}, listClass: '', selectedClass: 'x-combo-selected', triggerClass : 'x-form-arrow-trigger', shadow:'sides', listAlign: 'tl-bl?', maxHeight: 300, triggerAction: 'query', minChars : 4, typeAhead: false, queryDelay: 500, pageSize: 0, selectOnFocus: false, queryParam: 'query', loadingText: 'Loading...', resizable: false, handleHeight : 8, editable: true, allQuery: '', mode: 'remote', minListWidth : 70, forceSelection:false, typeAheadDelay : 250, displaySeparator:';', valueSeparator:',', lazyInit : true, initComponent : function(){ Ext.form.ComboBox.superclass.initComponent.call(this); this.addEvents( 'expand', 'collapse', 'beforeselect', 'select', 'beforequery' ); if(this.transform){ this.allowDomMove = false; var s = Ext.getDom(this.transform); if(!this.hiddenName){ this.hiddenName = s.name; } if(!this.store){ this.mode = 'local'; var d = [], opts = s.options; for(var i = 0, len = opts.length;i < len; i++){ var o = opts[i]; var value = (Ext.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text; if(o.selected) { this.value = value; } d.push([value, o.text]); } this.store = new Ext.data.SimpleStore({ 'id': 0, fields: ['value', 'text'], data : d }); this.valueField = 'value'; this.displayField = 'text'; } s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference if(!this.lazyRender){ this.target = true; this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate); Ext.removeNode(s); // remove it this.render(this.el.parentNode); }else{ Ext.removeNode(s); // remove it } } this.selectedIndex = -1; if(this.mode == 'local'){ if(this.initialConfig.queryDelay === undefined){ this.queryDelay = 10; } if(this.initialConfig.minChars === undefined){ this.minChars = 0; } } }, // private onRender : function(ct, position){ Ext.form.ComboBox.superclass.onRender.call(this, ct, position); var disValue=""; if(this.hiddenName){ this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)}, 'before', true); var hvalue=this.hiddenValue !== undefined ? this.hiddenValue : this.value !== undefined ? this.value : ''; var hvalueArray=hvalue.split(this.valueSeparator); for(var i=0;i<this.store.data.length;i++){ var r = this.store.getAt(i); var newValue = r.data[this.displayField]; var v=r.data[this.valueField]; for(var j=0;j<hvalueArray.length;j++){ if(hvalueArray[j]==v){ disValue+=newValue+this.displaySeparator; } } } this.hiddenField.value =this.hiddenValue !== undefined ? this.hiddenValue : this.value !== undefined ? this.value : ''; this.el.dom.removeAttribute('name'); } if(Ext.isGecko){ this.el.dom.setAttribute('autocomplete', 'off'); } if(!this.lazyInit){ this.initList(); }else{ this.on('focus', this.initList, this, {single: true}); } if(!this.editable){ this.editable = true; this.setEditable(false); } this.setValue(disValue); }, initList : function(){ if(!this.list){ var cls = 'x-combo-list'; this.list = new Ext.Layer({ shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false }); var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth); this.list.setWidth(lw); this.list.swallowEvent('mousewheel'); this.assetHeight = 0; if(this.title){ this.header = this.list.createChild({cls:cls+'-hd', html: this.title}); this.assetHeight += this.header.getHeight(); } this.innerList = this.list.createChild({cls:cls+'-inner'}); this.innerList.on('mouseover', this.onViewOver, this); this.innerList.on('mousemove', this.onViewMove, this); this.innerList.setWidth(lw - this.list.getFrameWidth('lr')) if(this.pageSize){ this.footer = this.list.createChild({cls:cls+'-ft'}); this.pageTb = new Ext.PagingToolbar({ store:this.store, pageSize: this.pageSize, renderTo:this.footer }); this.assetHeight += this.footer.getHeight(); } if(!this.tpl){ //alert(cls); //x-combo-list-item this.tpl = '<tpl for="."><div class="'+cls+'-item"><span class="unchecked" style="padding-bottom: 1px;" id="checkBox_{' + this.displayField + '}">    </span>{' + this.displayField + '}</div></tpl>'; } this.view = new Ext.DataView({ applyTo: this.innerList, tpl: this.tpl, singleSelect: true, selectedClass: this.selectedClass, itemSelector: this.itemSelector || '.' + cls + '-item' }); this.view.on('click', this.onViewClick, this); this.bindStore(this.store, true); if(this.resizable){ this.resizer = new Ext.Resizable(this.list, { pinned:true, handles:'se' }); this.resizer.on('resize', function(r, w, h){ this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight; this.listWidth = w; this.innerList.setWidth(w - this.list.getFrameWidth('lr')); this.restrictHeight(); }, this); this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px'); } } }, bindStore : function(store, initial){ if(this.store && !initial){ this.store.un('beforeload', this.onBeforeLoad, this); this.store.un('load', this.onLoad, this); this.store.un('loadexception', this.collapse, this); if(!store){ this.store = null; if(this.view){ this.view.setStore(null); } } } if(store){ this.store = Ext.StoreMgr.lookup(store); this.store.on('beforeload', this.onBeforeLoad, this); this.store.on('load', this.onLoad, this); this.store.on('loadexception', this.collapse, this); if(this.view){ this.view.setStore(store); } } }, // private initEvents : function(){ Ext.form.ComboBox.superclass.initEvents.call(this); this.keyNav = new Ext.KeyNav(this.el, { "up" : function(e){ this.inKeyMode = true; this.selectPrev(); }, "down" : function(e){ if(!this.isExpanded()){ this.onTriggerClick(); }else{ this.inKeyMode = true; this.selectNext(); } }, "enter" : function(e){ this.onViewClick(); //return true; }, "esc" : function(e){ this.collapse(); }, "tab" : function(e){ this.onViewClick(false); return true; }, scope : this, doRelay : function(foo, bar, hname){ if(hname == 'down' || this.scope.isExpanded()){ return Ext.KeyNav.prototype.doRelay.apply(this, arguments); } return true; }, forceKeyDown : true }); this.queryDelay = Math.max(this.queryDelay || 10, this.mode == 'local' ? 10 : 250); this.dqTask = new Ext.util.DelayedTask(this.initQuery, this); if(this.typeAhead){ this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this); } if(this.editable !== false){ this.el.on("keyup", this.onKeyUp, this); } if(this.forceSelection){ this.on('blur', this.doForce, this); } }, onDestroy : function(){ if(this.view){ this.view.el.removeAllListeners(); this.view.el.remove(); this.view.purgeListeners(); } if(this.list){ this.list.destroy(); } this.bindStore(null); Ext.form.ComboBox.superclass.onDestroy.call(this); }, // private fireKey : function(e){ if(e.isNavKeyPress() && !this.list.isVisible()){ this.fireEvent("specialkey", this, e); } }, // private onResize: function(w, h){ Ext.form.ComboBox.superclass.onResize.apply(this, arguments); if(this.list && this.listWidth === undefined){ var lw = Math.max(w, this.minListWidth); this.list.setWidth(lw); this.innerList.setWidth(lw - this.list.getFrameWidth('lr')); } }, // private onDisable: function(){ Ext.form.ComboBox.superclass.onDisable.apply(this, arguments); if(this.hiddenField){ this.hiddenField.disabled = this.disabled; } }, setEditable : function(value){ if(value == this.editable){ return; } this.editable = value; if(!value){ this.el.dom.setAttribute('readOnly', true); this.el.on('mousedown', this.onTriggerClick, this); this.el.addClass('x-combo-noedit'); }else{ this.el.dom.setAttribute('readOnly', false); this.el.un('mousedown', this.onTriggerClick, this); this.el.removeClass('x-combo-noedit'); } }, // private onBeforeLoad : function(){ if(!this.hasFocus){ return; } this.innerList.update(this.loadingText ? '<div class="loading-indicator">'+this.loadingText+'</div>' : ''); this.restrictHeight(); this.selectedIndex = -1; }, // private onLoad : function(){ if(!this.hasFocus){ return; } if(this.store.getCount() > 0){ this.expand(); this.restrictHeight(); if(this.lastQuery == this.allQuery){ if(this.editable){ this.el.dom.select(); } if(!this.selectByValue(this.value, true)){ this.select(0, true); } }else{ this.selectNext(); if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){ this.taTask.delay(this.typeAheadDelay); } } }else{ this.onEmptyResults(); } }, // private onTypeAhead : function(){ if(this.store.getCount() > 0){ var r = this.store.getAt(0); var newValue = r.data[this.displayField]; var len = newValue.length; var selStart = this.getRawValue().length; if(selStart != len){ this.setRawValue(newValue); this.selectText(selStart, newValue.length); } } }, // private onSelect : function(record, index){ if(this.fireEvent('beforeselect', this, record, index) !== false){ var r = this.store.getAt(index); var newValue = r.data[this.displayField]; var check=document.getElementById("checkBox_"+newValue); if(check.className=="checked"){ check.className="unchecked" }else{ check.className="checked" } var value=""; var hiddenValue=""; for(var i=0;i<this.store.data.length;i++){ var r = this.store.getAt(i); newValue = r.data[this.displayField]; check=document.getElementById("checkBox_"+newValue); if(check.className=="checked"){ value+= r.data[this.displayField]+this.displaySeparator; hiddenValue+= r.data[this.valueField]+this.valueSeparator; } } if(value.length>1){ value=value.substring(0,value.length-this.displaySeparator.length); } if(hiddenValue.length>1){ hiddenValue=hiddenValue.substring(0,value.length-this.valueSeparator.length); } this.setValue(value); this.hiddenField.value=hiddenValue; this.fireEvent('select', this, record, index); } }, getValue : function(){ if(this.valueField){ return typeof this.value != 'undefined' ? this.value : ''; }else{ return Ext.form.ComboBox.superclass.getValue.call(this); } }, /** * Clears any text/value currently set in the field */ clearValue : function(){ if(this.hiddenField){ this.hiddenField.value = ''; } this.setRawValue(''); this.lastSelectionText = ''; this.applyEmptyText(); }, setValue : function(v){ var text = v; if(this.valueField){ var r = this.findRecord(this.valueField, v); if(r){ text = r.data[this.displayField]; }else if(this.valueNotFoundText !== undefined){ text = this.valueNotFoundText; } } this.lastSelectionText = text; Ext.form.ComboBox.superclass.setValue.call(this, text); this.value = v; }, // private findRecord : function(prop, value){ var record; if(this.store.getCount() > 0){ this.store.each(function(r){ if(r.data[prop] == value){ record = r; return false; } }); } return record; }, // private onViewMove : function(e, t){ this.inKeyMode = false; }, // private onViewOver : function(e, t){ if(this.inKeyMode){ // prevent key nav and mouse over conflicts return; } var item = this.view.findItemFromChild(t); if(item){ var index = this.view.indexOf(item); this.select(index, false); } }, // private onViewClick : function(doFocus){ var index = this.view.getSelectedIndexes()[0]; var r = this.store.getAt(index); if(r){ this.onSelect(r, index); } if(doFocus !== false){ this.el.focus(); } }, // private restrictHeight : function(){ this.innerList.dom.style.height = ''; var inner = this.innerList.dom; var fw = this.list.getFrameWidth('tb'); var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight); this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight); this.list.beginUpdate(); this.list.setHeight(this.innerList.getHeight()+fw+(this.resizable?this.handleHeight:0)+this.assetHeight); this.list.alignTo(this.el, this.listAlign); this.list.endUpdate(); }, // private onEmptyResults : function(){ this.collapse(); }, /** * Returns true if the dropdown list is expanded, else false. */ isExpanded : function(){ return this.list && this.list.isVisible(); }, selectByValue : function(v, scrollIntoView){ if(v !== undefined && v !== null){ var r = this.findRecord(this.valueField || this.displayField, v); if(r){ this.select(this.store.indexOf(r), scrollIntoView); return true; } } return false; }, select : function(index, scrollIntoView){ this.selectedIndex = index; this.view.select(index); if(scrollIntoView !== false){ var el = this.view.getNode(index); if(el){ this.innerList.scrollChildIntoView(el, false); } } }, // private selectNext : function(){ var ct = this.store.getCount(); if(ct > 0){ if(this.selectedIndex == -1){ this.select(0); }else if(this.selectedIndex < ct-1){ this.select(this.selectedIndex+1); } } }, // private selectPrev : function(){ var ct = this.store.getCount(); if(ct > 0){ if(this.selectedIndex == -1){ this.select(0); }else if(this.selectedIndex != 0){ this.select(this.selectedIndex-1); } } }, // private onKeyUp : function(e){ if(this.editable !== false && !e.isSpecialKey()){ this.lastKey = e.getKey(); this.dqTask.delay(this.queryDelay); } }, // private validateBlur : function(){ return !this.list || !this.list.isVisible(); }, // private initQuery : function(){ this.doQuery(this.getRawValue()); }, // private doForce : function(){ if(this.el.dom.value.length > 0){ this.el.dom.value = this.lastSelectionText === undefined ? '' : this.lastSelectionText; this.applyEmptyText(); } }, doQuery : function(q, forceAll){ if(q === undefined || q === null){ q = ''; } var qe = { query: q, forceAll: forceAll, combo: this, cancel:false }; if(this.fireEvent('beforequery', qe)===false || qe.cancel){ return false; } q = qe.query; forceAll = qe.forceAll; if(forceAll === true || (q.length >= this.minChars)){ if(this.lastQuery !== q){ this.lastQuery = q; if(this.mode == 'local'){ this.selectedIndex = -1; if(forceAll){ this.store.clearFilter(); }else{ this.store.filter(this.displayField, q); } this.onLoad(); }else{ this.store.baseParams[this.queryParam] = q; this.store.load({ params: this.getParams(q) }); this.expand(); } }else{ this.selectedIndex = -1; this.onLoad(); } } }, // private getParams : function(q){ var p = {}; //p[this.queryParam] = q; if(this.pageSize){ p.start = 0; p.limit = this.pageSize; } return p; }, /** * Hides the dropdown list if it is currently expanded. Fires the 'collapse' event on completion. */ collapse : function(){ if(!this.isExpanded()){ return; } this.list.hide(); Ext.getDoc().un('mousewheel', this.collapseIf, this); Ext.getDoc().un('mousedown', this.collapseIf, this); this.fireEvent('collapse', this); }, // private collapseIf : function(e){ if(!e.within(this.wrap) && !e.within(this.list)){ this.collapse(); } }, /** * Expands the dropdown list if it is currently hidden. Fires the 'expand' event on completion. */ expand : function(){ if(this.isExpanded() || !this.hasFocus){ return; } this.list.alignTo(this.wrap, this.listAlign); var hvalueArray=this.hiddenField.value.split(this.valueSeparator); for(var i=0;i<this.store.data.length;i++){ var r = this.store.getAt(i); var newValue = r.data[this.displayField]; var v=r.data[this.valueField]; for(var j=0;j<hvalueArray.length;j++){ if(hvalueArray[j]==v){ document.getElementById("checkBox_"+newValue).className="checked"; } } } this.list.show(); Ext.getDoc().on('mousewheel', this.collapseIf, this); Ext.getDoc().on('mousedown', this.collapseIf, this); this.fireEvent('expand', this); }, // private // Implements the default empty TriggerField.onTriggerClick function onTriggerClick : function(){ if(this.disabled){ return; } if(this.isExpanded()){ this.collapse(); this.el.focus(); }else { this.onFocus({}); if(this.triggerAction == 'all') { this.doQuery(this.allQuery, true); } else { this.doQuery(this.getRawValue()); } this.el.focus(); } } }); Ext.reg('multicombo', Ext.form.MultiComboBox); ~~~ Ext.hoo.form.InterestMultiComboBox.js ~~~ /** * @function 支持多选的combox * @auhor: hoojo * @createDate: Sep 10, 2010 10:32:00 PM * @blog: blog.csdn.net/IBM_hoojo * @email: hoojo_@126.com * @class Ext.hoo.form.InterestMultiComboBox * @extends Ext.form.MultiComboBox */ Ext.ns("Ext.hoo.form"); Ext.hoo.form.InterestMultiComboBox = Ext.extend(Ext.form.MultiComboBox, { constructor: function () { Ext.hoo.form.InterestMultiComboBox.superclass.constructor.call(this, { renderTo: "show", width: 250, mode: "local", fieldLabel: "多选下拉框", store: new Ext.data.SimpleStore({ fields: ["textAttr", "valueAttr"], data: [ ["打球", "batting"], ["看书", "lookbook"], ["睡觉", "sleeping"], ["购物", "shopping"], ["打游戏", "games"], ["唱歌", "sing"] ] }), editable: true, emptyText:"请选择", //allowBlank: false, valueField: "textAttr", displayField: "valueAttr", labelSeparator: ":", valueSeparator: "#", displaySeparator: ",", //value:"batting,sleeping", hiddenName: "interest", forceSelection: true, triggerAction: "all" }); this.on("select", function (field, record, index) { alert(field.getValue() + "%%%%" + field.getRawValue() + Ext.fly("interest").dom.value); }, this); } }); Ext.onReady(function () { Ext.BLANK_IMAGE_URL = "../ext2/resources/images/default/s.gif"; Ext.QuickTips.init(); Ext.form.Field.prototype.msgTarget = "qtip"; new Ext.hoo.form.InterestMultiComboBox(); }); ~~~ ### 五、动态Combobox Tree(下拉列表树)组件 可以多选、单选、checkbox ![](https://box.kancloud.cn/2016-04-01_56fe122acf8b3.gif) 需要的文件 动态下列列表树插件:Ext.ux.form.DynamicTreeCombox.js 示例文件:Ext.hoo.form.DynaTreeCombo.js 代码如下: ~~~ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>form Component -- MultiComboBox</title> <meta http-equiv="pragma" content="no-cache"/> <meta http-equiv="cache-control" content="no-cache"/> <meta http-equiv="expires" content="0"/> <meta http-equiv="content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="author" content="hoojo"/> <meta http-equiv="email" content="hoojo_@126.com"/> <meta http-equiv="ext-lib" content="version 2.2"/> <meta http-equiv="blog" content="http://blog.csdn.net/IBM_hoojo"/> <link rel="stylesheet" type="text/css" href="../ext2/resources/css/ext-all.css"/> <script type="text/javascript" src="../ext2/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext2/ext-all.js"></script> <script type="text/javascript" src="../ext2/build/locale/ext-lang-zh_CN-min.js"></script> <script type="text/javascript" src="Ext.ux.form.DynamicTreeCombox.js"></script> <script type="text/javascript" src="Ext.hoo.form.DynaTreeCombo.js"></script> </head> <body> <div id="show" style="float: left; margin: 100px 0 0 100px;"></div> <div id="showBasic" style="float: left; margin: 100px 0 0 100px;"></div> <div id="showConstom" style="float: left; margin: 100px 0 0 100px;"></div> </body> </html> ~~~ Ext.ux.form.DynamicTreeCombox.js ~~~ Ext.ns("Ext.ux.form"); Ext.ux.form.DynamicTreeCombox = Ext.extend(Ext.form.ComboBox, { initComponent:function(){ Ext.ux.form.DynamicTreeCombox.superclass.initComponent.call(this); this.addEvents('beforeClickNode','afterClickNode', 'select'); if(!this.tree){ var root = this.root || new Ext.tree.AsyncTreeNode(); this.tree = new Ext.tree.TreePanel({ containerScroll: true, rootVisible: false, border: false, root: root }); this.tree.loader = new Ext.tree.TreeLoader(this.loaderConfig||{dataUrl:"",baseAttrs:{}}); this.tree.loader.addListener("beforeload",this.beforeLoad,this); this.tree.loader.addListener("load",this.onLoad,this); this.tree.addListener('collapsenode',this.onNodeCollapse,this); this.tree.addListener('expandnode',this.onNodeExpand,this); } var fieldMp = { text: "text", qtip: "qtip", parentFuncId: "id", icon: "icon" }; if(!this.fieldMapping){ this.fieldMapping = fieldMp; }else{ Ext.applyIf(this.fieldMapping, fieldMp); } }, initList:function(){ if(!this.list){ var cls = 'x-combo-list'; this.list = new Ext.Layer({ shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false }); var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth); this.list.setWidth(lw); this.list.swallowEvent('mousewheel'); this.innerList = this.list.createChild({cls:cls+'-inner'}); this.innerList.setWidth(lw - this.list.getFrameWidth('lr')); this.innerList.setHeight("100%"); } }, doQuery:function(){ if(this.expandAll){ var loader=this.tree.loader; if(loader.baseAttrs){ Ext.apply(loader.baseAttrs,{expanded:this.expandAll}); }else{ loader.baseAttrs={expanded:this.expandAll}; } } if(!this.tree.rendered){ this.tree.render(this.innerList); this.tree.addListener("click",this.clickNode,this); } this.expand(); }, beforeLoad:function(loader,node){ if(node!=node.getOwnerTree().root){ loader.baseParams.parentFuncId=node.attributes[this.fieldMapping.parentFuncId]; } }, onLoad:function(loader,node,res){ var nodeArr=node.childNodes; for(var i=0,j=nodeArr.length;i<j;i++){ if(nodeArr[i].attributes[this.fieldMapping.icon]){ nodeArr[i].getUI().getIconEl().src=nodeArr[i].attributes[this.fieldMapping.icon]; } nodeArr[i].setText(nodeArr[i].attributes[this.fieldMapping.text]); nodeArr[i].ui.textNode.setAttribute("qtip", nodeArr[i].attributes[this.fieldMapping.qtip]); } }, clickNode:function(node){ if(this.fireEvent('beforeClickNode',this,node)){ this.setValue(node.attributes[this.displayField]); this.value = node.attributes[this.valField || "id"]; } this.fireEvent("afterClickNode",this,node); this.fireEvent("select",this,node); this.collapse(); }, onNodeCollapse:function(node){ this.list.setHeight(this.tree.getEl().getHeight()+2); }, getValue: function () { return this.value; }, onNodeExpand:function(node){ this.list.setHeight(this.tree.getEl().getHeight()+2); }, onDestroy:function(){ if(this.view){ this.view.el.removeAllListeners(); this.view.el.remove(); this.view.purgeListeners(); } if(this.tree.loader){ this.tree.loader.purgeListeners(); } if(this.tree){ this.tree.el.removeAllListerers(); this.tree.el.remove(); this.tree.purgeListeners(); } if(this.innerList){ this.innerList.destroy(); } if(this.list){ this.list.destroy(); } Ext.form.ComboBox.superclass.onDestroy.call(this); } }); Ext.reg("treecombox",Ext.ux.form.DynamicTreeCombox); ~~~ Ext.hoo.form.DynaTreeCombo.js ~~~ /** * @function 动态tree的combobox,本地数据 * @auhor: hoojo * @createDate: Sep 11, 2010 6:33:13 PM * @blog: blog.csdn.net/IBM_hoojo * @email: hoojo_@126.com * @class Ext.hoo.form.DynaTreeCombo * @extends Ext.ux.form.DynamicTreeCombox */ Ext.ns("Ext.hoo.form"); Ext.hoo.form.DynaTreeCombo = Ext.extend(Ext.ux.form.DynamicTreeCombox, { constructor: function () { Ext.hoo.form.DynaTreeCombo.superclass.constructor.call(this, { renderTo: "show", expandAll: false, readOnly: true, width: 200, displayField: "text", valField: "id", root: new Ext.tree.AsyncTreeNode({ text: "ExtJS", id: "0", children: [{ text: "adpter", qtip: "这是一个adpter的tip", children: [{ text: "ext", leaf: true, qtip: "这是一个ext的tip", checked: true },{ text: "yui", leaf: true },{ text: "jquery", leaf: true },{ text: "prototype", leaf: true, checked: false }] },{ text: "air", checked: false, children: [{ text: "air.jsb", leaf: true },{ text: "ext-air.js", leaf: true }] },{ text: "docs" }] }) }); this.on("select", function (field, node) { alert(field.getValue() + "###" + field.getRawValue() + "##" + node.text); }, this); this.on("check", function (field, node) { alert(field.getValue() + "###" + field.getRawValue() + "##" + node.text); }, this); } }); /** * @function DynamicTreeCombox 后台数据 * @auhor: hoojo * @createDate: Sep 11, 2010 10:30:27 PM * @blog: blog.csdn.net/IBM_hoojo * @email: hoojo_@126.com */ Ext.hoo.form.AsyncBasicDynaTreeCombo = Ext.extend(Ext.ux.form.DynamicTreeCombox, { constructor: function () { Ext.hoo.form.AsyncBasicDynaTreeCombo.superclass.constructor.call(this, { renderTo: "showBasic", expandAll: false, readOnly: true, width: 200, displayField: "text", valField: "id", loaderConfig:{ dataUrl: "../ServiceDataServlet?method=basic"//加载树的URL } }); this.on("select", function (field, node) { alert(field.getValue() + "###" + field.getRawValue() + "##" + node.text); }, this); } }); /** * @function 后台数据 * @auhor: hoojo * @createDate: Sep 11, 2010 10:30:59 PM * @blog: blog.csdn.net/IBM_hoojo * @email: hoojo_@126.com */ Ext.hoo.form.AsyncConstomDynaTreeCombo = Ext.extend(Ext.ux.form.DynamicTreeCombox, { constructor: function () { Ext.hoo.form.AsyncConstomDynaTreeCombo.superclass.constructor.call(this, { renderTo: "showConstom", expandAll: false, readOnly: true, width: 200, displayField: "text", valField: "id", loaderConfig:{ dataUrl: "../ServiceDataServlet?method=constom", baseParams:{parentFuncId:""}//如果传递parentFuncId就会查询当前id下的节点 }, //后台数据中没有text、qtip、icon、parentFuncId属性,需加上fieldMapping进行属性映射,如果后台返回数据中有此属性可省略 fieldMapping: { text: "text",//映射node的text字段 qtip: "tip",//映射node的qtip字段 parentFuncId: "text"//映射动态请求后台的text属性作为请求参数 //icon: "img" } }); this.on("select", function (field, node) { alert(field.getValue() + "###" + field.getRawValue() + "##" + node.text); }, this); } }); Ext.onReady(function () { Ext.BLANK_IMAGE_URL = "../ext2/resources/images/default/s.gif"; Ext.QuickTips.init(); Ext.form.Field.prototype.msgTarget = "qtip"; new Ext.hoo.form.DynaTreeCombo(); new Ext.hoo.form.AsyncBasicDynaTreeCombo(); new Ext.hoo.form.AsyncConstomDynaTreeCombo(); }); ~~~ ServiceDataServlet.java ~~~ package com.hoo.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServiceDataServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/json"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); String method = request.getParameter("method"); StringBuilder sb = new StringBuilder(); if ("basic".equals(method)) { sb.append("[") .append("{").append("text:\"").append("adpter").append("\", qtip: \"").append("qtip提示:ADPTER").append("\","); sb.append("children: [") .append("{").append("text:\"").append("ext").append("\", qtip: \"").append("qtip提示:ext").append("\",") .append("leaf: true").append("},") .append("{").append("text:\"").append("jquery") .append("\",").append("leaf: true").append("}]").append("},") .append("{").append("text:\"").append("air").append("\","); sb.append("children: [") .append("{").append("text:\"").append("air.jsb") .append("\",").append("leaf: true").append("},") .append("{").append("text:\"").append("ext-air.js") .append("\",").append("leaf: true").append("}]").append("},") .append("{").append("text:\"").append("readMe.text").append("\",") .append("leaf: true}"); sb.append("]"); } if ("constom".equals(method)) { sb.append("[") .append("{").append("text:\"").append("adpter").append("\", tip: \"").append("ADPTER").append("\","); sb.append("children:[") .append("{").append("text:\"").append("ext").append("\", tip: \"").append("EXT").append("\",") .append("leaf: true").append("},") .append("{").append("text:\"").append("jquery").append("\", tip: \"").append("JQUERY").append("\",") .append("leaf: true").append("}]},") .append("{").append("text:\"").append("air").append("\", tip: \"").append("AIR").append("\","); sb.append("children:[") .append("{").append("text:\"").append("air.jsb").append("\", tip: \"").append("AIR.JSB").append("\",") .append("leaf: true").append("},") .append("{").append("text:\"").append("ext-air.js").append("\", tip: \"").append("EXT-AIR.JS").append("\",") .append("leaf: true").append("}]").append("},") .append("{").append("text:\"").append("readMe.text").append("\", tip: \"").append("README.TEXT").append("\",") .append("leaf: true}"); sb.append("]"); } out.print(sb.toString()); out.flush(); out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } } ~~~