/* Chosenbox.js Purpose: Description: History: Tue Nov 16 15:15:52 TST 2011, Created by benbai Copyright (C) 2011 Potix Corporation. All Rights Reserved. This program is distributed under LGPL Version 3.0 in the hope that it will be useful, but WITHOUT ANY WARRANTY. */ (function() { function clearAllData(wgt) { wgt._clearSelection(); wgt._ppMaxHeight = wgt.fixDisplay = wgt._separatorCode = wgt._startOnSearching = wgt._chgSel = wgt.fixInputWidth = null; } function startOnSearching(wgt) { if (!wgt._startOnSearching) wgt._startOnSearching = setTimeout(function() { wgt._fireOnSearching(wgt.$n(('inp')).value); wgt._startOnSearching = null; }, 350); } let Chosenbox = chosenbox.Chosenbox = zk.$extends(zul.Widget, { $init : function(props) { this.$supers('$init', arguments); this._selItems = []; this._separatorCode = []; this._ppMaxHeight = 350; }, $define : { items : function(v) { if (!this._renderByServer) this.setListContent(); }, /** * Returns the tab order of the input of this * component. *

* Default: 0 (means the same as browser's default). * * @return int */ /** * Sets the tab order of the input of this * component. * * @param int * tabindex */ tabindex : function(tabindex) { let n = this.$n('inp'); if (n) n.tabindex = tabindex || ''; }, /** * Returns the index of the selected item (-1 if no * one is selected). * * @return int */ /** * Selects the item with the given index. * * @param int * selectedIndex */ selectedIndex : function(v, opts) { let options, sel; this._clearSelection(); if ((sel = this.$n('sel')) && v >= 0) { options = jq(sel).children(); this._doSelect(this._getItemByIndex(v)); } if (v == -1) this._fixEmptyMessage(true); }, renderByServer : function(v) { if (v && this.$n()) this._clearListContent(); }, /** * Returns whether it is disabled. *

* Default: false. * * @return boolean */ /** * Sets whether it is disabled. * * @param boolean * disabled */ disabled : function(disabled) { let n = this.$n('inp'); if (n) n.disabled = disabled ? 'disabled' : ''; }, /** * Returns the name of the input of this component. *

* Default: null. *

* The name is used only to work with "legacy" Web * application that handles user's request by * servlets. It works only with HTTP/HTML-based * browsers. It doesn't work with other kind of * clients. *

* Don't use this method if your application is * purely based on ZK's event-driven model. * * @return String */ /** * Sets the name of the input of this component. *

* The name is used only to work with "legacy" Web * application that handles user's request by * servlets. It works only with HTTP/HTML-based * browsers. It doesn't work with other kind of * clients. *

* Don't use this method if your application is * purely based on ZK's event-driven model. * * @param String * name the name of this component. */ name : function(name) { let n = this.$n('inp'); if (n) n.name = name; }, /** * Returns the emptyMessage, it will be displayed if * no selected items while not focused. * * @return String */ /** * Sets the emptyMessage. * * @param String * emptyMessage */ emptyMessage : null, /** * Returns the no-result text of this component. *

* Default: null. *

* The no-result text will be displayed in popup if * nothing match to the input value and can not * create either, the syntax "{0}" will be replaced * with the input value at client side. * * @return String */ /** * Sets the no-result text of this component. *

* The no-result text will be displayed in popup if * nothing match to the input value and can not * create either, the syntax "{0}" will be replaced * with the input value at client side. * * @param String * noResultsText the no-result text of * this component. */ noResultsText : null, /** * Returns the create message of this component. *

* Default: null. *

* The create message will be displayed in popup if * nothing match to the input value but can create * as new label, the syntax "{0}" will be replaced * with the input value at client side. * * @return String */ /** * Sets the create message of this component. *

* The create message will be displayed in popup if * nothing match to the input value but can create * as new label, the syntax "{0}" will be replaced * with the input value at client side. * * @param String * createMessage the create message of * this component. */ createMessage : null, /** * Returns the separate chars of this component. *

* Support: 0-9, A-Z (case insensitive), and * ,.;'[]/\-= *

* Default: null. *

* The separate chars will work as 'Enter' key, it * will not considered as input value but send * onSerch or onSearching while key up. * * @return String */ /** * Sets the separate chars of this component. *

* Support: 0-9, A-Z (case insensitive), and * ,.;'[]/\-= *

* The separate chars will work as 'Enter' key, it * will not considered as input value but send * onSerch or onSearching while key up. * * @param String * createMessage the create message of * this component. */ separator : function(v) { let separatorCode = this._separatorCode; separatorCode.length = 0; // save keycode for special symbol // handle the code of special char because // we need process it with both keyUp and // keyDown // which has different code with keyPress if (v.indexOf(',') != -1) separatorCode.push(188); if (v.indexOf('.') != -1) separatorCode.push(190); if (v.indexOf('/') != -1) separatorCode.push(191); if (v.indexOf(';') != -1) separatorCode.push(zk.ie ? 186 : 59); if (v.indexOf("'") != -1) separatorCode.push(222); if (v.indexOf('[') != -1) separatorCode.push(219); if (v.indexOf(']') != -1) separatorCode.push(221); if (v.indexOf('\\') != -1) separatorCode.push(220); if (v.indexOf('-') != -1) separatorCode.push(zk.ie ? 189 : 109); if (v.indexOf('=') != -1) separatorCode.push(107); }, /** * Returns whether can create new item, The input * will considered to be a new item if it is not * exist and this property is true. * * @return boolean */ /** * Sets whether can create new item. * * @param boolean * creatable */ creatable : null, /** * Returns the open status of drop down list. * * @return boolean */ /** * Sets the drop down list open status, and * open/close drop down list as need. * * @param boolean * open */ open : null }, setListContent : function(v) { let sel, out, oldHlite, value; if (sel = this.$n('sel')) { if (oldHlite = jq(this.$n('sel')) .find( '.' + this.getZclass() + '-option-over')[0]) value = oldHlite.innerHTML; out = []; this._renderItems(out, v); this._clearListContent(); sel.innerHTML = out.join(''); // restore old high-light if (value && (oldHlite = this ._getItemByValue(value))) this._hliteOpt(oldHlite, true); this._startFixDisplay({ hliteFirst : true, fromServer : true }); } }, _clearListContent : function() { if (this.$n()) { this.$n('sel').innerHTML = ''; this.$n('empty').style.display = 'none'; } }, _renderItems : function(out, content) { let s = $eval(content ? content : this._items) || [], zcls = this.getZclass(); for (let i = 0, j = s.length; i < j; i++) { out.push('

', zUtl.encodeXML(s[i]), '
'); } return out; }, getZclass : function() { let zcls = this._zclass; return zcls != null ? zcls : "z-chosenbox"; }, // update the selected items, the old selection will be // cleared at first setChgSel : function(val) { // called from the server this._clearSelection(); let sel, options; if (sel = this.$n('sel')) { // select each item options = jq(sel).children(); let s = $eval(val), renderByServer = this._renderByServer, item, value; for (let i = 0; i < s.length; i++) { value = s[i]; if (item = this._getItemByValue(value)) this._doSelect(item); else this._selectItemDirectly(value); } } else this._chgSel = val; // not binded, just store it this._fixEmptyMessage(true); }, bind_ : function() { this.$supers(Chosenbox, 'bind_', arguments); let n = this.$n(), inp = this.$n('inp'); this.domListen_(inp, 'onFocus', 'doFocus_') .domListen_(inp, 'onBlur', 'doBlur_'); zWatch.listen({ onFloatUp : this, onSize : this }); this._fixWidth(n); //fix selection if (this._selItems && this._selItems.length > 0) { let s = this._selItems; this._selItems = []; for (let i = 0; i < s.length; i++) { let value = s[i]; if (item = this._getItemByValue(value)) this._doSelect(item); else this._selectItemDirectly(value); } } else if (this._chgSel) { let s = this._chgSel; this._chgSel = null; for (let i = 0; i < s.length; i++) { value = s[i]; if (item = this._getItemByValue(value)) this._doSelect(item); else this._selectItemDirectly(value); } } // fix emptyMessage this._fixEmptyMessage(true); if (this._open && !this.isDisabled()) this.setOpen(true); }, unbind_ : function() { let inp = this.$n('inp'); this.domUnlisten_(inp, 'onFocus', 'doFocus_') .domUnlisten_(inp, 'onBlur', 'doBlur_'); zWatch.unlisten({ onFloatUp : this, onSize : this }); clearAllData(this); this.$supers(Chosenbox, 'unbind_', arguments); }, redraw: function (out) { this.$supers('redraw', arguments); }, onSize : function() { this._fixInputWidth(); }, _fixWidth : function(n) { if (this._width) n.style.width = this._width; this.$n('pp').style.width = jq(n).width() + 'px'; }, doBlur_ : function(evt) { jq(this.$n()).removeClass( this.getZclass() + '-focus'); }, doFocus_ : function(evt) { if (!this.isDisabled()) jq(this.$n()).addClass( this.getZclass() + '-focus'); }, doMouseOver_ : function(evt) { let target = evt.domTarget; // mouseover option if (jq(target).hasClass( this.getZclass() + '-option')) this._hliteOpt(target, true); }, doMouseOut_ : function(evt) { let target = evt.domTarget; // mouseout option if (jq(target).hasClass( this.getZclass() + '-option-over')) this._hliteOpt(target, false); }, _hliteOpt : function(target, highlight) { let zcls = this.getZclass() + '-option-over'; if (highlight) { // clear old first let oldHlite = jq(this.$n('sel')) .find( '.' + this.getZclass() + '-option-over')[0]; if (oldHlite) jq(oldHlite).removeClass(zcls); jq(target).addClass(zcls); } else jq(target).removeClass(zcls); }, _doArrowDown : function(key, evt) { if (key == 'up') this._moveOptionFocus('prev'); else if (key == 'down') this._moveOptionFocus('next'); else { let inp = this.$n('inp'), pos = zk(inp) .getSelectionRange(), label = jq( this.$n()).find( '.' + this.getZclass() + '-sel-item-focus')[0]; // only works if cursor is at the beginning of // input if (pos[0] == 0 && pos[1] == 0) { if (key == 'left') this._moveLabelFocus(label, 'prev'); else if (key == 'right') { if (label) evt.stop(); this._moveLabelFocus(label, 'next'); } } } }, // focus previous or next visible option, // depends on dir _moveOptionFocus : function(dir) { let sel = this.$n('sel'), $sel = jq(sel), oldHlite = $sel .find('.' + this.getZclass() + '-option-over')[0], newHlite, next = dir == 'next', prev = dir == 'prev'; if (next && !this._open) // default focus first // while open this.setOpen(true, { sendOnOpen : true }); else { // preset newHlite if (oldHlite) // get previous or next item of // old hi-lighted one newHlite = next ? oldHlite.nextSibling : oldHlite.previousSibling; else // get first/last item if no old hi-lighted newHlite = next ? sel.firstChild : // choose // first/last // option // if no // old // highlighted prev ? sel.lastChild : null; if (newHlite) // find closest visible new item while (newHlite && newHlite.style.display == 'none') newHlite = next ? newHlite.nextSibling : prev ? newHlite.previousSibling : null; if (newHlite) this._hliteOpt(newHlite, true); else if (oldHlite) this._hliteOpt(oldHlite, false); } }, // focus previous or next label, // depends on dir _moveLabelFocus : function(label, dir) { let zcls = this.getZclass() + '-sel-item-focus', newLabel, prev = dir == 'prev', next = dir == 'next'; if (label) { jq(label).removeClass(zcls); newLabel = prev ? label.previousSibling : next ? label.nextSibling : null; if (prev && !newLabel) newLabel = label; else if (next && newLabel == this.$n('inp')) newLabel = null; } else if (prev) newLabel = this.$n('inp').previousSibling; if (newLabel) jq(newLabel).addClass(zcls); }, // called after press backspace or del and release _deleteLabel : function(key, evt) { let inp = this.$n('inp'), pos = zk(inp) .getSelectionRange(), label; // only works if cursor is at the beginning of input if (pos[0] == 0 && pos[1] == 0) { let zcls = this.getZclass() + '-sel-item-focus'; if (label = jq(this.$n()).find('.' + zcls)[0]) { let dir = (label.previousSibling && key == 'backspace') ? 'prev' : 'next'; this._moveLabelFocus(label, dir); this._doDeselect(label, { sendOnSelect : true }); evt.stop(); // should stop or will delete // text // maybe have to filt out deselected item this._startFixDisplay(); } else if ((label = inp.previousSibling) && key == 'backspace') jq(label).addClass(zcls); } }, _removeLabelFocus : function() { let zcls = this.getZclass() + '-sel-item-focus', label = jq( this.$n()).find('.' + zcls)[0]; if (label) jq(label).removeClass(zcls); }, // called after press enter and release _doEnterPressed : function(evt) { let $sel, hlited, old; // clear timer and fix display before process if (old = this.fixDisplay) clearTimeout(old); this._fixDisplay(); if (this._open) { if ((hlited = this.$n('empty')) && jq(hlited).hasClass( this.getZclass() + '-empty-creatable')) { this._fireOnSearch(this.$n('inp').value); if (this._open) { this.setOpen(false, { sendOnOpen : true }); } } else if (($sel = jq(this.$n('sel'))) && (hlited = $sel.find('.' + this.getZclass() + '-option-over')[0])) { let options = $sel.children(); this._doSelect(hlited, { sendOnSelect : true }); if (this._open) { this.setOpen(false, { sendOnOpen : true }); } } } }, doClick_ : function(evt) { if (!this.isDisabled()) { let target = evt.domTarget, $target = jq(target), inp = this .$n('inp'), zcls = this.getZclass(); this._removeLabelFocus(); if (inp.value == this._emptyMessage) inp.value = ''; if ($target.hasClass(zcls + '-option')) { // click // on // option this._doSelect(target, { sendOnSelect : true }); if (this._open) this.setOpen(false, { sendOnOpen : true, fixEmptyMessage : true }); } else if ($target.hasClass(zcls + '-empty-creatable')) { // click on // new label this._fireOnSearch(inp.value); if (this._open) this.setOpen(false, { sendOnOpen : true }); } else { let label = target, zcls = this.getZclass() + '-sel-item'; if ($target.hasClass(zcls) || (label = $target.parent('.' + zcls)[0])) { // click on // label jq(label).addClass(zcls + '-focus'); } if (!this._open) this.setOpen(true, { sendOnOpen : true }); } inp.focus(); this.$supers('doClick_', arguments); } }, // select an item _doSelect : function(target, opts) { this._hliteOpt(target, false); let value = target.innerHTML; if (this._selItems.indexOf(value) == -1) { this._createLabel(value); target.style.display = 'none'; // hide selected // item // record the selected item this._selItems.push(value); this._fixEmptyMessage(true); if (opts && opts.sendOnSelect) this.fireSelectEvent(); } }, _selectItemDirectly : function(value) { if (this._selItems.indexOf(value) == -1) { this._createLabel(value); // record the selected item this._selItems.push(value); this._fixEmptyMessage(true); } }, // deselect an item _doDeselect : function(selectedItem, opts) { let value = jq(selectedItem).find( '.' + this.getZclass() + '-sel-item-cnt')[0].innerHTML, element = this ._getItemByValue(value), _selItems = this._selItems; if (this._open) this.setOpen(false, { sendOnOpen : true }); // remove record _selItems.splice(_selItems.indexOf(value), 1); // show origin option of deselected item if it // exists if (element) element.style.display = 'block'; // remove label of deselected item jq(selectedItem).remove(); if (opts && opts.sendOnSelect) this.fireSelectEvent(); // only fire if active // from client // maybe have to filt out deselected item this._startFixDisplay(); }, _getItemByValue : function(value) { let options = jq(this.$n('sel')).children(), item; for (let i = 0; i < options.length; i++) if ((item = options[i]) && item.innerHTML == value) return item; else if (!item) // over index return null; }, // create label for selected item _createLabel : function(value) { let span = document.createElement("span"), content = document .createElement("div"), delbtn = document .createElement("div"), wgt = this, zcls = this .getZclass(); span.className = zcls + '-sel-item'; content.innerHTML = value; content.className = zcls + '-sel-item-cnt'; delbtn.className = zcls + '-del-btn'; span.appendChild(content); span.appendChild(delbtn); jq(delbtn).bind('click', function() { if (!wgt.isDisabled()) { wgt.$n('inp').focus(); wgt._doDeselect(span, { sendOnSelect : true }); } }); this.$n().insertBefore(span, this.$n('inp')); // add // div // mark }, // clear all selected items _clearSelection : function(opts) { let n = this.$n(), inp = this.$n('inp'), c, // selected // item del; if (n) c = n.firstChild; while (c && c != inp) { del = c; c = c.nextSibling; this._doDeselect(del, opts); } this._selItems.length = 0; }, // fire onSelectevent to server fireSelectEvent : function() { let data = [], selItems = this._selItems; // selected // item for (let i = 0; i < selItems.length; i++) data.push(selItems[i]); this.fire('onSelect', data); }, // fire onSearch event _fireOnSearch : function(value) { let data = []; data.push(value); this.fire('onSearch', data); }, // fire onSearching event _fireOnSearching : function(value) { let data = []; data.push(value); this.fire('onSearching', data); }, // should close drop-down list if not click self onFloatUp : function(ctl) { if (ctl.origin != this) { if (this._open) this.setOpen(false, { sendOnOpen : true, fixEmptyMessage : true }); this._removeLabelFocus(); } }, doKeyDown_ : function(evt) { let keyCode = evt.keyCode; switch (keyCode) { case 8:// backspace this._deleteLabel('backspace', evt); break; case 13:// enter processed in key up only break; case 27:// esc processed in key up only break; case 37:// left this._doArrowDown('left', evt); break; case 38:// up this._doArrowDown('up'); break; case 39:// right this._doArrowDown('right', evt); break; case 40:// down this._doArrowDown('down'); break; case 46:// del this._deleteLabel('del', evt); break; default: // separator processed in key up only if (!this._isSeparator(keyCode)) { this._updateInput(evt); if (!this._open) this.setOpen(true, { sendOnOpen : true }); } else evt.stop(); } if (!(keyCode == 39 || keyCode == 46 || keyCode == 8 || keyCode == 37)) this._removeLabelFocus(); }, doKeyUp_ : function(evt) { let keyCode = evt.keyCode, opts = { hliteFirst : true }; switch (keyCode) { case 13:// enter this._doEnterPressed(evt); break; case 27:// esc if (this._open) this.setOpen(false, { sendOnOpen : true }); this._fixEmptyMessage(); break; default: if (this._isSeparator(keyCode)) this._doEnterPressed(evt); else { this._fixInputWidth(); if (keyCode == 38 || keyCode == 40) opts = null; if (!this._renderByServer) this._startFixDisplay(opts); } } if (!(keyCode >= 37 && keyCode <= 40 || keyCode == 13)) startOnSearching(this); }, _isSeparator : function(keyCode) { let separator = this._separator, separatorCode = this._separatorCode; return (separatorCode && separatorCode .indexOf(keyCode) != -1) || ((keyCode >= 48 && keyCode <= 122) && separator && separator .toUpperCase() .indexOf( String .fromCharCode(keyCode)) != -1); }, _updateInput : function(evt) { let inp = evt ? evt.domTarget : this.$n('inp'), txcnt = this .$n('txcnt'), wgt = this; // check every 100ms while input if (!this.fixInputWidth) this.fixInputWidth = setTimeout(function() { wgt._fixInputWidth() }, 100); }, setOpen : function(open, opts) { if (!this.isDisabled()) this._open = open; if (this.$n('pp')) { let pp = this.$n('pp'); if (open) this.open(this.$n(), pp, opts); else this.close(pp, opts); } }, open : function(n, pp, opts) { let ppstyle = pp.style; this._fixWidth(n); this._fixsz(pp); zk(pp).makeVParent(); // required for setTopmost this.setFloating_(true); this.setTopmost(); ppstyle.zIndex = n.style.zIndex; ppstyle.display = 'block'; if (opts) { let inp = this.$n(); zk(pp).position(inp, "after_start"); } zk(pp).slideDown(this, { duration : 100 }); this._startFixDisplay({ hliteFirst : true }); if (opts && opts.sendOnOpen) this.fire('onOpen', { open : true }); }, close : function(pp, opts) { zk(pp).undoVParent(); this.setFloating_(false); pp.style.display = 'none'; if (opts) { if (opts.sendOnOpen) this.fire('onOpen', { open : false }); if (opts.fixEmptyMessage) this._fixEmptyMessage(); } if (this._renderByServer) this._clearListContent(); }, _fixsz : function(pp) { let ppstyle = pp.style, maxh = this._ppMaxHeight; ppstyle.height = 'auto'; ppstyle.left = "-10000px"; ppstyle.display = "block"; ppstyle.visibility = "hidden"; if (jq(pp).height() > maxh) ppstyle.height = maxh + 'px'; ppstyle.display = "none"; ppstyle.visibility = "visible"; }, // calculate the width for input field _fixInputWidth : function() { let n = this.$n(), inp = this.$n('inp'), txcnt = this .$n('txcnt'), oldh = jq(n).height(), width, max = parseInt(this._width) - 10; // copy value to hidden txcnt txcnt.innerHTML = inp.value; // get width from hidden txcnt width = jq(txcnt).width() + 30; if (width > max) inp.style.width = max + 'px'; else inp.style.width = width + 'px'; if (this.fixInputWidth) clearTimeout(this.fixInputWidth); this.fixInputWidth = null; }, // prevent redundant fix display _startFixDisplay : function(opts) { // fix asap if from server if (opts && opts.fromServer) this._fixDisplay(opts); else { // replace old if exist and hold a while // while input let wgt = this, old; if (old = this.fixDisplay) clearTimeout(old); this.fixDisplay = setTimeout(function() { wgt._fixDisplay(opts); }, 200); } }, // filt out not matched item _fixDisplay : function(opts) { if (!this._open) return; let fromServer = opts && opts.fromServer; if (!this._renderByServer || (opts && opts.fromServer)) { let str = this.$n('inp').value, oldhlite = jq( this.$n('sel')) .find( '.' + this.getZclass() + '-option-over')[0], existance = this ._fixSelDisplay(opts && opts.hliteFirst && !oldhlite, str, fromServer); str = str ? str.trim() : ''; this._fixEmptyDisplay({ showExistance : true }, str, existance._found, existance._exist); } else { this._fixEmptyDisplay({ showBlank : !this.$n('sel').firstChild }); } }, // fix the display content of options _fixSelDisplay : function(hliteFirst, str, fromServer) { let pp = this.$n('pp'), $pp = jq(pp), maxh = this._ppMaxHeight, ppstyle = pp.style, selItems = this._selItems, options = jq( this.$n('sel')).children(), found = false, // unselected // match // item // exist exist = false, // selected match item exist index, element, showAll, selected; str = str ? str.trim() : ''; showAll = str && str == this._emptyMessage || str == ''; if (fromServer && str && str != this._emptyMessage && str != '' && this._renderByServer) showAll = true; // iterate through item list for (index = 0, element = options[index]; index < options.length; index++, element = options[index]) { // should fix each element if renew content from // server selected = selItems.indexOf(element.innerHTML) != -1; if (fromServer || !selected) { if (!selected && (showAll || str && element.innerHTML .toLowerCase() .startsWith( str .toLowerCase()))) { if (!found) { found = true; if (hliteFirst) this._hliteOpt(element, true); } element.style.display = 'block'; } else { this._hliteOpt(element, false); element.style.display = 'none'; // hide // if // has // input // and // not // match } } if (!exist && str && element.innerHTML.toLowerCase() == str .toLowerCase()) exist = true; } ppstyle.height = 'auto'; if ($pp.height() > maxh) ppstyle.height = maxh + 'px'; return { _found : found, _exist : exist }; }, // fix the display of no-result text block _fixEmptyDisplay : function(type, str, found, exist) { let ecls = this.getZclass() + '-empty-creatable', empty = this .$n('empty'); if (type && (type.showBlank || type.showExistance && this._renderByServer && !str)) { empty.innerHTML = ' '; jq(empty).removeClass(ecls); empty.style.display = 'block'; } else if (type && type.showExistance) { // set the status of empty block if (!found) { if (this._creatable && !exist && str) {// show // create // message // if // input // new // item // and // creatable let createMsg = this._createMessage; if (createMsg) createMsg = zUtl.encodeXML( createMsg.replace(/\{0\}/g, str)).replace( /\n/g, '
'); else createMsg = ' '; empty.innerHTML = createMsg; jq(empty).addClass(ecls); } else { // show no-result text if // nothing can be selected let empMsg = this._noResultsText; if (empMsg) empMsg = zUtl.encodeXML( empMsg.replace(/\{0\}/g, str)).replace( /\n/g, '
'); else empMsg = ' '; empty.innerHTML = empMsg; jq(empty).removeClass(ecls); } empty.style.display = 'block'; } else { empty.style.display = 'none'; jq(empty).removeClass(ecls); } } }, // show emptyMessage or clear input _fixEmptyMessage : function(force) { let inp; if ((!this._open || force) && (inp = this.$n('inp'))) { inp.value = this._selItems.length == 0 ? zUtl .encodeXML(this.getEmptyMessage()) : ''; this._fixInputWidth(); if (this._open) { this._startFixDisplay(); } } }, domAttrs_ : function() { let v; return this.$supers('domAttrs_', arguments) + (this.isDisabled() ? ' disabled="disabled"' : '') + ((v = this.getEmptyMessage()) ? ' value="' + zUtl.encodeXML(v) + '"' : '') + ((v = this.getTabindex()) ? ' tabindex="' + v + '"' : '') + ((v = this.getName()) ? ' name="' + zUtl.encodeXML(v) + '"' : ''); } }); })();