Rev 1422 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*Copyright (c) 2004-2006, The Dojo FoundationAll Rights Reserved.Licensed under the Academic Free License version 2.1 or above OR themodified BSD license. For more information on Dojo licensing, see:http://dojotoolkit.org/community/licensing.shtml*/dojo.provide("dojo.widget.ComboBox");dojo.require("dojo.widget.*");dojo.require("dojo.event.*");dojo.require("dojo.io.*");dojo.require("dojo.html.*");dojo.require("dojo.string");dojo.require("dojo.widget.html.stabile");dojo.require("dojo.widget.PopupContainer");dojo.declare("dojo.widget.incrementalComboBoxDataProvider", null, function (options) {this.searchUrl = options.dataUrl;this._cache = {};this._inFlight = false;this._lastRequest = null;this.allowCache = false;}, {_addToCache:function (keyword, data) {if (this.allowCache) {this._cache[keyword] = data;}}, startSearch:function (searchStr, callback) {if (this._inFlight) {}var tss = encodeURIComponent(searchStr);var realUrl = dojo.string.substituteParams(this.searchUrl, {"searchString":tss});var _this = this;var request = this._lastRequest = dojo.io.bind({url:realUrl, method:"get", mimetype:"text/json", load:function (type, data, evt) {_this._inFlight = false;if (!dojo.lang.isArray(data)) {var arrData = [];for (var key in data) {arrData.push([data[key], key]);}data = arrData;}_this._addToCache(searchStr, data);if (request == _this._lastRequest) {callback(data);}}});this._inFlight = true;}});dojo.declare("dojo.widget.basicComboBoxDataProvider", null, function (options, node) {this._data = [];this.searchLimit = 30;this.searchType = "STARTSTRING";this.caseSensitive = false;if (!dj_undef("dataUrl", options) && !dojo.string.isBlank(options.dataUrl)) {this._getData(options.dataUrl);} else {if ((node) && (node.nodeName.toLowerCase() == "select")) {var opts = node.getElementsByTagName("option");var ol = opts.length;var data = [];for (var x = 0; x < ol; x++) {var text = opts[x].textContent || opts[x].innerText || opts[x].innerHTML;var keyValArr = [String(text), String(opts[x].value)];data.push(keyValArr);if (opts[x].selected) {options.setAllValues(keyValArr[0], keyValArr[1]);}}this.setData(data);}}}, {_getData:function (url) {dojo.io.bind({url:url, load:dojo.lang.hitch(this, function (type, data, evt) {if (!dojo.lang.isArray(data)) {var arrData = [];for (var key in data) {arrData.push([data[key], key]);}data = arrData;}this.setData(data);}), mimetype:"text/json"});}, startSearch:function (searchStr, callback) {this._performSearch(searchStr, callback);}, _performSearch:function (searchStr, callback) {var st = this.searchType;var ret = [];if (!this.caseSensitive) {searchStr = searchStr.toLowerCase();}for (var x = 0; x < this._data.length; x++) {if ((this.searchLimit > 0) && (ret.length >= this.searchLimit)) {break;}var dataLabel = new String((!this.caseSensitive) ? this._data[x][0].toLowerCase() : this._data[x][0]);if (dataLabel.length < searchStr.length) {continue;}if (st == "STARTSTRING") {if (searchStr == dataLabel.substr(0, searchStr.length)) {ret.push(this._data[x]);}} else {if (st == "SUBSTRING") {if (dataLabel.indexOf(searchStr) >= 0) {ret.push(this._data[x]);}} else {if (st == "STARTWORD") {var idx = dataLabel.indexOf(searchStr);if (idx == 0) {ret.push(this._data[x]);}if (idx <= 0) {continue;}var matches = false;while (idx != -1) {if (" ,/(".indexOf(dataLabel.charAt(idx - 1)) != -1) {matches = true;break;}idx = dataLabel.indexOf(searchStr, idx + 1);}if (!matches) {continue;} else {ret.push(this._data[x]);}}}}}callback(ret);}, setData:function (pdata) {this._data = pdata;}});dojo.widget.defineWidget("dojo.widget.ComboBox", dojo.widget.HtmlWidget, {forceValidOption:false, searchType:"stringstart", dataProvider:null, autoComplete:true, searchDelay:100, dataUrl:"", fadeTime:200, maxListLength:8, mode:"local", selectedResult:null, dataProviderClass:"", buttonSrc:dojo.uri.moduleUri("dojo.widget", "templates/images/combo_box_arrow.png"), dropdownToggle:"fade", templateString:"<span _=\"whitespace and CR's between tags adds in FF\"\n\tclass=\"dojoComboBoxOuter\"\n\t><input style=\"display:none\" tabindex=\"-1\" name=\"\" value=\"\" \n\t\tdojoAttachPoint=\"comboBoxValue\"\n\t><input style=\"display:none\" tabindex=\"-1\" name=\"\" value=\"\" \n\t\tdojoAttachPoint=\"comboBoxSelectionValue\"\n\t><input type=\"text\" autocomplete=\"off\" class=\"dojoComboBox\"\n\t\tdojoAttachEvent=\"key:_handleKeyEvents; keyUp: onKeyUp; compositionEnd; onResize;\"\n\t\tdojoAttachPoint=\"textInputNode\"\n\t><img hspace=\"0\"\n\t\tvspace=\"0\"\n\t\tclass=\"dojoComboBox\"\n\t\tdojoAttachPoint=\"downArrowNode\"\n\t\tdojoAttachEvent=\"onMouseUp: handleArrowClick; onResize;\"\n\t\tsrc=\"${this.buttonSrc}\"\n></span>\n", templateCssString:".dojoComboBoxOuter {\n\tborder: 0px !important;\n\tmargin: 0px !important;\n\tpadding: 0px !important;\n\tbackground: transparent !important;\n\twhite-space: nowrap !important;\n}\n\n.dojoComboBox {\n\tborder: 1px inset #afafaf;\n\tmargin: 0px;\n\tpadding: 0px;\n\tvertical-align: middle !important;\n\tfloat: none !important;\n\tposition: static !important;\n\tdisplay: inline !important;\n}\n\n/* the input box */\ninput.dojoComboBox {\n\tborder-right-width: 0px !important; \n\tmargin-right: 0px !important;\n\tpadding-right: 0px !important;\n}\n\n/* the down arrow */\nimg.dojoComboBox {\n\tborder-left-width: 0px !important;\n\tpadding-left: 0px !important;\n\tmargin-left: 0px !important;\n}\n\n/* IE vertical-alignment calculations can be off by +-1 but these margins are collapsed away */\n.dj_ie img.dojoComboBox {\n\tmargin-top: 1px; \n\tmargin-bottom: 1px; \n}\n\n/* the drop down */\n.dojoComboBoxOptions {\n\tfont-family: Verdana, Helvetica, Garamond, sans-serif;\n\t/* font-size: 0.7em; */\n\tbackground-color: white;\n\tborder: 1px solid #afafaf;\n\tposition: absolute;\n\tz-index: 1000; \n\toverflow: auto;\n\tcursor: default;\n}\n\n.dojoComboBoxItem {\n\tpadding-left: 2px;\n\tpadding-top: 2px;\n\tmargin: 0px;\n}\n\n.dojoComboBoxItemEven {\n\tbackground-color: #f4f4f4;\n}\n\n.dojoComboBoxItemOdd {\n\tbackground-color: white;\n}\n\n.dojoComboBoxItemHighlight {\n\tbackground-color: #63709A;\n\tcolor: white;\n}\n", templateCssPath:dojo.uri.moduleUri("dojo.widget", "templates/ComboBox.css"), setValue:function (value) {this.comboBoxValue.value = value;if (this.textInputNode.value != value) {this.textInputNode.value = value;dojo.widget.html.stabile.setState(this.widgetId, this.getState(), true);this.onValueChanged(value);}}, onValueChanged:function (value) {}, getValue:function () {return this.comboBoxValue.value;}, getState:function () {return {value:this.getValue()};}, setState:function (state) {this.setValue(state.value);}, enable:function () {this.disabled = false;this.textInputNode.removeAttribute("disabled");}, disable:function () {this.disabled = true;this.textInputNode.setAttribute("disabled", true);}, _getCaretPos:function (element) {if (dojo.lang.isNumber(element.selectionStart)) {return element.selectionStart;} else {if (dojo.render.html.ie) {var tr = document.selection.createRange().duplicate();var ntr = element.createTextRange();tr.move("character", 0);ntr.move("character", 0);try {ntr.setEndPoint("EndToEnd", tr);return String(ntr.text).replace(/\r/g, "").length;}catch (e) {return 0;}}}}, _setCaretPos:function (element, location) {location = parseInt(location);this._setSelectedRange(element, location, location);}, _setSelectedRange:function (element, start, end) {if (!end) {end = element.value.length;}if (element.setSelectionRange) {element.focus();element.setSelectionRange(start, end);} else {if (element.createTextRange) {var range = element.createTextRange();with (range) {collapse(true);moveEnd("character", end);moveStart("character", start);select();}} else {element.value = element.value;element.blur();element.focus();var dist = parseInt(element.value.length) - end;var tchar = String.fromCharCode(37);var tcc = tchar.charCodeAt(0);for (var x = 0; x < dist; x++) {var te = document.createEvent("KeyEvents");te.initKeyEvent("keypress", true, true, null, false, false, false, false, tcc, tcc);element.dispatchEvent(te);}}}}, _handleKeyEvents:function (evt) {if (evt.ctrlKey || evt.altKey || !evt.key) {return;}this._prev_key_backspace = false;this._prev_key_esc = false;var k = dojo.event.browser.keys;var doSearch = true;switch (evt.key) {case k.KEY_DOWN_ARROW:if (!this.popupWidget.isShowingNow) {this._startSearchFromInput();}this._highlightNextOption();dojo.event.browser.stopEvent(evt);return;case k.KEY_UP_ARROW:this._highlightPrevOption();dojo.event.browser.stopEvent(evt);return;case k.KEY_TAB:if (!this.autoComplete && this.popupWidget.isShowingNow && this._highlighted_option) {dojo.event.browser.stopEvent(evt);this._selectOption({"target":this._highlighted_option, "noHide":false});this._setSelectedRange(this.textInputNode, this.textInputNode.value.length, null);} else {this._selectOption();return;}break;case k.KEY_ENTER:if (this.popupWidget.isShowingNow) {dojo.event.browser.stopEvent(evt);}if (this.autoComplete) {this._selectOption();return;}case " ":if (this.popupWidget.isShowingNow && this._highlighted_option) {dojo.event.browser.stopEvent(evt);this._selectOption();this._hideResultList();return;}break;case k.KEY_ESCAPE:this._hideResultList();this._prev_key_esc = true;return;case k.KEY_BACKSPACE:this._prev_key_backspace = true;if (!this.textInputNode.value.length) {this.setAllValues("", "");this._hideResultList();doSearch = false;}break;case k.KEY_RIGHT_ARROW:case k.KEY_LEFT_ARROW:doSearch = false;break;default:if (evt.charCode == 0) {doSearch = false;}}if (this.searchTimer) {clearTimeout(this.searchTimer);}if (doSearch) {this._blurOptionNode();this.searchTimer = setTimeout(dojo.lang.hitch(this, this._startSearchFromInput), this.searchDelay);}}, compositionEnd:function (evt) {evt.key = evt.keyCode;this._handleKeyEvents(evt);}, onKeyUp:function (evt) {this.setValue(this.textInputNode.value);}, setSelectedValue:function (value) {this.comboBoxSelectionValue.value = value;}, setAllValues:function (value1, value2) {this.setSelectedValue(value2);this.setValue(value1);}, _focusOptionNode:function (node) {if (this._highlighted_option != node) {this._blurOptionNode();this._highlighted_option = node;dojo.html.addClass(this._highlighted_option, "dojoComboBoxItemHighlight");}}, _blurOptionNode:function () {if (this._highlighted_option) {dojo.html.removeClass(this._highlighted_option, "dojoComboBoxItemHighlight");this._highlighted_option = null;}}, _highlightNextOption:function () {if ((!this._highlighted_option) || !this._highlighted_option.parentNode) {this._focusOptionNode(this.optionsListNode.firstChild);} else {if (this._highlighted_option.nextSibling) {this._focusOptionNode(this._highlighted_option.nextSibling);}}dojo.html.scrollIntoView(this._highlighted_option);}, _highlightPrevOption:function () {if (this._highlighted_option && this._highlighted_option.previousSibling) {this._focusOptionNode(this._highlighted_option.previousSibling);} else {this._highlighted_option = null;this._hideResultList();return;}dojo.html.scrollIntoView(this._highlighted_option);}, _itemMouseOver:function (evt) {if (evt.target === this.optionsListNode) {return;}this._focusOptionNode(evt.target);dojo.html.addClass(this._highlighted_option, "dojoComboBoxItemHighlight");}, _itemMouseOut:function (evt) {if (evt.target === this.optionsListNode) {return;}this._blurOptionNode();}, onResize:function () {var inputSize = dojo.html.getContentBox(this.textInputNode);if (inputSize.height <= 0) {dojo.lang.setTimeout(this, "onResize", 100);return;}var buttonSize = {width:inputSize.height, height:inputSize.height};dojo.html.setContentBox(this.downArrowNode, buttonSize);}, fillInTemplate:function (args, frag) {dojo.html.applyBrowserClass(this.domNode);var source = this.getFragNodeRef(frag);if (!this.name && source.name) {this.name = source.name;}this.comboBoxValue.name = this.name;this.comboBoxSelectionValue.name = this.name + "_selected";dojo.html.copyStyle(this.domNode, source);dojo.html.copyStyle(this.textInputNode, source);dojo.html.copyStyle(this.downArrowNode, source);with (this.downArrowNode.style) {width = "0px";height = "0px";}var dpClass;if (this.dataProviderClass) {if (typeof this.dataProviderClass == "string") {dpClass = dojo.evalObjPath(this.dataProviderClass);} else {dpClass = this.dataProviderClass;}} else {if (this.mode == "remote") {dpClass = dojo.widget.incrementalComboBoxDataProvider;} else {dpClass = dojo.widget.basicComboBoxDataProvider;}}this.dataProvider = new dpClass(this, this.getFragNodeRef(frag));this.popupWidget = new dojo.widget.createWidget("PopupContainer", {toggle:this.dropdownToggle, toggleDuration:this.toggleDuration});dojo.event.connect(this, "destroy", this.popupWidget, "destroy");this.optionsListNode = this.popupWidget.domNode;this.domNode.appendChild(this.optionsListNode);dojo.html.addClass(this.optionsListNode, "dojoComboBoxOptions");dojo.event.connect(this.optionsListNode, "onclick", this, "_selectOption");dojo.event.connect(this.optionsListNode, "onmouseover", this, "_onMouseOver");dojo.event.connect(this.optionsListNode, "onmouseout", this, "_onMouseOut");dojo.event.connect(this.optionsListNode, "onmouseover", this, "_itemMouseOver");dojo.event.connect(this.optionsListNode, "onmouseout", this, "_itemMouseOut");}, _openResultList:function (results) {if (this.disabled) {return;}this._clearResultList();if (!results.length) {this._hideResultList();}if ((this.autoComplete) && (results.length) && (!this._prev_key_backspace) && (this.textInputNode.value.length > 0)) {var cpos = this._getCaretPos(this.textInputNode);if ((cpos + 1) > this.textInputNode.value.length) {this.textInputNode.value += results[0][0].substr(cpos);this._setSelectedRange(this.textInputNode, cpos, this.textInputNode.value.length);}}var even = true;while (results.length) {var tr = results.shift();if (tr) {var td = document.createElement("div");td.appendChild(document.createTextNode(tr[0]));td.setAttribute("resultName", tr[0]);td.setAttribute("resultValue", tr[1]);td.className = "dojoComboBoxItem " + ((even) ? "dojoComboBoxItemEven" : "dojoComboBoxItemOdd");even = (!even);this.optionsListNode.appendChild(td);}}this._showResultList();}, _onFocusInput:function () {this._hasFocus = true;}, _onBlurInput:function () {this._hasFocus = false;this._handleBlurTimer(true, 500);}, _handleBlurTimer:function (clear, millisec) {if (this.blurTimer && (clear || millisec)) {clearTimeout(this.blurTimer);}if (millisec) {this.blurTimer = dojo.lang.setTimeout(this, "_checkBlurred", millisec);}}, _onMouseOver:function (evt) {if (!this._mouseover_list) {this._handleBlurTimer(true, 0);this._mouseover_list = true;}}, _onMouseOut:function (evt) {var relTarget = evt.relatedTarget;try {if (!relTarget || relTarget.parentNode != this.optionsListNode) {this._mouseover_list = false;this._handleBlurTimer(true, 100);this._tryFocus();}}catch (e) {}}, _isInputEqualToResult:function (result) {var input = this.textInputNode.value;if (!this.dataProvider.caseSensitive) {input = input.toLowerCase();result = result.toLowerCase();}return (input == result);}, _isValidOption:function () {var tgt = dojo.html.firstElement(this.optionsListNode);var isValidOption = false;while (!isValidOption && tgt) {if (this._isInputEqualToResult(tgt.getAttribute("resultName"))) {isValidOption = true;} else {tgt = dojo.html.nextElement(tgt);}}return isValidOption;}, _checkBlurred:function () {if (!this._hasFocus && !this._mouseover_list) {this._hideResultList();if (!this.textInputNode.value.length) {this.setAllValues("", "");return;}var isValidOption = this._isValidOption();if (this.forceValidOption && !isValidOption) {this.setAllValues("", "");return;}if (!isValidOption) {this.setSelectedValue("");}}}, _selectOption:function (evt) {var tgt = null;if (!evt) {evt = {target:this._highlighted_option};}if (!dojo.html.isDescendantOf(evt.target, this.optionsListNode)) {if (!this.textInputNode.value.length) {return;}tgt = dojo.html.firstElement(this.optionsListNode);if (!tgt || !this._isInputEqualToResult(tgt.getAttribute("resultName"))) {return;}} else {tgt = evt.target;}while ((tgt.nodeType != 1) || (!tgt.getAttribute("resultName"))) {tgt = tgt.parentNode;if (tgt === dojo.body()) {return false;}}this.selectedResult = [tgt.getAttribute("resultName"), tgt.getAttribute("resultValue")];this.setAllValues(tgt.getAttribute("resultName"), tgt.getAttribute("resultValue"));if (!evt.noHide) {this._hideResultList();this._setSelectedRange(this.textInputNode, 0, null);}this._tryFocus();}, _clearResultList:function () {if (this.optionsListNode.innerHTML) {this.optionsListNode.innerHTML = "";}}, _hideResultList:function () {this.popupWidget.close();}, _showResultList:function () {var childs = this.optionsListNode.childNodes;if (childs.length) {var visibleCount = Math.min(childs.length, this.maxListLength);with (this.optionsListNode.style) {display = "";if (visibleCount == childs.length) {height = "";} else {height = visibleCount * dojo.html.getMarginBox(childs[0]).height + "px";}width = (dojo.html.getMarginBox(this.domNode).width - 2) + "px";}this.popupWidget.open(this.domNode, this, this.downArrowNode);} else {this._hideResultList();}}, handleArrowClick:function () {this._handleBlurTimer(true, 0);this._tryFocus();if (this.popupWidget.isShowingNow) {this._hideResultList();} else {this._startSearch("");}}, _tryFocus:function () {try {this.textInputNode.focus();}catch (e) {}}, _startSearchFromInput:function () {this._startSearch(this.textInputNode.value);}, _startSearch:function (key) {this.dataProvider.startSearch(key, dojo.lang.hitch(this, "_openResultList"));}, postCreate:function () {this.onResize();dojo.event.connect(this.textInputNode, "onblur", this, "_onBlurInput");dojo.event.connect(this.textInputNode, "onfocus", this, "_onFocusInput");if (this.disabled) {this.disable();}var s = dojo.widget.html.stabile.getState(this.widgetId);if (s) {this.setState(s);}}});