Subversion Repositories Applications.papyrus

Rev

Rev 1987 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
        Copyright (c) 2004-2006, The Dojo Foundation
        All Rights Reserved.

        Licensed under the Academic Free License version 2.1 or above OR the
        modified 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 &nbsp; 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);
        }
}});