/* * Copyright (c) 2006, www.never-online.net! All rights reserved. * web : http://www.never-online * author : never-online, BlueDestiny * version: 0.12 beta * this is a autocomplete extras version, complete version in neverModules framework. * debug in IE6.0, Opera9.0, Mozilla Firefox1.5.0 */ /* neverModules.runtime.useCache = false; _registerNS(neverModules.modules.autocomplete); _registerNS(neverModules.configuration.autocomplete) _extends(neverModules.modules.autocomplete, neverModules.base.baseclass); */ /* * Copyright (c) 2006, www.never-online.net! All rights reserved. * Batch default autocomplete configuration * autocomplete 0.12 */ var neverModules = window.neverModules || {}; var _registerNS = _registerNS || function (ns) { var levels = ns.split("."); var _NS = neverModules; for (var i=(levels[0]=="neverModules")?1:0; i", end: ""} } neverModules.modules.autocomplete = _createjsClass(); neverModules.modules.autocomplete.prototype = { _defaultInitializer: function (configuration) { this.name = configuration.instanceName; this.textbox = configuration.textbox; this.returnBox = configuration.returnBox||this.textbox; this.maxSlice = neverModules.configuration.autocomplete.defaultMaxSlice; this.sliceRange = neverModules.configuration.autocomplete.defaultSliceRange; this.ignoreSpeed = !!neverModules.configuration.autocomplete.defaultIgnoreSpeed; this.ignoreCase = !!neverModules.configuration.autocomplete.defaultIgnoreCase; this.ignoreWhere = !!neverModules.configuration.autocomplete.defaultIgnoreWhere; this.autoSlice = !!neverModules.configuration.autocomplete.defaultAutoSlice; this.useContent = !!neverModules.configuration.autocomplete.defaultIsUseContent; this.useArrow = !!neverModules.configuration.autocomplete.defaultIsUseArrow; this.useSpaceMatch = !!neverModules.configuration.autocomplete.defaultUseSpaceMatch; this.spaceMatchRg = neverModules.configuration.autocomplete.defaultSpaceMatchRg; this.animateImage = neverModules.configuration.autocomplete.defaultAnimateImage; this.callback = neverModules.configuration.autocomplete.defaultCallbackHdle; this.scrollHeight = isNaN(parseInt(configuration.height))? neverModules.configuration.autocomplete.defaultHeight: parseInt(configuration.height); /* Initialize private variables */ this._currentVer = 0.12; this._formatData = []; this._inTheCacheData = false; this._cacheValue = "$NEVERMODULES_NULL_STRING$"; this._selectedIdx = neverModules.configuration.autocomplete._defaultSelectedIdx; this._currentStatus = neverModules.configuration.autocomplete._defaultStatus; this._cacheData = neverModules.configuration.autocomplete._defaultInitObject; this._completeContainer = neverModules.configuration.autocomplete._defaultInitObject; this._completeIframe = neverModules.configuration.autocomplete._defaultInitObject; this._completeStyle = configuration.style||neverModules.configuration.autocomplete._defaultStyleCss; this._dataSource = configuration.dataSource||neverModules.configuration.autocomplete._defaultDataSource; this._highlightTag = neverModules.configuration.autocomplete._defaultHighlightTag; this._invalidKeyCode = neverModules.configuration.autocomplete._defaultInvalidCode; this._inputValue = "$NEVERMODULES_NULL_STRING$"; }, _createAutocomplete: function () { with(this) { if (!document.body) throw new Error (["neverModules Error","Document not loaded,Can not create autoComplete"]); textbox.setAttribute("autocomplete","off"); _completeContainer = document.createElement("DIV"); document.body.appendChild(_completeContainer); _completeContainer.className = this._completeStyle; with (_completeContainer.style) { height = scrollHeight+"px"; overflow = "auto"; zIndex = "2"; position = "absolute"; display = "none"; }; var self = this; _completeContainer.onscroll = function () { self.textboxFocus(); }; if (neverModules.browser.isIE) { _completeIframe = document.createElement("iframe"); document.body.appendChild(_completeIframe); with (_completeIframe.style) { position = "absolute"; display = "none"; zIndex = "1"; overflow = "hidden"; frameBorder = "0"; scrolling = "no"; marginHeight = "0"; marginWidth = "0"; }; _completeContainer.onselectstart = function () { window.returnValue=false; }; }; addEvent(document,'mousedown', function (evt) { e = window.event? window.event.srcElement: evt.target; try { if (!self._queryTheContainer(e)) { self.close(); } else { self.textboxFocus(); } } catch(ex) {}; }); // add a event listener to close autocomplete, // when the focus is not in the autocomplete(input control). addEvent(document,'keyup', function (evt) { e = window.event? window.event.srcElement: evt.target; try { if (!self._queryTheContainer(e)) { self.close(); } else { self.textboxFocus(); } } catch(ex) {}; }); if (this._currentStatus) this.show(); }}, _encode: function (str) { str = str+""; str = str.replace(/\ /g, " "); str = str.replace(/\ /g, " "); //str = str.replace(//g,">"); return str; }, _decode: function (str) { str = str+""; str = str.replace(/ /g, " "); //str = str.replace(/</g,"<"); //str = str.replace(/>/g,">"); return str; }, _queryTheContainer: function (e) { while(e && e.tagName!="BODY") { if (!e) return false; if (e==this.textbox || e==this._completeContainer) { return true; }; e=e.parentNode; }; return false; }, _fireCallbackHdle: function () { if (typeof (this.callback)=="function") { this.callback.apply(this, arguments); } }, _hdleFactory: function (hdle, aArgs) { aArgs = aArgs || []; if ("formatDatasource"==hdle) { return this.useContent==true? this._formatMutiDataSource.apply(this, aArgs): this._formatSingleDataSource.apply(this, aArgs); } else if ("query"==hdle) { return this.useContent==true? this._queryMutiDataSource.apply(this, aArgs): this._querySingleDataSource.apply(this, aArgs); } else if ("toggle"==hdle) { return this.useContent==true? this._hdleMutiToggle.apply(this, aArgs): this._hdleSingleToggle.apply(this, aArgs); } else if ("arrow"==hdle) { return this.useContent==true? this._hdleMutiArrow.apply(this, aArgs): this._hdleSingleArrow.apply(this, aArgs); } }, _hdleQuery: function (strQuery) { if (!strQuery) return false; return this._hdleFactory("query",arguments); }, _hdleToggle: function (oElement, sClassName1, sClassName2, sClassName3) { this._hdleFactory("toggle",arguments); }, _hdleClick: function (oElement) { var text = this.getSelectedValue(oElement).text; var content = this.getSelectedValue(oElement).content; this._inputValue = text; this.returnBox.value = text; this._fireCallbackHdle(text, content); this.close(); this.textboxFocus(); }, _hdleFormatDataSource: function () { return this._hdleFactory("formatDatasource", arguments); }, /* * Copyright (c) 2006, www.never-online.net! All rights reserved. * the following that is the event handler * autocomplete 0.12 */ _hdleSingleArrow: function (nKeyCode) { with(this) { var r = _completeContainer.getElementsByTagName("div"); switch (nKeyCode) { case 13: // Enter r[this._selectedIdx]?r[this._selectedIdx].click():null; break; case 38: // Up arrow this._selectedIdx--; break; case 40: // Down arrow this._selectedIdx++; break; case 27: // ESC this.close(); break; default: return; } this._selectedIdx<=-1?this._selectedIdx=0:this._selectedIdx>r.length-1?this._selectedIdx=r.length-1:""; if (!r[this._selectedIdx]) return; this._completeContainer.scrollTop=this._getRelativeScrollTop(r[this._selectedIdx]); this._hdleToggle(r[this._selectedIdx],'over'); this._selectedIdx>0?this._hdleToggle(r[this._selectedIdx-1],'out'):""; this._hdleToggle(r[this._selectedIdx+1],'out'); this._createRange(r[this._selectedIdx]); }}, _hdleMutiArrow: function (nKeyCode) { var a = this._completeContainer.childNodes[0]; var r = a.getElementsByTagName("TR"); switch (nKeyCode) { case 13: // Enter r[this._selectedIdx]?r[this._selectedIdx].click():""; break; case 38: // Up arrow this._selectedIdx--; break; case 40: // Down arrow this._selectedIdx++; break; case 27: // ESC this.close(); break; default: return; } this._selectedIdx<=-1?this._selectedIdx=0:this._selectedIdx>r.length-1?this._selectedIdx=r.length-1:""; if (!r[this._selectedIdx]) return; this._completeContainer.scrollTop=this._getRelativeScrollTop(r[this._selectedIdx]); this._hdleToggle(r[this._selectedIdx],'over','autot-over','autoc-over'); this._selectedIdx>0?this._hdleToggle(r[this._selectedIdx-1],'out','autot','autoc'):""; r[this._selectedIdx+1]?this._hdleToggle(r[this._selectedIdx+1],'out','autot','autoc'):""; this._createRange(r[this._selectedIdx]); }, _createRange: function (oElement) { if (!oElement) return; var rng; var text = this.getSelectedValue(oElement).text; this.returnBox.value = text; if (neverModules.browser.isIE) { try { rng = this.textbox.createTextRange(); rng.moveStart("character", this._inputValue.length); rng.select(); rng=null; } catch (ex) {}; } else { //TODO } }, _tg: function (oElement) { this._hdleToggle.apply(this, arguments); }, _hdleMutiToggle: function (oElement, sClassName1, sClassName2, sClassName3) { if (!oElement) return; var a = this._completeContainer; oElement.tagName=="TR"?oElement.className=sClassName1:""; var a = oElement.childNodes; for(var i=0; i-1) { a[i].className=sClassName2; } else if (a[i].className.toLowerCase().indexOf("autoc")>-1) { a[i].className=sClassName3; } } } }, _hdleSingleToggle: function (oElement, sClassName) { if (!oElement) return; oElement.className = sClassName; }, _hc: function (oElement) { this._hdleClick.apply(this, arguments); }, _ckSpaceMatchQuery: function (strQuery) { strQuery=strQuery+""; if (!this.useSpaceMatch) return strQuery; strQuery = this.useSpaceMatch?strQuery.replace(/ /g,"\|"):strQuery; return strQuery; }, /* * Copyright (c) 2006, www.never-online.net! All rights reserved. * the following that is the private method * autocomplete 0.12 */ _getRelativeScrollTop: function (e) { return e.offsetTop; }, _querySingleDataSource: function (strQuery) { var rQuery = this._ckSpaceMatchQuery(strQuery); strQuery = this.useSpaceMatch?strQuery.replace(/ /g,this.spaceMatchRg):strQuery; var rg = new RegExp().compile(']+?>' +(this.ignoreWhere?'[^<>]*?':'')+strQuery+'[^<>]*?<\/div>', this.ignoreCase?"ig":"g"); var sDataSource = (this._inTheCacheData?this._cacheData:this._hdleFormatDataSource())+""; var aMatch = sDataSource.match(rg); rg = null; if (!aMatch) { this.close(); return false; } if (this.ignoreSpeed==true) { rg = new RegExp().compile("(?:>)([^<>]*?)(" +rQuery+ ")", this.ignoreCase?"ig":"g"); return this._cacheData=(this.autoSlice && aMatch.length>this.maxSlice? aMatch.slice(this.sliceRange.low, this.sliceRange.high).join(""): aMatch.join("")).replace(rg, ">$1" +this._highlightTag.start+ "$2" +this._highlightTag.end +""); } else { return this._cacheData=this.autoSlice && aMatch.length>this.maxSlice? aMatch.slice(this.sliceRange.low, this.sliceRange.high).join(""): aMatch.join(""); } }, _queryMutiDataSource: function (strQuery) { var rQuery = this._ckSpaceMatchQuery(strQuery); strQuery = this.useSpaceMatch?strQuery.replace(/ /g,this.spaceMatchRg):strQuery; var a=(this._inTheCacheData?(this._cacheData||[]).length>0?this._cacheData:this._dataSource:this._dataSource)||[]; var text, content, hints, rText, rg; this._formatData=[]; rg = new RegExp().compile( this.ignoreWhere?"(.*?)(" +strQuery+ ")(.*?)":"^(" +strQuery+ ")(.*?)", this.ignoreCase?"ig":"g"); for (var i=0; ithis.maxSlice? this._formatData.slice(this.sliceRange.low, this.sliceRange.high): this._formatData; return this._hdleFormatDataSource(); }, _formatSingleDataSource: function () { var strHTML=""; var a=this._dataSource||[]; if (a.length==1) { strHTML = '' + '
' +a[0]+ '
'; } else { strHTML = '' + '
\n'+a.join('
\n
\n')+"\n
"; } return strHTML; }, _formatMutiDataSource: function () { var a = this._formatData||[]; var strBuilder = []; var text,rText,content,hints,strHTML; for (var i=0; i\n' +rText+ '\n' +content+ '\n\n'); } strHTML = ''; strHTML += strBuilder.join("") strHTML += "
"; return strHTML; }, _showAnimateImage: function (src, width, height) { if (!!src) this.setAnimateImage.apply(this,arguments); var o = this.animateImage; var p = new Image(); var ig; var self = this; p.src=o.src; p.width=o.width?o.width:p.width; p.height=o.height?o.height:p.height; if (document.getElementById("autocompleteAnimateImageId") && document.getElementById("autocompleteAnimatecontainerId")) { ig = document.getElementById("autocompleteAnimateImageId"); c=document.getElementById("autocompleteAnimatecontainerId"); ig.src = p.src; ig.width = p.width; ig.height = p.height; animateImageShow(); return; } var c = document.createElement("DIV"); c.id = "autocompleteAnimatecontainerId"; ig = document.createElement("IMG"); ig.id = "autocompleteAnimateImageId"; ig.src = p.src; ig.width = p.width; ig.height = p.height; c.style.display = "none"; document.body.appendChild(c); c.appendChild(ig); animateImageShow(); function animateImageShow() { var os = getAbsoluteCoords(self.textbox); with (c.style) { left = os.left+os.width-p.width-2+"px"; top = os.top+Math.round((os.height-p.height)/2)-(neverModules.browser.isIE?-1:2)+"px"; zIndex = "10"; position = "absolute"; display = "block"; } } }, _setCacheValue: function (strValue) { /* * using cache array to improve the query speed performace * must be set the ignoreSpeed with false value * 缓存存于cacheData中,使用cache来提高查询速度。大数据量时有效 * 此功能还有一个好处,可以减少与服务器的交互(在AJAX时) */ this._inTheCacheData = false; if (this._cacheValue=="" || (!this._cacheData)) { this._inTheCacheData=false; this._cacheValue = strValue; return; }; if (this._cacheValue==strValue.substring(0,this._cacheValue.length)) { this._inTheCacheData = true; }; this._cacheValue = strValue; }, /* * Copyright (c) 2006, www.never-online.net! All rights reserved. * the following that is the public method * autocomplete 0.12 * interface list */ show: function () { this._currentStatus = 1; var p = getAbsoluteCoords(this.textbox); var x = this._completeContainer.style; x.left = p.left+"px"; x.top = p.top+p.height+"px"; x.width = p.width+"px"; x.display = "block"; if (neverModules.browser.isIE) { var w = this._completeIframe.style; w.display = "block"; w.left = p.left+"px"; w.top = p.top+p.height+"px"; w.width = p.width+"px"; w.height = this._completeContainer.offsetHeight+"px"; } try { var a = document.getElementById(this.name+ "_complete_table"); if (a.offsetHeight>=this._completeContainer.offsetHeight) { //a.setAttribute("width",this.textbox.offsetWidth-18); a.setAttribute("height",this.scrollHeight); } } catch(e) {}; this._completeContainer.scrollTop = '0px'; }, close: function (e) { try { if (neverModules.browser.isIE) this._completeIframe.style.display = "none"; this._completeContainer.style.display = "none"; this._currentStatus = 0; } catch (ex) {}; }, clearDataSource: function () { this._dataSource = []; this._cacheData = []; }, setDataSource: function (aDataSource) { if (aDataSource.constructor!=Array) return; this.close(); this.clearDataSource(); this._dataSource = aDataSource; // reference //this._dataSource = aDataSource.join("$NEVER_MODULES_SPLIT$").split("$NEVER_MODULES_SPLIT$"); }, getSelectedValue: function (oElement) { if (!oElement) return {text: "null", content: "null"}; var text = this.useContent? oElement.getAttribute("txt"): oElement.innerHTML.replace(/<[^<>]*>/g,""); var content = this.useContent? oElement.getAttribute("content"):""; return {text: text, content: content}; }, expandAllItem: function () { this._formatData = this._dataSource; this._completeContainer.innerHTML = this._hdleFormatDataSource(); this.show(); }, hdleEvent: function (evt) { var strQuery = this.textbox.value.rgEncode(); var strHTML; var nKeyCode = window.event?event.keyCode:evt.which; if (strQuery == "" && this._currentStatus==0) { this.close(); return; } if (this.isValidKey(evt)==false) { if ((!this._currentStatus) || (this.useArrow!=true && nKeyCode!=27)) return; this._hdleFactory("arrow",[nKeyCode]); return; }; this._inputValue = strQuery; this._setCacheValue(strQuery); this._completeContainer.innerHTML = ""; this._selectedIdx = -1; strHTML = this._hdleQuery(strQuery); if (strHTML!=false) { this._completeContainer.innerHTML = strHTML; this.show(); } else { this.close(); this._inTheCacheData = false; } }, isValidKey: function (evt) { var nKeyCode = window.event?event.keyCode:evt.which; for (var key in this._invalidKeyCode) { if (nKeyCode==this._invalidKeyCode[key]) return false; }; return true; }, showAnimateImage: function (src, width, height) { this._showAnimateImage.apply(this, arguments); }, closeAnimateImage: function () { try { document.getElementById("autocompleteAnimatecontainerId").style.display="none"; } catch (ex) {}; }, setAnimateImage: function (src, width, height) { if (!src) return; this.animateImage = {src:src, width:width, height:height}; }, isRequireAjax: function () { return (!this._inTheCacheData); }, isinCache: function () { return this.isRequireAjax(); }, dispose: function () { try { this._completeContainer.parentNode.removeChild(this._completeContainer); if (neverModules.browser.isIE) this._completeIframe.parentNode.removeChild(this._completeIframe); } catch (ex) {}; }, create: function () { this._createAutocomplete(); }, textboxFocus: function () { //禁止focus return; if (this.textbox) this.textbox.focus(); } }