# HG changeset patch # User Dan # Date 1214172839 14400 # Node ID 5e8fd89c02eaf32dfdf66d40d54f72224f06c083 # Parent 41c45314ac27f796ddbb09973762089b92e7cd10 Initial progress towards converting auto-completion framework to Spry. Not currently in a very working state. diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/css/enano-shared.css --- a/includes/clientside/css/enano-shared.css Wed Jun 18 22:43:16 2008 -0400 +++ b/includes/clientside/css/enano-shared.css Sun Jun 22 18:13:59 2008 -0400 @@ -157,7 +157,7 @@ /* The beautiful tables inside what may not obviously be mdg-comment divs */ div.tblholder td.row1 { padding: 4px; background-color: #E0E0E0; } -div.tblholder td.row2 { padding: 4px; background-color: #F0F0F0; } +div.tblholder td.row2 { padding: 4px; background-color: #F0F0F0 !important; } /* using !important allows emphasized cells like in autosuggest to be highlighted */ div.tblholder td.row3 { padding: 4px; background-color: #E8E8E8; } div.tblholder th { padding: 4px; background-color: #7080A0; font-weight: bold; text-align: center; color: #FFFFFF; } div.tblholder th.subhead { padding: 4px; background-color: #90A0B0; font-weight: bold; text-align: center; color: #FFFFFF; } @@ -240,20 +240,6 @@ background-image: url(../../../images/search-btn-hilite.png); } -input[type ^="text"].username, input[type ^="password"].password { - padding: 2px 2px 2px 27px; - width: 96px; - height: 15px; - border: 0px none #000; - font-size: 11px; -} -input[type ^="text"].username { - background-image: url(../../../images/login-username.png); -} -input[type ^="password"].password { - background-image: url(../../../images/login-password.png); -} - /* * jBox menu system */ @@ -827,3 +813,21 @@ div.rankadmin-right { float: left; } + +/* Spry auto-suggestion */ +.hideSuggestClass +{ + max-height: 200px; + overflow:auto; + display:none; + width: 175px; + margin: 0px; + cursor: pointer; + z-index: 1011; +} + +.showSuggestClass .hideSuggestClass +{ + display: block !important; +} + diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/jsres.php --- a/includes/clientside/jsres.php Wed Jun 18 22:43:16 2008 -0400 +++ b/includes/clientside/jsres.php Sun Jun 22 18:13:59 2008 -0400 @@ -54,9 +54,12 @@ // Files safe to run full (aggressive) compression on $full_compress_safe = array( // Sorted by file size, descending (du -b *.js | sort -n) - 'libbigint.js', + // 'SpryData.js', + // 'SpryEffects.js', 'ajax.js', + 'libbigint.js', 'editor.js', + // 'SpryAutoSuggest.js', 'login.js', 'acl.js', 'misc.js', @@ -65,9 +68,9 @@ 'autofill.js', 'dropdown.js', 'paginate.js', - 'autocomplete.js', 'md5.js', 'enano-lib-basic.js', + 'SpryJSONDataSet.js', 'pwstrength.js', 'sha256.js', 'flyin.js', @@ -79,7 +82,7 @@ ); // Files that should NOT be compressed due to already being compressed, licensing, or invalid produced code -$compress_unsafe = array('SpryEffects.js', 'json.js', 'fat.js', 'admin-menu.js'); +$compress_unsafe = array('SpryEffects.js', 'json.js', 'fat.js', 'admin-menu.js', 'autofill.js'); require('includes/functions.php'); require('includes/json2.php'); diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/static/SpryAutoSuggest.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/includes/clientside/static/SpryAutoSuggest.js Sun Jun 22 18:13:59 2008 -0400 @@ -0,0 +1,883 @@ +// SpryAutoSuggest.js - version 0.91 - Spry Pre-Release 1.6.1 +// +// Copyright (c) 2006. Adobe Systems Incorporated. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Adobe Systems Incorporated nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +var Spry; +if (!Spry) Spry = {}; +if (!Spry.Widget) Spry.Widget = {}; + +Spry.Widget.BrowserSniff = function() +{ + var b = navigator.appName.toString(); + var up = navigator.platform.toString(); + var ua = navigator.userAgent.toString(); + + this.mozilla = this.ie = this.opera = this.safari = false; + var re_opera = /Opera.([0-9\.]*)/i; + var re_msie = /MSIE.([0-9\.]*)/i; + var re_gecko = /gecko/i; + var re_safari = /(applewebkit|safari)\/([\d\.]*)/i; + var r = false; + + if ( (r = ua.match(re_opera))) { + this.opera = true; + this.version = parseFloat(r[1]); + } else if ( (r = ua.match(re_msie))) { + this.ie = true; + this.version = parseFloat(r[1]); + } else if ( (r = ua.match(re_safari))) { + this.safari = true; + this.version = parseFloat(r[2]); + } else if (ua.match(re_gecko)) { + var re_gecko_version = /rv:\s*([0-9\.]+)/i; + r = ua.match(re_gecko_version); + this.mozilla = true; + this.version = parseFloat(r[1]); + } + this.windows = this.mac = this.linux = false; + + this.Platform = ua.match(/windows/i) ? "windows" : + (ua.match(/linux/i) ? "linux" : + (ua.match(/mac/i) ? "mac" : + ua.match(/unix/i)? "unix" : "unknown")); + this[this.Platform] = true; + this.v = this.version; + + if (this.safari && this.mac && this.mozilla) { + this.mozilla = false; + } +}; + +Spry.is = new Spry.Widget.BrowserSniff(); + +Spry.Widget.AutoSuggest = function(region, sRegion, dataset, field, options) +{ + if (!this.isBrowserSupported()) + return; + + options = options || {}; + + this.init(region, sRegion, dataset, field); + Spry.Widget.Utils.setOptions(this, options); + + if (Spry.Widget.AutoSuggest.onloadDidFire) + this.attachBehaviors(); + else + Spry.Widget.AutoSuggest.loadQueue.push(this); + + // when data is changing we will decide if we will have to show the suggestions + this.dataset.addObserver(this); + + // Set up an observer so we can attach our click behaviors whenever + // the region is regenerated. + var regionID = Spry.Widget.Utils.getElementID(sRegion); + + var self = this; + this._notifyDataset = { onPostUpdate: function() { + self.attachClickBehaviors(); + }, onPreUpdate: function(){ + self.removeClickBehaviours(); + }}; + + Spry.Data.Region.addObserver(regionID,this._notifyDataset); + + // clean up the widget when on page unload + Spry.Widget.Utils.addEventListener(window, 'unload', function(){self.destroy()}, false); + + // make the first computation in case the textfield is not empty + this.attachClickBehaviors(); + this.handleKeyUp(null); + this.showSuggestions(false); +}; + +Spry.Widget.AutoSuggest.prototype.init = function(region, sRegion, dataset, field) +{ + this.region = Spry.Widget.Utils.getElement(region); + + if (!this.region) + return; + + this.minCharsType = false; + this.containsString = false; + this.loadFromServer = false; + this.urlParam = ''; + this.suggestionIsVisible = false; + this.stopFocus = false; + this.hasFocus = false; + this.showSuggestClass = 'showSuggestClass'; + this.hideSuggestClass = 'hideSuggestClass'; + this.hoverSuggestClass = 'hoverSuggestClass'; + this.movePrevKeyCode = Spry.Widget.AutoSuggest.KEY_UP; + this.moveNextKeyCode = Spry.Widget.AutoSuggest.KEY_DOWN; + + this.textElement = Spry.Widget.Utils.getFirstChildWithNodeNameAtAnyLevel(this.region, "INPUT"); + this.textElement.setAttribute('AutoComplete', 'off'); + + this.suggestRegion = Spry.Widget.Utils.getElement(sRegion); + // prepare the suggest region + Spry.Widget.Utils.makePositioned(this.suggestRegion); + Spry.Widget.Utils.addClassName(this.suggestRegion, this.hideSuggestClass); + + this.timerID = null; + if (typeof dataset == "string"){ + this.dataset = window[dataset]; + }else{ + this.dataset = dataset; + } + this.field = field; + if (typeof field == 'string' && field.indexOf(',') != -1) + { + field = field.replace(/\s*,\s*/ig, ','); + this.field = field.split(','); + } +}; + +Spry.Widget.AutoSuggest.prototype.isBrowserSupported = function() +{ + return Spry.is.ie && Spry.is.v >= 5 && Spry.is.windows + || + Spry.is.mozilla && Spry.is.v >= 1.4 + || + Spry.is.safari + || + Spry.is.opera && Spry.is.v >= 9; +}; + +Spry.Widget.AutoSuggest.prototype.getValue = function() +{ + if (!this.textElement) + return ''; + return this.textElement.value; +}; + +Spry.Widget.AutoSuggest.prototype.setValue = function(str) +{ + if (!this.textElement) + return; + this.textElement.value = str; + this.showSuggestions(false); +}; + +Spry.Widget.AutoSuggest.prototype.focus = function() +{ + if (!this.textElement) + return; + this.textElement.focus(); +}; + +Spry.Widget.AutoSuggest.prototype.showSuggestions = function(doShow) +{ + if (this.region && this.isVisibleSuggestion() != doShow) + { + if (doShow && this.hasFocus) + { + Spry.Widget.Utils.addClassName(this.region, this.showSuggestClass); + if (Spry.is.ie && Spry.is.version < 7) + this.createIframeLayer(this.suggestRegion); + } + else + { + if (Spry.is.ie && Spry.is.version < 7) + this.removeIframeLayer(); + Spry.Widget.Utils.removeClassName(this.region, this.showSuggestClass); + } + } + this.suggestionIsVisible = Spry.Widget.Utils.hasClassName(this.region, this.showSuggestClass); +}; + +Spry.Widget.AutoSuggest.prototype.isVisibleSuggestion = function() +{ + return this.suggestionIsVisible; +}; + +Spry.Widget.AutoSuggest.prototype.onDataChanged = function(el) +{ + var data = el.getData(true); + var val = this.getValue(); + this.showSuggestions(data && (!this.minCharsType || val.length >= this.minCharsType) && (data.length > 1 || (data.length == 1 && this.childs[0] && this.childs[0].attributes.getNamedItem("spry:suggest").value != this.getValue()))); +}; +Spry.Widget.AutoSuggest.prototype.nodeMouseOver = function(e, node) +{ + var l = this.childs.length; + for (var i=0; i this.scrolParent.scrollTop + h) + { + // the 5 pixels make the latest option more visible. + this.scrolParent.scrollTop = el.offsetTop + el.offsetHeight - h + 5; + if (this.scrolParent.scrollTop < 0) + this.scrolParent.scrollTop = 0; + } + + } +}; + +Spry.Widget.AutoSuggest.KEY_UP = 38; +Spry.Widget.AutoSuggest.KEY_DOWN = 40; + +Spry.Widget.AutoSuggest.prototype.handleSpecialKeys = function(e){ + + switch (e.keyCode) + { + case this.moveNextKeyCode: // Down key + case this.movePrevKeyCode: // Up Key + if (!(this.childs.length > 0) || !this.getValue()) + return; + + var prev = this.childs.length-1; + var next = false; + var found = false; + var data = this.dataset.getData(); + if (this.childs.length > 1 || (data && data.length == 1 && this.childs[0] && this.childs[0].attributes.getNamedItem('spry:suggest').value != this.getValue())) + { + this.showSuggestions(true); + } + else + return; + + var utils = Spry.Widget.Utils; + for (var k=0; k < this.childs.length; k++) + { + if (next) + { + utils.addClassName(this.childs[k], this.hoverSuggestClass); + this.scrollVisible(this.childs[k]); + break; + } + if (utils.hasClassName(this.childs[k], this.hoverSuggestClass)) + { + utils.removeClassName(this.childs[k], this.hoverSuggestClass); + found = true; + if (e.keyCode == this.moveNextKeyCode) + { + next = true; + continue; + } + else + { + utils.addClassName(this.childs[prev], this.hoverSuggestClass); + this.scrollVisible(this.childs[prev]); + break; + } + } + prev = k; + } + if (!found || (next && k == this.childs.length)) + { + utils.addClassName(this.childs[0], this.hoverSuggestClass); + this.scrollVisible(this.childs[0]); + } + utils.stopEvent(e); + break; + case 27: // ESC key + this.showSuggestions(false); + break; + case 13: //Enter Key + if (!this.isVisibleSuggestion()) + return; + for (var k=0; k < this.childs.length; k++) + if (Spry.Widget.Utils.hasClassName(this.childs[k], this.hoverSuggestClass)) + { + var attr = this.childs[k].attributes.getNamedItem('spry:suggest'); + if (attr){ + this.setValue(attr.value); + this.handleKeyUp(null); + } + // stop form submission + Spry.Widget.Utils.stopEvent(e); + return false; + } + break; + case 9: //Tab Key + this.showSuggestions(false); + } + return; +}; + +Spry.Widget.AutoSuggest.prototype.filterDataSet = function() +{ + var contains = this.containsString; + var columnName = this.field; + var val = this.getValue(); + + if (this.previousString && this.previousString == val) + return; + + this.previousString = val; + + if (!val || (this.minCharsType && this.minCharsType > val.length)) + { + this.dataset.filter(function(ds, row, rowNumber) {return null;}); + this.showSuggestions(false); + return; + } + + var regExpStr = Spry.Widget.Utils.escapeRegExp(val); + + if (!contains) + regExpStr = "^" + regExpStr; + + var regExp = new RegExp(regExpStr, "ig"); + + if (this.maxListItems > 0) + this.dataset.maxItems = this.maxListItems; + + var filterFunc = function(ds, row, rowNumber) + { + if (ds.maxItems >0 && ds.maxItems <= ds.data.length) + return null; + + if (typeof columnName == 'object') + { + var l = columnName.length; + for (var i=0; i < l; i++) + { + var str = row[columnName[i]]; + if (str && str.search(regExp) != -1) + return row; + } + } + else + { + var str = row[columnName]; + if (str && str.search(regExp) != -1) + return row; + } + return null; + }; + + this.dataset.filter(filterFunc); + var data = this.dataset.getData(); + this.showSuggestions(data && (!this.minCharsType || val.length >= this.minCharsType) && (data.length > 1 || (data.length == 1 && this.childs[0] && this.childs[0].attributes.getNamedItem('spry:suggest').value != val ))); +}; + +Spry.Widget.AutoSuggest.prototype.loadDataSet = function() +{ + var val = this.getValue(); + var ds = this.dataset; + ds.cancelLoadData(); + ds.useCache = false; + + if (!val || (this.minCharsType && this.minCharsType > val.length)) + { + this.showSuggestions(false); + return; + } + + if (this.previousString && this.previousString == val) + { + var data = ds.getData(); + this.showSuggestions(data && (data.length > 1 || (data.length == 1 && this.childs[0].attributes.getNamedItem("spry:suggest").value != val))); + return; + } + + this.previousString = val; + + var url = Spry.Widget.Utils.addReplaceParam(ds.url, this.urlParam, val); + ds.setURL(url); + ds.loadData(); +}; + +Spry.Widget.AutoSuggest.prototype.addMouseListener = function(node, value) +{ + var self = this; + var addListener = Spry.Widget.Utils.addEventListener; + addListener(node, "click", function(e){ return self.nodeClick(e, value); self.handleKeyUp(null);}, false); + addListener(node, "mouseover", function(e){ Spry.Widget.Utils.addClassName(node, self.hoverSuggestClass); self.nodeMouseOver(e, node)}, false); + addListener(node, "mouseout", function(e){ Spry.Widget.Utils.removeClassName(node, self.hoverSuggestClass); self.nodeMouseOver(e, node)}, false); +}; +Spry.Widget.AutoSuggest.prototype.removeMouseListener = function(node, value) +{ + var self = this; + var removeListener = Spry.Widget.Utils.removeEventListener; + removeListener(node, "click", function (e){ self.nodeClick(e, value); self.handleKeyUp(null);}, false); + removeListener(node, "mouseover", function(e){ Spry.Widget.Utils.addClassName(node, self.hoverSuggestClass); self.nodeMouseOver(e, node)}, false); + removeListener(node, "mouseout", function(e){ Spry.Widget.Utils.removeClassName(node, self.hoverSuggestClass); self.nodeMouseOver(e, node)}, false); +}; +Spry.Widget.AutoSuggest.prototype.attachClickBehaviors = function() +{ + var self = this; + var valNodes = Spry.Utils.getNodesByFunc(this.region, function(node) + { + if (node.nodeType == 1) /* Node.ELEMENT_NODE */ + { + var attr = node.attributes.getNamedItem("spry:suggest"); + if (attr){ + self.addMouseListener(node, attr.value); + return true; + } + } + return false; + }); + this.childs = valNodes; +}; +Spry.Widget.AutoSuggest.prototype.removeClickBehaviours = function() +{ + var self = this; + var valNodes = Spry.Utils.getNodesByFunc(this.region, function(node) + { + if (node.nodeType == 1) /* Node.ELEMENT_NODE */ + { + var attr = node.attributes.getNamedItem("spry:suggest"); + if (attr){ + self.removeMouseListener(node, attr.value); + return true; + } + } + return false; + }); +}; +Spry.Widget.AutoSuggest.prototype.destroy = function(){ + + this.removeClickBehaviours(); + Spry.Data.Region.removeObserver(Spry.Widget.Utils.getElementID(this.suggestRegion),this._notifyDataset); + + if (this.event_handlers) + for (var i=0; i0) + { + if(isFirstEntry) + { + camelizedString = oStringList[i]; + isFirstEntry = false; + } + else + { + var s = oStringList[i]; + camelizedString += s.charAt(0).toUpperCase() + s.substring(1); + } + } + } + + return camelizedString; +}; + +Spry.Widget.Utils.getStyleProp = function(element, prop) +{ + var value; + var camel = Spry.Widget.Utils.camelize(prop); + try + { + value = element.style[camel]; + if (!value) + { + if (document.defaultView && document.defaultView.getComputedStyle) + { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css.getPropertyValue(prop) : null; + } + else + if (element.currentStyle) + value = element.currentStyle[camel]; + } + } + catch (e) {} + + return value == 'auto' ? null : value; +}; +Spry.Widget.Utils.makePositioned = function(element) +{ + var pos = Spry.Widget.Utils.getStyleProp(element, 'position'); + if (!pos || pos == 'static') + { + element.style.position = 'relative'; + + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) + { + element.style.top = 0; + element.style.left = 0; + } + } +}; +Spry.Widget.Utils.escapeRegExp = function(rexp) +{ + return rexp.replace(/([\.\/\]\[\{\}\(\)\\\$\^\?\*\|\!\=\+\-])/g, '\\$1'); +}; +Spry.Widget.Utils.getFirstChildWithNodeNameAtAnyLevel = function(node, nodeName) +{ + var elements = node.getElementsByTagName(nodeName); + if (elements) + return elements[0]; + + return null; +}; diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/static/SpryData.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/includes/clientside/static/SpryData.js Sun Jun 22 18:13:59 2008 -0400 @@ -0,0 +1,1045 @@ +// SpryData.js - version 0.45 - Spry Pre-Release 1.6.1 +// +// Copyright (c) 2007. Adobe Systems Incorporated. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Adobe Systems Incorporated nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +var Spry;if(!Spry)Spry={};if(!Spry.Utils)Spry.Utils={};Spry.Utils.msProgIDs=["MSXML2.XMLHTTP.6.0","MSXML2.XMLHTTP.3.0"];Spry.Utils.createXMLHttpRequest=function() +{var req=null;try +{if(window.ActiveXObject) +{while(!req&&Spry.Utils.msProgIDs.length) +{try{req=new ActiveXObject(Spry.Utils.msProgIDs[0]);}catch(e){req=null;} +if(!req) +Spry.Utils.msProgIDs.splice(0,1);}} +if(!req&&window.XMLHttpRequest) +req=new XMLHttpRequest();} +catch(e){req=null;} +if(!req) +Spry.Debug.reportError("Failed to create an XMLHttpRequest object!");return req;};Spry.Utils.loadURL=function(method,url,async,callback,opts) +{var req=new Spry.Utils.loadURL.Request();req.method=method;req.url=url;req.async=async;req.successCallback=callback;Spry.Utils.setOptions(req,opts);try +{req.xhRequest=Spry.Utils.createXMLHttpRequest();if(!req.xhRequest) +return null;if(req.async) +req.xhRequest.onreadystatechange=function(){Spry.Utils.loadURL.callback(req);};req.xhRequest.open(req.method,req.url,req.async,req.username,req.password);if(req.headers) +{for(var name in req.headers) +req.xhRequest.setRequestHeader(name,req.headers[name]);} +req.xhRequest.send(req.postData);if(!req.async) +Spry.Utils.loadURL.callback(req);} +catch(e) +{if(req.errorCallback) +req.errorCallback(req);else +Spry.Debug.reportError("Exception caught while loading "+url+": "+e);req=null;} +return req;};Spry.Utils.loadURL.callback=function(req) +{if(!req||req.xhRequest.readyState!=4) +return;if(req.successCallback&&(req.xhRequest.status==200||req.xhRequest.status==0)) +req.successCallback(req);else if(req.errorCallback) +req.errorCallback(req);};Spry.Utils.loadURL.Request=function() +{var props=Spry.Utils.loadURL.Request.props;var numProps=props.length;for(var i=0;i]*>[\s\r\n]*(<\!--)?|(-->)?[\s\r\n]*<\/script>/img,"");Spry.Utils.eval(s);}}};Spry.Utils.updateContent=function(ele,url,finishFunc,opts) +{Spry.Utils.loadURL("GET",url,true,function(req) +{Spry.Utils.setInnerHTML(ele,req.xhRequest.responseText);if(finishFunc) +finishFunc(ele,url);},opts);};if(!Spry.$$) +{Spry.Utils.addEventListener=function(element,eventType,handler,capture) +{try +{element=Spry.$(element);if(element.addEventListener) +element.addEventListener(eventType,handler,capture);else if(element.attachEvent) +element.attachEvent("on"+eventType,handler);} +catch(e){}};Spry.Utils.removeEventListener=function(element,eventType,handler,capture) +{try +{element=Spry.$(element);if(element.removeEventListener) +element.removeEventListener(eventType,handler,capture);else if(element.detachEvent) +element.detachEvent("on"+eventType,handler);} +catch(e){}};Spry.Utils.addLoadListener=function(handler) +{if(typeof window.addEventListener!='undefined') +window.addEventListener('load',handler,false);else if(typeof document.addEventListener!='undefined') +document.addEventListener('load',handler,false);else if(typeof window.attachEvent!='undefined') +window.attachEvent('onload',handler);};Spry.Utils.addClassName=function(ele,className) +{ele=Spry.$(ele);if(!ele||!className||(ele.className&&ele.className.search(new RegExp("\\b"+className+"\\b"))!=-1)) +return;ele.className+=(ele.className?" ":"")+className;};Spry.Utils.removeClassName=function(ele,className) +{ele=Spry.$(ele);if(!ele||!className||(ele.className&&ele.className.search(new RegExp("\\b"+className+"\\b"))==-1)) +return;ele.className=ele.className.replace(new RegExp("\\s*\\b"+className+"\\b","g"),"");};Spry.Utils.getObjectByName=function(name) +{var result=null;if(name) +{var lu=window;var objPath=name.split(".");for(var i=0;lu&&i1) +{for(var i=0,elements=[],length=arguments.length;i"]/)!=-1) +{str=str.replace(/&/g,"&");str=str.replace(//g,">");str=str.replace(/"/g,""");} +return str};Spry.Utils.decodeEntities=function(str) +{var d=Spry.Utils.decodeEntities.div;if(!d) +{d=document.createElement('div');Spry.Utils.decodeEntities.div=d;if(!d)return str;} +d.innerHTML=str;if(d.childNodes.length==1&&d.firstChild.nodeType==3&&d.firstChild.nextSibling==null) +str=d.firstChild.data;else +{str=str.replace(/</gi,"<");str=str.replace(/>/gi,">");str=str.replace(/"/gi,"\"");str=str.replace(/&/gi,"&");} +return str;};Spry.Utils.fixupIETagAttributes=function(inStr) +{var outStr="";var tagStart=inStr.match(/^<[^\s>]+\s*/)[0];var tagEnd=inStr.match(/\s*\/?>$/)[0];var tagAttrs=inStr.replace(/^<[^\s>]+\s*|\s*\/?>/g,"");outStr+=tagStart;if(tagAttrs) +{var startIndex=0;var endIndex=0;while(startIndex=tagAttrs.length) +{outStr+=tagAttrs.substring(startIndex,endIndex);break;} +++endIndex;outStr+=tagAttrs.substring(startIndex,endIndex);startIndex=endIndex;if(tagAttrs.charAt(endIndex)=='"'||tagAttrs.charAt(endIndex)=="'") +{var savedIndex=endIndex++;while(endIndex]*>|-->|\\]\\](>|\>)","g");var searchStartIndex=0;var skipFixUp=0;while(inStr.length) +{var results=regexp.exec(inStr);if(!results||!results[0]) +{outStr+=inStr.substr(searchStartIndex,inStr.length-searchStartIndex);break;} +if(results.index!=searchStartIndex) +{outStr+=inStr.substr(searchStartIndex,results.index-searchStartIndex);} +if(results[0]==""||results[0]=="]]>"||(skipFixUp&&results[0]=="]]>")) +{--skipFixUp;outStr+=results[0];} +else if(!skipFixUp&&results[0].charAt(0)=='<') +outStr+=Spry.Utils.fixupIETagAttributes(results[0]);else +outStr+=results[0];searchStartIndex=regexp.lastIndex;} +return outStr;};Spry.Utils.stringToXMLDoc=function(str) +{var xmlDoc=null;try +{var xmlDOMObj=new ActiveXObject("Microsoft.XMLDOM");xmlDOMObj.async=false;xmlDOMObj.loadXML(str);xmlDoc=xmlDOMObj;} +catch(e) +{try +{var domParser=new DOMParser;xmlDoc=domParser.parseFromString(str,'text/xml');} +catch(e) +{Spry.Debug.reportError("Caught exception in Spry.Utils.stringToXMLDoc(): "+e+"\n");xmlDoc=null;}} +return xmlDoc;};Spry.Utils.serializeObject=function(obj) +{var str="";var firstItem=true;if(obj==null||obj==undefined) +return str+obj;var objType=typeof obj;if(objType=="number"||objType=="boolean") +str+=obj;else if(objType=="string") +str+="\""+Spry.Utils.escapeQuotesAndLineBreaks(obj)+"\"";else if(obj.constructor==Array) +{str+="[";for(var i=0;i0) +{node=nodeStack.pop();if(node==root) +node=null;else +try{node=node.nextSibling;}catch(e){node=null;}}} +if(nodeStack&&nodeStack.length>0) +Spry.Debug.trace("-- WARNING: Spry.Utils.getNodesByFunc() failed to traverse all nodes!\n");return resultArr;};Spry.Utils.getFirstChildWithNodeName=function(node,nodeName) +{var child=node.firstChild;while(child) +{if(child.nodeName==nodeName) +return child;child=child.nextSibling;} +return null;};Spry.Utils.setOptions=function(obj,optionsObj,ignoreUndefinedProps) +{if(!optionsObj) +return;for(var optionName in optionsObj) +{if(ignoreUndefinedProps&&optionsObj[optionName]==undefined) +continue;obj[optionName]=optionsObj[optionName];}};Spry.Utils.SelectionManager={};Spry.Utils.SelectionManager.selectionGroups=new Object;Spry.Utils.SelectionManager.SelectionGroup=function() +{this.selectedElements=new Array;};Spry.Utils.SelectionManager.SelectionGroup.prototype.select=function(element,className,multiSelect) +{var selObj=null;if(!multiSelect) +{this.clearSelection();} +else +{for(var i=0;i
"+Spry.Utils.encodeEntities(parent.innerHTML)+"
");return false;} +parent=parent.parentNode;}} +if(attr.value) +{attr=node.attributes.getNamedItem("id");if(!attr||!attr.value) +{node.setAttribute("id","spryregion"+(++Spry.Data.initRegions.nextUniqueRegionID));} +lastRegionFound=node;return true;} +else +Spry.Debug.reportError(attrName+" attributes require one or more data set names as values!");}} +catch(e){} +return false;});var name,dataSets,i;var newRegions=[];for(i=0;iPerforming IE innerHTML fix up of Region: "+name+"

"+Spry.Utils.encodeEntities(dataStr));dataStr=Spry.Utils.fixUpIEInnerHTML(dataStr);} +if(Spry.Data.Region.debug) +Spry.Debug.trace("
Region template markup for '"+name+"':

"+Spry.Utils.encodeEntities(dataStr));if(!hasSpryContent) +{rgn.innerHTML="";} +var region=new Spry.Data.Region(rgn,name,isDetailRegion,dataStr,dataSets,regionStates,regionStateMap,hasBehaviorAttributes);Spry.Data.regionsArray[region.name]=region;newRegions.push(region);} +for(var i=0;i0) +this.curRowID=this.data[0]['ds_RowID'];else +this.curRowID=0;};Spry.Data.DataSet.prototype.cancelLoadData=function() +{if(this.pendingRequest&&this.pendingRequest.timer) +clearTimeout(this.pendingRequest.timer);this.pendingRequest=null;};Spry.Data.DataSet.prototype.getRowCount=function(unfiltered) +{var rows=this.getData(unfiltered);return rows?rows.length:0;};Spry.Data.DataSet.prototype.getRowByID=function(rowID) +{if(!this.data) +return null;return this.dataHash[rowID];};Spry.Data.DataSet.prototype.getRowByRowNumber=function(rowNumber,unfiltered) +{var rows=this.getData(unfiltered);if(rows&&rowNumber>=0&&rowNumber=this.data.length) +{Spry.Debug.trace("Invalid row number: "+rowNumber+"\n");return;} +var rowID=this.data[rowNumber]["ds_RowID"];if(rowID==undefined||this.curRowID==rowID) +return;this.setCurrentRow(rowID);};Spry.Data.DataSet.prototype.findRowsWithColumnValues=function(valueObj,firstMatchOnly,unfiltered) +{var results=[];var rows=this.getData(unfiltered);if(rows) +{var numRows=rows.length;for(var i=0;i0)?this.lastSortColumns[0]:"";};Spry.Data.DataSet.prototype.getSortOrder=function(){return this.lastSortOrder?this.lastSortOrder:"";};Spry.Data.DataSet.prototype.sort=function(columnNames,sortOrder) +{if(!columnNames) +return;if(typeof columnNames=="string") +columnNames=[columnNames,"ds_RowID"];else if(columnNames.length<2&&columnNames[0]!="ds_RowID") +columnNames.push("ds_RowID");if(!sortOrder) +sortOrder="toggle";if(sortOrder=="toggle") +{if(this.lastSortColumns.length>0&&this.lastSortColumns[0]==columnNames[0]&&this.lastSortOrder=="ascending") +sortOrder="descending";else +sortOrder="ascending";} +if(sortOrder!="ascending"&&sortOrder!="descending") +{Spry.Debug.reportError("Invalid sort order type specified: "+sortOrder+"\n");return;} +var nData={oldSortColumns:this.lastSortColumns,oldSortOrder:this.lastSortOrder,newSortColumns:columnNames,newSortOrder:sortOrder};this.notifyObservers("onPreSort",nData);var cname=columnNames[columnNames.length-1];var sortfunc=Spry.Data.DataSet.prototype.sort.getSortFunc(cname,this.getColumnType(cname),sortOrder);for(var i=columnNames.length-2;i>=0;i--) +{cname=columnNames[i];sortfunc=Spry.Data.DataSet.prototype.sort.buildSecondarySortFunc(Spry.Data.DataSet.prototype.sort.getSortFunc(cname,this.getColumnType(cname),sortOrder),sortfunc);} +if(this.unfilteredData) +{this.unfilteredData.sort(sortfunc);if(this.filterFunc) +this.filter(this.filterFunc,true);} +else +this.data.sort(sortfunc);this.lastSortColumns=columnNames.slice(0);this.lastSortOrder=sortOrder;this.notifyObservers("onPostSort",nData);};Spry.Data.DataSet.prototype.sort.getSortFunc=function(prop,type,order) +{var sortfunc=null;if(type=="number") +{if(order=="ascending") +sortfunc=function(a,b) +{a=a[prop];b=b[prop];if(a==undefined||b==undefined) +return(a==b)?0:(a?1:-1);return a-b;};else +sortfunc=function(a,b) +{a=a[prop];b=b[prop];if(a==undefined||b==undefined) +return(a==b)?0:(a?-1:1);return b-a;};} +else if(type=="date") +{if(order=="ascending") +sortfunc=function(a,b) +{var dA=a[prop];var dB=b[prop];dA=dA?(new Date(dA)):0;dB=dB?(new Date(dB)):0;return dA-dB;};else +sortfunc=function(a,b) +{var dA=a[prop];var dB=b[prop];dA=dA?(new Date(dA)):0;dB=dB?(new Date(dB)):0;return dB-dA;};} +else +{if(order=="ascending") +sortfunc=function(a,b){a=a[prop];b=b[prop];if(a==undefined||b==undefined) +return(a==b)?0:(a?1:-1);var tA=a.toString();var tB=b.toString();var tA_l=tA.toLowerCase();var tB_l=tB.toLowerCase();var min_len=tA.length>tB.length?tB.length:tA.length;for(var i=0;ib_l_c) +return 1;else if(a_l_cb_c) +return 1;else if(a_ctB.length) +return 1;return-1;};else +sortfunc=function(a,b){a=a[prop];b=b[prop];if(a==undefined||b==undefined) +return(a==b)?0:(a?-1:1);var tA=a.toString();var tB=b.toString();var tA_l=tA.toLowerCase();var tB_l=tB.toLowerCase();var min_len=tA.length>tB.length?tB.length:tA.length;for(var i=0;ib_l_c) +return-1;else if(a_l_cb_c) +return-1;else if(a_ctB.length) +return-1;return 1;};} +return sortfunc;};Spry.Data.DataSet.prototype.sort.buildSecondarySortFunc=function(funcA,funcB) +{return function(a,b) +{var ret=funcA(a,b);if(ret==0) +ret=funcB(a,b);return ret;};};Spry.Data.DataSet.prototype.filterData=function(filterFunc,filterOnly) +{var dataChanged=false;if(!filterFunc) +{this.filterDataFunc=null;dataChanged=true;} +else +{this.filterDataFunc=filterFunc;if(this.dataWasLoaded&&((this.unfilteredData&&this.unfilteredData.length)||(this.data&&this.data.length))) +{if(this.unfilteredData) +{this.data=this.unfilteredData;this.unfilteredData=null;} +var oldData=this.data;this.data=[];this.dataHash={};for(var i=0;i0) +{var self=this;this.loadInterval=interval;this.loadIntervalID=setInterval(function(){self.loadData();},interval);}};Spry.Data.DataSet.prototype.stopLoadInterval=function() +{if(this.loadIntervalID) +clearInterval(this.loadIntervalID);this.loadInterval=0;this.loadIntervalID=null;};Spry.Data.DataSet.nextDataSetID=0;Spry.Data.HTTPSourceDataSet=function(dataSetURL,dataSetOptions) +{Spry.Data.DataSet.call(this);this.url=dataSetURL;this.dataSetsForDataRefStrings=new Array;this.hasDataRefStrings=false;this.useCache=true;this.setRequestInfo(dataSetOptions,true);Spry.Utils.setOptions(this,dataSetOptions,true);this.recalculateDataSetDependencies();if(this.loadInterval>0) +this.startLoadInterval(this.loadInterval);};Spry.Data.HTTPSourceDataSet.prototype=new Spry.Data.DataSet();Spry.Data.HTTPSourceDataSet.prototype.constructor=Spry.Data.HTTPSourceDataSet;Spry.Data.HTTPSourceDataSet.prototype.setRequestInfo=function(requestInfo,undefineRequestProps) +{this.requestInfo=new Spry.Utils.loadURL.Request();this.requestInfo.extractRequestOptions(requestInfo,undefineRequestProps);if(this.requestInfo.method=="POST") +{if(!this.requestInfo.headers) +this.requestInfo.headers={};if(!this.requestInfo.headers['Content-Type']) +this.requestInfo.headers['Content-Type']="application/x-www-form-urlencoded; charset=UTF-8";}};Spry.Data.HTTPSourceDataSet.prototype.recalculateDataSetDependencies=function() +{this.hasDataRefStrings=false;var i=0;for(i=0;i0) +isDOMNodeArray=nodeArray[0].nodeType!=2;var nextID=0;var encodeText=true;var encodeCData=false;if(typeof entityEncodeStrings=="boolean") +encodeText=encodeCData=entityEncodeStrings;for(var i=0;i0) +{var processedSubPaths=[];var numSubPaths=subPaths.length;for(var i=0;iGenerated region markup for '"+this.name+"':

"+Spry.Utils.encodeEntities(str));Spry.Utils.setInnerHTML(this.regionNode,str,!Spry.Data.Region.evalScripts);if(this.hasBehaviorAttributes) +this.attachBehaviors();if(!suppressNotfications) +Spry.Data.Region.notifyObservers("onPostUpdate",this,notificationData);} +if(!suppressNotfications) +Spry.Data.Region.notifyObservers("onPostStateChange",this,stateObj);};Spry.Data.Region.prototype.getDataSets=function() +{return this.dataSets;};Spry.Data.Region.prototype.addDataSet=function(aDataSet) +{if(!aDataSet) +return;if(!this.dataSets) +this.dataSets=new Array;for(var i=0;i1) +{dsName=valArr[0];node.setAttribute(attr,valArr[1]);} +node.setAttribute(rowNumAttrName,"{"+(dsName?(dsName+"::"):"")+"ds_RowNumber}");};Spry.Data.Region.behaviorAttrs["spry:even"]={setup:function(node,value) +{Spry.Data.Region.setUpRowNumberForEvenOddAttr(node,"spry:even",value,"spryevenrownumber");},attach:function(rgn,node,value) +{if(value) +{rowNumAttr=node.attributes.getNamedItem("spryevenrownumber");if(rowNumAttr&&rowNumAttr.value) +{var rowNum=parseInt(rowNumAttr.value);if(rowNum%2) +Spry.Utils.addClassName(node,value);}} +node.removeAttribute("spry:even");node.removeAttribute("spryevenrownumber");}};Spry.Data.Region.behaviorAttrs["spry:odd"]={setup:function(node,value) +{Spry.Data.Region.setUpRowNumberForEvenOddAttr(node,"spry:odd",value,"spryoddrownumber");},attach:function(rgn,node,value) +{if(value) +{rowNumAttr=node.attributes.getNamedItem("spryoddrownumber");if(rowNumAttr&&rowNumAttr.value) +{var rowNum=parseInt(rowNumAttr.value);if(rowNum%2==0) +Spry.Utils.addClassName(node,value);}} +node.removeAttribute("spry:odd");node.removeAttribute("spryoddrownumber");}};Spry.Data.Region.setRowAttrClickHandler=function(node,dsName,rowAttr,funcName) +{if(dsName) +{var ds=Spry.Data.getDataSetByName(dsName);if(ds) +{rowIDAttr=node.attributes.getNamedItem(rowAttr);if(rowIDAttr) +{var rowAttrVal=rowIDAttr.value;if(rowAttrVal) +Spry.Utils.addEventListener(node,"click",function(event){ds[funcName](rowAttrVal);},false);}}}};Spry.Data.Region.behaviorAttrs["spry:setrow"]={setup:function(node,value) +{if(!value) +{Spry.Debug.reportError("The spry:setrow attribute requires a data set name as its value!");node.removeAttribute("spry:setrow");return;} +node.setAttribute("spryrowid","{"+value+"::ds_RowID}");},attach:function(rgn,node,value) +{Spry.Data.Region.setRowAttrClickHandler(node,value,"spryrowid","setCurrentRow");node.removeAttribute("spry:setrow");node.removeAttribute("spryrowid");}};Spry.Data.Region.behaviorAttrs["spry:setrownumber"]={setup:function(node,value) +{if(!value) +{Spry.Debug.reportError("The spry:setrownumber attribute requires a data set name as its value!");node.removeAttribute("spry:setrownumber");return;} +node.setAttribute("spryrownumber","{"+value+"::ds_RowID}");},attach:function(rgn,node,value) +{Spry.Data.Region.setRowAttrClickHandler(node,value,"spryrownumber","setCurrentRowNumber");node.removeAttribute("spry:setrownumber");node.removeAttribute("spryrownumber");}};Spry.Data.Region.behaviorAttrs["spry:sort"]={attach:function(rgn,node,value) +{if(!value) +return;var ds=rgn.getDataSets()[0];var sortOrder="toggle";var colArray=value.split(/\s/);if(colArray.length>1) +{var specifiedDS=Spry.Data.getDataSetByName(colArray[0]);if(specifiedDS) +{ds=specifiedDS;colArray.shift();} +if(colArray.length>1) +{var str=colArray[colArray.length-1];if(str=="ascending"||str=="descending"||str=="toggle") +{sortOrder=str;colArray.pop();}}} +if(ds&&colArray.length>0) +Spry.Utils.addEventListener(node,"click",function(event){ds.sort(colArray,sortOrder);},false);node.removeAttribute("spry:sort");}};Spry.Data.Region.prototype.attachBehaviors=function() +{var rgn=this;Spry.Utils.getNodesByFunc(this.regionNode,function(node) +{if(!node||node.nodeType!=1) +return false;try +{var bAttrs=Spry.Data.Region.behaviorAttrs;for(var bAttrName in bAttrs) +{var attr=node.attributes.getNamedItem(bAttrName);if(attr) +{var behavior=bAttrs[bAttrName];if(behavior&&behavior.attach) +behavior.attach(rgn,node,attr.value);}}}catch(e){} +return false;});};Spry.Data.Region.prototype.updateContent=function() +{var allDataSetsReady=true;var dsArray=this.getDataSets();if(!dsArray||dsArray.length<1) +{Spry.Debug.reportError("updateContent(): Region '"+this.name+"' has no data set!\n");return;} +for(var i=0;i]*>\s*-->/mg;var searchStartIndex=0;var processingContentTag=0;while(inStr.length) +{var results=regexp.exec(inStr);if(!results||!results[0]) +{outStr+=inStr.substr(searchStartIndex,inStr.length-searchStartIndex);break;} +if(!processingContentTag&&results.index!=searchStartIndex) +{outStr+=inStr.substr(searchStartIndex,results.index-searchStartIndex);} +if(results[0].search(/<\//)!=-1) +{--processingContentTag;if(processingContentTag) +Spry.Debug.reportError("Nested spry:content regions are not allowed!\n");} +else +{++processingContentTag;var dataRefStr=results[0].replace(/.*\bdataref="/,"");outStr+=dataRefStr.replace(/".*$/,"");} +searchStartIndex=regexp.lastIndex;} +return outStr;};Spry.Data.Region.prototype.tokenizeData=function(dataStr) +{if(!dataStr) +return null;var rootToken=new Spry.Data.Region.Token(Spry.Data.Region.Token.LIST_TOKEN,null,null,null);var tokenStack=new Array;var parseStr=Spry.Data.Region.processContentPI(dataStr);tokenStack.push(rootToken);var regexp=/((){0,1})|((\{|%7[bB])[^\}\s%]+(\}|%7[dD]))/mg;var searchStartIndex=0;while(parseStr.length) +{var results=regexp.exec(parseStr);var token=null;if(!results||!results[0]) +{var str=parseStr.substr(searchStartIndex,parseStr.length-searchStartIndex);token=new Spry.Data.Region.Token(Spry.Data.Region.Token.STRING_TOKEN,null,str,str);tokenStack[tokenStack.length-1].addChild(token);break;} +if(results.index!=searchStartIndex) +{var str=parseStr.substr(searchStartIndex,results.index-searchStartIndex);token=new Spry.Data.Region.Token(Spry.Data.Region.Token.STRING_TOKEN,null,str,str);tokenStack[tokenStack.length-1].addChild(token);} +if(results[0].search(/^({|%7[bB])/)!=-1) +{var valueName=results[0];var regionStr=results[0];valueName=valueName.replace(/^({|%7[bB])/,"");valueName=valueName.replace(/(}|%7[dD])$/,"");var dataSetName=null;var splitArray=valueName.split(/::/);if(splitArray.length>1) +{dataSetName=splitArray[0];valueName=splitArray[1];} +regionStr=regionStr.replace(/^%7[bB]/,"{");regionStr=regionStr.replace(/%7[dD]$/,"}");token=new Spry.Data.Region.Token(Spry.Data.Region.Token.VALUE_TOKEN,dataSetName,valueName,new String(regionStr));tokenStack[tokenStack.length-1].addChild(token);} +else if(results[0].charAt(0)=='<') +{var piName=results[0].replace(/^(){0,1}|\s.*$/,"");if(results[0].search(/<\//)!=-1) +{if(tokenStack[tokenStack.length-1].tokenType!=Spry.Data.Region.Token.PROCESSING_INSTRUCTION_TOKEN) +{Spry.Debug.reportError("Invalid processing instruction close tag: "+piName+" -- "+results[0]+"\n");return null;} +tokenStack.pop();} +else +{var piDesc=Spry.Data.Region.PI.instructions[piName];if(piDesc) +{var dataSet=null;var selectedDataSetName="";if(results[0].search(/^.*\bselect=\"/)!=-1) +{selectedDataSetName=results[0].replace(/^.*\bselect=\"/,"");selectedDataSetName=selectedDataSetName.replace(/".*$/,"");if(selectedDataSetName) +{dataSet=Spry.Data.getDataSetByName(selectedDataSetName);if(!dataSet) +{Spry.Debug.reportError("Failed to retrieve data set ("+selectedDataSetName+") for "+piName+"\n");selectedDataSetName="";}}} +var jsExpr=null;if(results[0].search(/^.*\btest=\"/)!=-1) +{jsExpr=results[0].replace(/^.*\btest=\"/,"");jsExpr=jsExpr.replace(/".*$/,"");jsExpr=Spry.Utils.decodeEntities(jsExpr);} +var regionState=null;if(results[0].search(/^.*\bname=\"/)!=-1) +{regionState=results[0].replace(/^.*\bname=\"/,"");regionState=regionState.replace(/".*$/,"");regionState=Spry.Utils.decodeEntities(regionState);} +var piData=new Spry.Data.Region.Token.PIData(piName,selectedDataSetName,jsExpr,regionState);token=new Spry.Data.Region.Token(Spry.Data.Region.Token.PROCESSING_INSTRUCTION_TOKEN,dataSet,piData,new String(results[0]));tokenStack[tokenStack.length-1].addChild(token);tokenStack.push(token);} +else +{Spry.Debug.reportError("Unsupported region processing instruction: "+results[0]+"\n");return null;}}} +else +{Spry.Debug.reportError("Invalid region token: "+results[0]+"\n");return null;} +searchStartIndex=regexp.lastIndex;} +return rootToken;};Spry.Data.Region.prototype.callScriptFunction=function(funcName,processContext) +{var result=undefined;funcName=funcName.replace(/^\s*\{?\s*function::\s*|\s*\}?\s*$/g,"");var func=Spry.Utils.getObjectByName(funcName);if(func) +result=func(this.name,function(){return processContext.getValueFromDataSet.apply(processContext,arguments);});return result;};Spry.Data.Region.prototype.evaluateExpression=function(exprStr,processContext) +{var result=undefined;try +{if(exprStr.search(/^\s*function::/)!=-1) +result=this.callScriptFunction(exprStr,processContext);else +result=Spry.Utils.eval(Spry.Data.Region.processDataRefString(processContext,exprStr,null,true));} +catch(e) +{Spry.Debug.trace("Caught exception in Spry.Data.Region.prototype.evaluateExpression() while evaluating: "+Spry.Utils.encodeEntities(exprStr)+"\n Exception:"+e+"\n");} +return result;};Spry.Data.Region.prototype.processTokenChildren=function(outputArr,token,processContext) +{var children=token.children;var len=children.length;for(var i=0;i0&&this.dataSets[0]) +{dataSet=this.dataSets[0];} +if(!dataSet) +{Spry.Debug.reportError("processTokens(): Value reference has no data set specified: "+token.regionStr+"\n");return"";} +val=processContext.getValueFromDataSet(dataSet,token.data);} +if(typeof val!="undefined") +outputArr.push(val+"");break;default:Spry.Debug.reportError("processTokens(): Invalid token type: "+token.regionStr+"\n");break;}};Spry.Data.Region.prototype.transform=function() +{if(this.data&&!this.tokens) +this.tokens=this.tokenizeData(this.data);if(!this.tokens) +return"";processContext=new Spry.Data.Region.ProcessingContext(this);if(!processContext) +return"";var outputArr=[""];this.processTokens(outputArr,this.tokens,processContext);return outputArr.join("");};Spry.Data.Region.PI={};Spry.Data.Region.PI.instructions={};Spry.Data.Region.PI.buildOpenTagForValueAttr=function(ele,piName,attrName) +{if(!ele||!piName) +return"";var jsExpr="";try +{var testAttr=ele.attributes.getNamedItem(piName);if(testAttr&&testAttr.value) +jsExpr=Spry.Utils.encodeEntities(testAttr.value);} +catch(e){jsExpr="";} +if(!jsExpr) +{Spry.Debug.reportError(piName+" attribute requires a JavaScript expression that returns true or false!\n");return"";} +return"<"+Spry.Data.Region.PI.instructions[piName].tagName+" "+attrName+"=\""+jsExpr+"\">";};Spry.Data.Region.PI.buildOpenTagForTest=function(ele,piName) +{return Spry.Data.Region.PI.buildOpenTagForValueAttr(ele,piName,"test");};Spry.Data.Region.PI.buildOpenTagForState=function(ele,piName) +{return Spry.Data.Region.PI.buildOpenTagForValueAttr(ele,piName,"name");};Spry.Data.Region.PI.buildOpenTagForRepeat=function(ele,piName) +{if(!ele||!piName) +return"";var selectAttrStr="";try +{var selectAttr=ele.attributes.getNamedItem(piName);if(selectAttr&&selectAttr.value) +{selectAttrStr=selectAttr.value;selectAttrStr=selectAttrStr.replace(/\s/g,"");}} +catch(e){selectAttrStr="";} +if(!selectAttrStr) +{Spry.Debug.reportError(piName+" attribute requires a data set name!\n");return"";} +var testAttrStr="";try +{var testAttr=ele.attributes.getNamedItem("spry:test");if(testAttr) +{if(testAttr.value) +testAttrStr=" test=\""+Spry.Utils.encodeEntities(testAttr.value)+"\"";ele.attributes.removeNamedItem(testAttr.nodeName);}} +catch(e){testAttrStr="";} +return"<"+Spry.Data.Region.PI.instructions[piName].tagName+" select=\""+selectAttrStr+"\""+testAttrStr+">";};Spry.Data.Region.PI.buildOpenTagForContent=function(ele,piName) +{if(!ele||!piName) +return"";var dataRefStr="";try +{var contentAttr=ele.attributes.getNamedItem(piName);if(contentAttr&&contentAttr.value) +dataRefStr=Spry.Utils.encodeEntities(contentAttr.value);} +catch(e){dataRefStr="";} +if(!dataRefStr) +{Spry.Debug.reportError(piName+" attribute requires a data reference!\n");return"";} +return"<"+Spry.Data.Region.PI.instructions[piName].tagName+" dataref=\""+dataRefStr+"\">";};Spry.Data.Region.PI.buildOpenTag=function(ele,piName) +{return"<"+Spry.Data.Region.PI.instructions[piName].tagName+">";};Spry.Data.Region.PI.buildCloseTag=function(ele,piName) +{return"";};Spry.Data.Region.PI.instructions["spry:state"]={tagName:"spry:state",childrenOnly:false,getOpenTag:Spry.Data.Region.PI.buildOpenTagForState,getCloseTag:Spry.Data.Region.PI.buildCloseTag};Spry.Data.Region.PI.instructions["spry:if"]={tagName:"spry:if",childrenOnly:false,getOpenTag:Spry.Data.Region.PI.buildOpenTagForTest,getCloseTag:Spry.Data.Region.PI.buildCloseTag};Spry.Data.Region.PI.instructions["spry:repeat"]={tagName:"spry:repeat",childrenOnly:false,getOpenTag:Spry.Data.Region.PI.buildOpenTagForRepeat,getCloseTag:Spry.Data.Region.PI.buildCloseTag};Spry.Data.Region.PI.instructions["spry:repeatchildren"]={tagName:"spry:repeat",childrenOnly:true,getOpenTag:Spry.Data.Region.PI.buildOpenTagForRepeat,getCloseTag:Spry.Data.Region.PI.buildCloseTag};Spry.Data.Region.PI.instructions["spry:choose"]={tagName:"spry:choose",childrenOnly:true,getOpenTag:Spry.Data.Region.PI.buildOpenTag,getCloseTag:Spry.Data.Region.PI.buildCloseTag};Spry.Data.Region.PI.instructions["spry:when"]={tagName:"spry:when",childrenOnly:false,getOpenTag:Spry.Data.Region.PI.buildOpenTagForTest,getCloseTag:Spry.Data.Region.PI.buildCloseTag};Spry.Data.Region.PI.instructions["spry:default"]={tagName:"spry:default",childrenOnly:false,getOpenTag:Spry.Data.Region.PI.buildOpenTag,getCloseTag:Spry.Data.Region.PI.buildCloseTag};Spry.Data.Region.PI.instructions["spry:content"]={tagName:"spry:content",childrenOnly:true,getOpenTag:Spry.Data.Region.PI.buildOpenTagForContent,getCloseTag:Spry.Data.Region.PI.buildCloseTag};Spry.Data.Region.PI.orderedInstructions=["spry:state","spry:if","spry:repeat","spry:repeatchildren","spry:choose","spry:when","spry:default","spry:content"];Spry.Data.Region.getTokensFromStr=function(str) +{if(!str) +return null;return str.match(/{[^}]+}/g);};Spry.Data.Region.processDataRefString=function(processingContext,regionStr,dataSetsToUse,isJSExpr) +{if(!regionStr) +return"";if(!processingContext&&!dataSetsToUse) +return regionStr;var resultStr="";var re=new RegExp("\\{([^\\}:]+::)?[^\\}]+\\}","g");var startSearchIndex=0;while(startSearchIndexdata.length) +{Spry.Debug.reportError("Invalid index used in Spry.Data.Region.DSContext.getCurrentRow()!\n");return null;} +return data[curRowIndex];};this.getRowIndex=function() +{var curRowIndex=getInternalRowIndex();if(curRowIndex>=0) +return curRowIndex;return m_dataSet.getRowNumber(m_dataSet.getCurrentRow());};this.setRowIndex=function(rowIndex) +{this.getCurrentState().rowIndex=rowIndex;var data=this.getData();var numChildren=m_children.length;for(var i=0;i0) +return this.dataSetContexts[0];return null;} +if(typeof dataSet=='string') +{dataSet=Spry.Data.getDataSetByName(dataSet);if(!dataSet) +return null;} +for(var i=0;i1) +{dsName=arguments[0];columnName=arguments[1];} +else +{var dataRef=arguments[0].replace(/\s*{\s*|\s*}\s*/g,"");if(dataRef.search("::")!=-1) +{dsName=dataRef.replace(/::.*/,"");columnName=dataRef.replace(/.*::/,"");} +else +columnName=dataRef;} +var result="";var dsContext=this.getDataSetContext(dsName);if(dsContext) +result=dsContext.getValue(columnName,dsContext.getCurrentRow());else +Spry.Debug.reportError("getValueFromDataSet: Failed to get "+dsName+" context for the "+this.region.regionNode.id+" region.\n");return result;};Spry.Data.Region.ProcessingContext.prototype.$v=Spry.Data.Region.ProcessingContext.prototype.getValueFromDataSet;Spry.Data.Region.ProcessingContext.prototype.getCurrentRowForDataSet=function(dataSet) +{var dsc=this.getDataSetContext(dataSet);if(dsc) +return dsc.getCurrentRow();return null;};Spry.Data.Region.Token=function(tokenType,dataSet,data,regionStr) +{var self=this;this.tokenType=tokenType;this.dataSet=dataSet;this.data=data;this.regionStr=regionStr;this.parent=null;this.children=null;};Spry.Data.Region.Token.prototype.addChild=function(child) +{if(!child) +return;if(!this.children) +this.children=new Array;this.children.push(child);child.parent=this;};Spry.Data.Region.Token.LIST_TOKEN=0;Spry.Data.Region.Token.STRING_TOKEN=1;Spry.Data.Region.Token.PROCESSING_INSTRUCTION_TOKEN=2;Spry.Data.Region.Token.VALUE_TOKEN=3;Spry.Data.Region.Token.PIData=function(piName,data,jsExpr,regionState) +{var self=this;this.name=piName;this.data=data;this.jsExpr=jsExpr;this.regionState=regionState;};Spry.Utils.addLoadListener(function(){setTimeout(function(){if(Spry.Data.initRegionsOnLoad)Spry.Data.initRegions();},0);}); \ No newline at end of file diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/static/SpryJSONDataSet.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/includes/clientside/static/SpryJSONDataSet.js Sun Jun 22 18:13:59 2008 -0400 @@ -0,0 +1,142 @@ +// SpryJSONDataSet.js - version 0.6 - Spry Pre-Release 1.6.1 +// +// Copyright (c) 2007. Adobe Systems Incorporated. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Adobe Systems Incorporated nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +Spry.Data.JSONDataSet=function(dataSetURL,dataSetOptions) +{this.path="";this.pathIsObjectOfArrays=false;this.doc=null;this.subPaths=[];this.useParser=false;this.preparseFunc=null;Spry.Data.HTTPSourceDataSet.call(this,dataSetURL,dataSetOptions);var jwType=typeof this.subPaths;if(jwType=="string"||(jwType=="object"&&this.subPaths.constructor!=Array)) +this.subPaths=[this.subPaths];};Spry.Data.JSONDataSet.prototype=new Spry.Data.HTTPSourceDataSet();Spry.Data.JSONDataSet.prototype.constructor=Spry.Data.JSONDataSet;Spry.Data.JSONDataSet.prototype.getDataRefStrings=function() +{var strArr=[];if(this.url)strArr.push(this.url);if(this.path)strArr.push(this.path);if(this.requestInfo&&this.requestInfo.postData)strArr.push(this.requestInfo.postData);return strArr;};Spry.Data.JSONDataSet.prototype.getDocument=function(){return this.doc;};Spry.Data.JSONDataSet.prototype.getPath=function(){return this.path;};Spry.Data.JSONDataSet.prototype.setPath=function(path) +{if(this.path!=path) +{this.path=path;if(this.dataWasLoaded&&this.doc) +{this.notifyObservers("onPreLoad");this.setDataFromDoc(this.doc);}}};Spry.Data.JSONDataSet.getMatchingObjects=function(path,jsonObj) +{var results=[];if(path&&jsonObj) +{var prop="";var leftOverPath="";var offset=path.search(/\./);if(offset!=-1) +{prop=path.substring(0,offset);leftOverPath=path.substring(offset+1);} +else +prop=path;var matches=[];if(prop&&typeof jsonObj=="object") +{var obj=jsonObj[prop];var objType=typeof obj;if(objType!=undefined&&objType!=null) +{if(obj&&objType=="object"&&obj.constructor==Array) +matches=matches.concat(obj);else +matches.push(obj);}} +var numMatches=matches.length;if(leftOverPath) +{for(var i=0;i=1&&typeof matches[0]!="object") +basicColName=path.replace(/.*\./,"");if(!pathIsObjectOfArrays) +{for(var i=0;i userlist.length-1 || n < 0) - { - cel.firstChild.className = 'row2'; - if(cel.firstChild.nextSibling) cel.firstChild.nextSibling.className = 'row2'; - return; - } - - if(dir=='down') no=cel.nextSibling; - else if(dir=='up') no=cel.previousSibling; - no.firstChild.className = 'row2'; - if(no.firstChild.nextSibling) no.firstChild.nextSibling.className = 'row2'; - if(no.firstChild.id) - { - scroll = getScrollOffset() + getHeight(); - elemht = getElementHeight(no.firstChild.id); - elemoff = fetch_offset(no.firstChild); - whereto = elemoff['top'] + elemht; - if(whereto > scroll) - { - window.location.hash = '#'+no.firstChild.id; - unObj.focus(); - } - } - cel=cel.nextSibling; - unObjCurrentSelection = userlist[n]; - index = false; - changed = true; - return; - } - } catch(e) { } - //*/ d = false; - } -} - -function unSelect() -{ - if(!unObj || submitAuthorized) return false; - if ( unObjCurrentSelection ) - unObj.value = unObjCurrentSelection; - destroyUsernameDropdowns(); -} - -function in_array(needle, haystack) -{ - for(var i in haystack) - { - if(haystack[i] == needle) return i; - } - return false; -} - -function ajaxUserNameComplete(o) -{ - if(!o) {destroyUsernameDropdowns(); return;} - if(!o.value) {destroyUsernameDropdowns(); return;} - if(o.value.length < 3) {destroyUsernameDropdowns(); return;} - //if(IE) return; // This control doesn't work in IE. Yes, it's true! document.createElement doesn't work. - if(!o.id) - { - o.id = 'usernametextboxobj_' + Math.floor(Math.random() * 10000000); - } - unObj = o; - o.setAttribute("autocomplete","off"); - o.onkeyup = function(e, o) { o=unObj; if(!nameCompleteEventHandler(e)) ajaxUserNameComplete(o); } - val = escape(o.value).replace('+', '%2B'); - ajaxGet(stdAjaxPrefix+'&_mode=fillusername&name='+val, function() - { - if ( ajax.readyState == 4 && ajax.status == 200 ) - { - // Determine the appropriate left/top positions, then create a div to use for the drop-down list - // The trick here is to be able to make the div dynamically destroy itself depending on how far the user's mouse is from it - destroyUsernameDropdowns(); - off = fetch_offset(unObj); - dim = fetch_dimensions(unObj); - left = off['left']; - i1 = off['top']; - i2 = dim['h']; - var top = 0; - top = i1 + i2; - var thediv = document.createElement('div'); - thediv.className = 'tblholder'; - thediv.style.marginTop = '0px'; - thediv.style.position = 'absolute'; - thediv.style.top = top + 'px'; - thediv.style.left = left + 'px'; - thediv.style.zIndex = getHighestZ() + 2; - id = 'usernamehoverobj_' + Math.floor(Math.random() * 10000000); - unObjDivCurrentId = id; - thediv.id = id; - unObj.onblur = function() { destroyUsernameDropdowns(); } - - var response = String(ajax.responseText) + ' '; - if ( response.substr(0,1) != '{' ) - { - new MessageBox(MB_OK|MB_ICONSTOP, 'Invalid response', 'Invalid or unexpected JSON response from server:
' + ajax.responseText + '
'); - return false; - } - - response = parseJSON(response); - var errorstring = false; - if ( response.mode == 'error' ) - { - errorstring = response.error; - } - else - { - var userlist = response.users_real; - } - - if(errorstring) - { - html = ''+errorstring+''; - } - else - { - html = ''; - cls = 'row2'; - unObjCurrentSelection = userlist[0]; - for(i=0;i'; - if(cls=='row2') cls='row1'; - } - html = html + '
' + $lang.get('user_autofill_heading_suggestions') + '
'+userlist[i]+'
'; - } - - thediv.innerHTML = html; - var body = document.getElementsByTagName('body'); - body = body[0]; - unSelectMenuOn = true; - submitAuthorized = false; - body.appendChild(thediv); - } - }); -} - -function ajaxPageNameComplete(o) -{ - if(!o) {destroyUsernameDropdowns(); return;} - if(!o.value) {destroyUsernameDropdowns(); return;} - if(o.value.length < 3) {destroyUsernameDropdowns(); return;} - if(IE) return; // This control doesn't work in IE. Yes, it's true! document.createElement doesn't work. - if(!o.id) - { - o.id = 'usernametextboxobj_' + Math.floor(Math.random() * 10000000); - } - o.setAttribute("autocomplete","off"); - unObj = o; - o.onkeyup = function(e, o) { o=unObj; if(!nameCompleteEventHandler(e)) ajaxPageNameComplete(o); } - val = escape(o.value).replace('+', '%2B'); - ajaxGet(stdAjaxPrefix+'&_mode=fillpagename&name='+val, function() - { - if(!ajax) return; - if ( ajax.readyState == 4 && ajax.status == 200 ) - { - // Determine the appropriate left/top positions, then create a div to use for the drop-down list - // The trick here is to be able to make the div dynamically destroy itself depending on how far the user's mouse is from it - destroyUsernameDropdowns(); - off = fetch_offset(unObj); - dim = fetch_dimensions(unObj); - left = off['left']; - top = off['top'] + dim['h']; - var thediv = document.createElement('div'); - thediv.className = 'tblholder'; - thediv.style.marginTop = '0px'; - thediv.style.position = 'absolute'; - thediv.style.top = top + 'px'; - thediv.style.left = left + 'px'; - thediv.style.zIndex = getHighestZ() + 2; - id = 'usernamehoverobj_' + Math.floor(Math.random() * 10000000); - unObjDivCurrentId = id; - thediv.id = id; - - eval(ajax.responseText); - if(errorstring) - { - html = ''+errorstring+''; - } - else - { - html = ''; - cls = 'row2'; - unObjCurrentSelection = userlist[0]; - for(i=0;i'; - if(cls=='row2') cls='row1'; - } - html = html + '
' + $lang.get('page_autosuggest_heading') + '
' + $lang.get('page_autosuggest_col_name') + '' + $lang.get('page_autosuggest_col_page_id') + '
'+namelist[i]+''+userlist[i]+'
'; - } - - thediv.innerHTML = html; - var body = document.getElementsByTagName('body'); - body = body[0]; - unSelectMenuOn = true; - submitAuthorized = false; - body.appendChild(thediv); - } - }); -} - -function destroyUsernameDropdowns() -{ - var divs = document.getElementsByTagName('div'); - var prefix = 'usernamehoverobj_'; - for(i=0;i' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + '
{name}
' + "\n" + + '', - this.repeat = false; - this.event = event; - this.box_id = false; - this.boxes = new Array(); - this.state = false; - this.allowanon = ( allowanon ) ? true : false; - - if ( !parent.id ) - parent.id = 'afuser_' + Math.floor(Math.random() * 1000000); - - this.field_id = parent.id; - - // constants - this.KEY_UP = 38; - this.KEY_DOWN = 40; - this.KEY_ESC = 27; - this.KEY_TAB = 9; - this.KEY_ENTER = 13; - - // response cache - this.responses = new Object(); - - // ajax placeholder - this.process_dataset = function(resp_json) + init: function(element, fillclass) { - // window.console.info('Processing the following dataset.'); - // window.console.debug(resp_json); - var autofill = this; + // setup the dataset + window["autofill_region_" + element.id] = new Spry.Data.JSONDataSet(makeUrlNS('Special', 'Autofill', 'type=' + fillclass)); - if ( typeof(autofill.event) == 'object' ) - { - if ( autofill.event.keyCode ) - { - if ( autofill.event.keyCode == autofill.KEY_ENTER && autofill.boxes.length < 1 && !autofill.box_id ) - { - // user hit enter after accepting a suggestion - submit the form - var frm = findParentForm($dynano(autofill.field_id).object); - frm._af_acting = false; - frm.submit(); - // window.console.info('Submitting form'); - return false; - } - if ( autofill.event.keyCode == autofill.KEY_UP || autofill.event.keyCode == autofill.KEY_DOWN || autofill.event.keyCode == autofill.KEY_ESC || autofill.event.keyCode == autofill.KEY_TAB || autofill.event.keyCode == autofill.KEY_ENTER ) - { - autofill.keyhandler(); - // window.console.info('Control key detected, called keyhandler and exiting'); - return true; - } - } - } + // inject our HTML wrapper + var template = this.template.replace(new RegExp('--ID--', 'g'), element.id); + var wrapper = element.parentNode; // document.createElement('div'); + wrapper.id = 'autofill_wrap_' + element.id; - if ( this.box_id ) - { - this.destroy(); - // window.console.info('already have a box open - destroying and exiting'); - //return false; - } - - var users = new Array(); - for ( var i = 0; i < resp_json.users_real.length; i++ ) - { - try - { - var user = resp_json.users_real[i].toLowerCase(); - var inp = $dynano(autofill.field_id).object.value; - inp = inp.toLowerCase(); - if ( user.indexOf(inp) > -1 ) - { - users.push(resp_json.users_real[i]); - } - } - catch(e) - { - users.push(resp_json.users_real[i]); - } - } - - // This was used ONLY for debugging the DOM and list logic - // resp_json.users = resp_json.users_real; + // a bunch of hacks to add a spry wrapper + // var el2 = element.cloneNode(false); + // wrapper.appendChild(el2); + wrapper.innerHTML += template; + // insertAfter(element.parentNode, wrapper, element); + // element.parentNode.removeChild(element); + // element = el2; - // construct table - var div = document.createElement('div'); - div.className = 'tblholder'; - div.style.clip = 'rect(0px,auto,auto,0px)'; - div.style.maxHeight = '200px'; - div.style.overflow = 'auto'; - div.style.zIndex = '9999'; - var table = document.createElement('table'); - table.border = '0'; - table.cellSpacing = '1'; - table.cellPadding = '3'; + var autosuggest = new Spry.Widget.AutoSuggest("autofill_wrap_" + element.id, element.id + '_region', window["autofill_region_" + element.id], 'name', {loadFromServer: true, urlParam: 'userinput', hoverSuggestClass: 'row2', minCharsType: 3}); + } +}; + +function autofill_init_element(element, params) +{ + if ( element.parentNode.id.match(/^autofill_wrap_/) ) + return false; + + params = params || {}; + // assign an ID if it doesn't have one yet + if ( !element.id ) + { + element.id = 'autofill_' + Math.floor(Math.random() * 100000); + } + var id = element.id; + + // get the fill type + var fillclass = element.className; + fillclass = fillclass.split(' '); + fillclass = fillclass[1]; + + var schema = ( autofill_schemas[fillclass] ) ? autofill_schemas[fillclass] : autofill_schemas['generic']; + if ( typeof(schema.init) != 'function' ) + { + schema.init = autofill_schemas.generic.init; + } + schema.init(element, fillclass, params); + + element.af_initted = true; +} + +var autofill_onload = function() +{ + autofill_schemas.username = { + template: '
' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + '
' + $lang.get('user_autofill_heading_suggestions') + '
{name_highlight}
{rank_title}
' + "\n" + + '
', - var tr = document.createElement('tr'); - var th = document.createElement('th'); - th.appendChild(document.createTextNode($lang.get('user_autofill_heading_suggestions'))); - tr.appendChild(th); - table.appendChild(tr); - - if ( users.length < 1 ) + init: function(element, fillclass, params) { - var tr = document.createElement('tr'); - var td = document.createElement('td'); - td.className = 'row1'; - td.appendChild(document.createTextNode($lang.get('user_autofill_msg_no_suggestions'))); - td.afobj = autofill; - tr.appendChild(td); - table.appendChild(tr); - } - else - - for ( var i = 0; i < users.length; i++ ) - { - var user = users[i]; - var tr = document.createElement('tr'); - var td = document.createElement('td'); - td.className = ( i == 0 ) ? 'row2' : 'row1'; - td.appendChild(document.createTextNode(user)); - td.afobj = autofill; - td.style.cursor = 'pointer'; - td.onclick = function() - { - this.afobj.set(this.firstChild.nodeValue); - } - tr.appendChild(td); - table.appendChild(tr); - } + // calculate positions before spry f***s everything up + var top = $dynano(element).Top() + $dynano(element).Height() - 10; // tblholder has 10px top margin + var left = $dynano(element).Left(); - // Finalize div - var tb_top = $dynano(autofill.field_id).Top(); - var tb_height = $dynano(autofill.field_id).Height(); - var af_top = tb_top + tb_height - 9; - var tb_left = $dynano(autofill.field_id).Left(); - var af_left = tb_left; - - div.style.position = 'absolute'; - div.style.left = af_left + 'px'; - div.style.top = af_top + 'px'; - div.style.width = '200px'; - div.style.fontSize = '7pt'; - div.style.fontFamily = 'Trebuchet MS, arial, helvetica, sans-serif'; - div.id = 'afuserdrop_' + Math.floor(Math.random() * 1000000); - div.appendChild(table); - - autofill.boxes.push(div.id); - autofill.box_id = div.id; - if ( users.length > 0 ) - autofill.state = users[0]; - - var body = document.getElementsByTagName('body')[0]; - body.appendChild(div); - - autofill.repeat = true; - } + var allow_anon = ( params.allow_anon ) ? '1' : '0'; + // setup the dataset + window["autofill_region_" + element.id] = new Spry.Data.JSONDataSet(makeUrlNS('Special', 'Autofill', 'type=' + fillclass + '&allow_anon' + allow_anon)); + Spry.Data.initRegions(document.body); + (window["autofill_region_" + element.id]).loadData(); + + // inject our HTML wrapper + var template = this.template.replace(new RegExp('--ID--', 'g'), element.id); + var wrapper = element.parentNode; // document.createElement('div'); + wrapper.id = 'autofill_wrap_' + element.id; + + // a bunch of hacks to add a spry wrapper + wrapper.innerHTML = template + wrapper.innerHTML; + + var autosuggest = new Spry.Widget.AutoSuggest("autofill_wrap_" + element.id, element.id + '_region', window["autofill_region_" + element.id], 'name', {loadFromServer: true, urlParam: 'userinput', hoverSuggestClass: 'row2', minCharsType: 3}); + var regiondiv = document.getElementById(element.id + '_region'); + regiondiv.style.position = 'absolute'; + regiondiv.style.top = top + 'px'; + regiondiv.style.left = left + 'px'; + } + }; - // perform ajax call - this.fetch_and_process = function() - { - af_current = this; - var processResponse = function() - { - if ( ajax.readyState == 4 && ajax.status == 200 ) - { - var afobj = af_current; - af_current = false; - // parse the JSON response - var response = String(ajax.responseText) + ' '; - if ( response.substr(0,1) != '{' ) - { - new MessageBox(MB_OK|MB_ICONSTOP, 'Invalid response', 'Invalid or unexpected JSON response from server:
' + ajax.responseText + '
'); - return false; - } - if ( $dynano(afobj.field_id).object.value.length < 3 ) - return false; - var resp_json = parseJSON(response); - var resp_code = $dynano(afobj.field_id).object.value.toLowerCase().substr(0, 3); - afobj.responses[resp_code] = resp_json; - afobj.process_dataset(resp_json); - } - } - var usernamefragment = ajaxEscape($dynano(this.field_id).object.value); - ajaxGet(stdAjaxPrefix + '&_mode=fillusername&name=' + usernamefragment + '&allowanon=' + ( this.allowanon ? '1' : '0' ), processResponse); + autofill_schemas.page = { + template: '
' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + ' ' + "\n" + + '
' + $lang.get('page_autosuggest_heading') + '
{pid_highlight}
{name_highlight}
' + "\n" + + '
' } - this.go = function() - { - if ( document.getElementById(this.field_id).value.length < 3 ) - { - this.destroy(); - return false; - } - - if ( af_current ) - return false; - - var resp_code = $dynano(this.field_id).object.value.toLowerCase().substr(0, 3); - if ( this.responses.length < 1 || ! this.responses[ resp_code ] ) - { - // window.console.info('Cannot find dataset ' + resp_code + ' in cache, sending AJAX request'); - this.fetch_and_process(); - } - else - { - // window.console.info('Using cached dataset: ' + resp_code); - var resp_json = this.responses[ resp_code ]; - this.process_dataset(resp_json); - } - document.getElementById(this.field_id).onkeyup = function(event) - { - this.afobj.event = event; - this.afobj.go(); - } - document.getElementById(this.field_id).onkeydown = function(event) - { - var form = findParentForm(this); - if ( typeof(event) != 'object' ) - var event = window.event; - if ( typeof(event) == 'object' ) - { - if ( event.keyCode == this.afobj.KEY_ENTER && this.afobj.boxes.length < 1 && !this.afobj.box_id ) - { - // user hit enter after accepting a suggestion - submit the form - form._af_acting = false; - return true; - } - else - { - form._af_acting = true; - return true; - } - } - } - } + var inputs = document.getElementsByClassName('input', 'autofill'); - this.keyhandler = function() - { - var key = this.event.keyCode; - if ( key == this.KEY_ENTER && !this.repeat ) - { - submitAuthorized = true; - var form = findParentForm($dynano(this.field_id).object); - form._af_acting = false; - return true; - } - switch(key) - { - case this.KEY_UP: - this.focus_up(); - break; - case this.KEY_DOWN: - this.focus_down(); - break; - case this.KEY_ESC: - this.destroy(); - break; - case this.KEY_TAB: - this.destroy(); - break; - case this.KEY_ENTER: - this.set(); - break; - } - - var form = findParentForm($dynano(this.field_id).object); - form._af_acting = false; - } - - this.get_state_td = function() - { - var div = document.getElementById(this.box_id); - if ( !div ) - return false; - if ( !this.state ) - return false; - var table = div.firstChild; - for ( var i = 1; i < table.childNodes.length; i++ ) - { - // the table is DOM-constructed so no cruddy HTML hacks :-) - var child = table.childNodes[i]; - var tn = child.firstChild.firstChild; - if ( tn.nodeValue == this.state ) - return child.firstChild; - } - return false; - } - - this.focus_down = function() + for ( var i = 0; i < inputs.length; i++ ) { - var state_td = this.get_state_td(); - if ( !state_td ) - return false; - if ( state_td.parentNode.nextSibling ) - { - // Ooh boy, DOM stuff can be so complicated... - // → - // ↑ ↓ - // user user - - var newstate = state_td.parentNode.nextSibling.firstChild.firstChild.nodeValue; - if ( !newstate ) - return false; - this.state = newstate; - state_td.className = 'row1'; - state_td.parentNode.nextSibling.firstChild.className = 'row2'; - - // Exception - automatically scroll around if the item is off-screen - var height = $dynano(this.box_id).Height(); - var top = $dynano(this.box_id).object.scrollTop; - var scroll_bottom = height + top; - - var td_top = $dynano(state_td.parentNode.nextSibling.firstChild).Top() - $dynano(this.box_id).Top(); - var td_height = $dynano(state_td.parentNode.nextSibling.firstChild).Height(); - var td_bottom = td_top + td_height; - - if ( td_bottom > scroll_bottom ) - { - var scrollY = td_top - height + 2*td_height - 7; - // window.console.debug(scrollY); - $dynano(this.box_id).object.scrollTop = scrollY; - /* - var newtd = state_td.parentNode.nextSibling.firstChild; - var a = document.createElement('a'); - var id = 'autofill' + Math.floor(Math.random() * 100000); - a.name = id; - a.id = id; - newtd.appendChild(a); - window.location.hash = '#' + id; - */ - - // In firefox, scrolling like that makes the field get unfocused - $dynano(this.field_id).object.focus(); - } - } - else - { - return false; - } + autofill_init_element(inputs[i]); } +} + +addOnloadHook(autofill_onload); + +function AutofillUsername(element, event, allowanon) +{ + element.onkeyup = element.onkeydown = element.onkeypress = function(e) {}; - this.focus_up = function() - { - var state_td = this.get_state_td(); - if ( !state_td ) - return false; - if ( state_td.parentNode.previousSibling && state_td.parentNode.previousSibling.firstChild.tagName != 'TH' ) - { - // Ooh boy, DOM stuff can be so complicated... - // ← - // ↓ ↑ - // user user - - var newstate = state_td.parentNode.previousSibling.firstChild.firstChild.nodeValue; - if ( !newstate ) - { - return false; - } - this.state = newstate; - state_td.className = 'row1'; - state_td.parentNode.previousSibling.firstChild.className = 'row2'; - - // Exception - automatically scroll around if the item is off-screen - var top = $dynano(this.box_id).object.scrollTop; - - var td_top = $dynano(state_td.parentNode.previousSibling.firstChild).Top() - $dynano(this.box_id).Top(); - - if ( td_top < top ) - { - $dynano(this.box_id).object.scrollTop = td_top - 10; - /* - var newtd = state_td.parentNode.previousSibling.firstChild; - var a = document.createElement('a'); - var id = 'autofill' + Math.floor(Math.random() * 100000); - a.name = id; - a.id = id; - newtd.appendChild(a); - window.location.hash = '#' + id; - */ - - // In firefox, scrolling like that makes the field get unfocused - $dynano(this.field_id).object.focus(); - } - } - else - { - $dynano(this.box_id).object.scrollTop = 0; - return false; - } - } - - this.destroy = function() - { - this.repeat = false; - var body = document.getElementsByTagName('body')[0]; - var div = document.getElementById(this.box_id); - if ( !div ) - return false; - setTimeout('var body = document.getElementsByTagName("body")[0]; body.removeChild(document.getElementById("'+div.id+'"));', 20); - // hackish workaround for divs that stick around past their welcoming period - for ( var i = 0; i < this.boxes.length; i++ ) - { - var div = document.getElementById(this.boxes[i]); - if ( div ) - setTimeout('var body = document.getElementsByTagName("body")[0]; var div = document.getElementById("'+div.id+'"); if ( div ) body.removeChild(div);', 20); - delete(this.boxes[i]); - } - this.boxes = new Array(); - this.box_id = false; - this.state = false; - } + element.className = 'autofill username'; - this.set = function(val) - { - var ta = document.getElementById(this.field_id); - if ( val ) - ta.value = val; - else if ( this.state ) - ta.value = this.state; - this.destroy(); - findParentForm($dynano(this.field_id.object))._af_acting = false; - } - - this.sleep = function() - { - if ( this.box_id ) - { - var div = document.getElementById(this.box_id); - div.style.display = 'none'; - } - var el = $dynano(this.field_id).object; - var fr = findParentForm(el); - el._af_acting = false; - } - - this.wake = function() - { - if ( this.box_id ) - { - var div = document.getElementById(this.box_id); - div.style.display = 'block'; - } - } - - parent.onblur = function() - { - af_current = this.afobj; - window.setTimeout('if ( af_current ) af_current.sleep(); af_current = false;', 50); - } - - parent.onfocus = function() - { - af_current = this.afobj; - window.setTimeout('if ( af_current ) af_current.wake(); af_current = false;', 50); - } - - parent.afobj = this; - var frm = findParentForm(parent); - if ( frm.onsubmit ) - { - frm.orig_onsubmit = frm.onsubmit; - frm.onsubmit = function(e) - { - if ( this._af_acting ) - return false; - this.orig_onsubmit(e); - } - } - else - { - frm.onsubmit = function() - { - if ( this._af_acting ) - return false; - } - } - - if ( parent.value.length < 3 ) - { - this.destroy(); - return false; - } + allowanon = allowanon ? true : false; + autofill_init_element(element, { + allow_anon: allowanon + }); } function findParentForm(o) diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/static/enano-lib-basic.js --- a/includes/clientside/static/enano-lib-basic.js Wed Jun 18 22:43:16 2008 -0400 +++ b/includes/clientside/static/enano-lib-basic.js Sun Jun 22 18:13:59 2008 -0400 @@ -292,10 +292,10 @@ var thefiles = [ 'dynano.js', 'misc.js', + 'l10n.js', 'login.js', 'admin-menu.js', 'ajax.js', - 'autocomplete.js', 'autofill.js', 'base64.js', 'dropdown.js', @@ -311,7 +311,6 @@ 'sliders.js', 'toolbar.js', 'rijndael.js', - 'l10n.js', 'template-compiler.js', 'acl.js', 'comments.js', @@ -322,6 +321,9 @@ 'theme-manager.js', 'rank-manager.js', 'SpryEffects.js', + 'SpryData.js', + 'SpryJSONDataSet.js', + 'SpryAutoSuggest.js', 'loader.js' ]; diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/static/l10n.js --- a/includes/clientside/static/l10n.js Wed Jun 18 22:43:16 2008 -0400 +++ b/includes/clientside/static/l10n.js Sun Jun 22 18:13:59 2008 -0400 @@ -10,6 +10,7 @@ return false; this.strings = enano_lang[lang_id]; this.lang_id = lang_id; + this.placeholder = false; this.get = function(string_id, subst) { @@ -48,7 +49,10 @@ } -var $lang; +var $lang = { + get: function(t) { return t; }, + placeholder: true +}; var language_onload = function() { diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/static/loader.js --- a/includes/clientside/static/loader.js Wed Jun 18 22:43:16 2008 -0400 +++ b/includes/clientside/static/loader.js Sun Jun 22 18:13:59 2008 -0400 @@ -1,14 +1,13 @@ // Some final stuff - loader routines, etc. +var onload_complete = false; + function mdgInnerLoader(e) { - if(window.location.hash == '#comments') ajaxComments(); - window.onkeydown=isKeyPressed; - window.onkeyup=function(e) { isKeyPressed(e); }; + window.onkeydown = isKeyPressed; + window.onkeyup = function(e) { isKeyPressed(e); }; Fat.fade_all(); fadeInfoBoxes(); - //initTextareas(); - //buildSearchBoxes(); jBoxInit(); if(typeof (dbx_set_key) == 'function') { @@ -17,17 +16,32 @@ initSliders(); runOnloadHooks(e); } + +// if some dumb plugin set an onload function, preserve it var ld; -if(window.onload) ld = window.onload; -else ld = function() {return;}; -function enano_init(e) { +if ( window.onload) +{ + ld = window.onload; +} +else +{ + ld = function() {return;}; +} + +// Enano's main init function. +function enano_init(e) +{ if ( typeof(ld) == 'function' ) { ld(e); } mdgInnerLoader(e); + + // we're loaded; set flags to true + onload_complete = true; } +// don't init the page if less than IE6 if ( typeof(KILL_SWITCH) == 'boolean' && !KILL_SWITCH ) { window.onload = enano_init; diff -r 41c45314ac27 -r 5e8fd89c02ea includes/clientside/static/misc.js --- a/includes/clientside/static/misc.js Wed Jun 18 22:43:16 2008 -0400 +++ b/includes/clientside/static/misc.js Sun Jun 22 18:13:59 2008 -0400 @@ -639,4 +639,17 @@ return haystack.split(needle); } +/** + * Equivalent to PHP's in_array function. + */ + +function in_array(needle, haystack) +{ + for(var i in haystack) + { + if(haystack[i] == needle) return i; + } + return false; +} + addOnloadHook(expander_onload); diff -r 41c45314ac27 -r 5e8fd89c02ea includes/functions.php --- a/includes/functions.php Wed Jun 18 22:43:16 2008 -0400 +++ b/includes/functions.php Sun Jun 22 18:13:59 2008 -0400 @@ -2837,6 +2837,63 @@ } /** + * Replaces all given occurences of needle in haystack, case insensitively. + * @param string Needle + * @param string Thread + * @param string Haystack + * @return string + */ + +function str_replace_i($needle, $thread, $haystack) +{ + $needle_len = strlen($needle); + $haystack_len = strlen($haystack); + for ( $i = 0; $i < $haystack_len; $i++ ) + { + $test = substr($haystack, $i, $needle_len); + if ( strtolower($test) == strtolower($needle) ) + { + // Got it! + $upto = substr($haystack, 0, $i); + $from = substr($haystack, ( $i + $needle_len )); + $haystack = "{$upto}{$thread}{$from}"; + $haystack_len = strlen($haystack); + $i = $i + strlen($thread); + } + } + return $haystack; +} + +/** + * Highlights a term in a string. + * @param string Needle (term to highlight) + * @param string Haystack (search string) + * @param string Starting tag () + * @param string Ending tag () + * @return string + */ + +function highlight_term($needle, $haystack, $start_tag = '', $end_tag = '') +{ + $needle_len = strlen($needle); + $haystack_len = strlen($haystack); + for ( $i = 0; $i < $haystack_len; $i++ ) + { + $test = substr($haystack, $i, $needle_len); + if ( strtolower($test) == strtolower($needle) ) + { + // Got it! + $upto = substr($haystack, 0, $i); + $from = substr($haystack, ( $i + $needle_len )); + $haystack = "{$upto}{$start_tag}{$test}{$end_tag}{$from}"; + $haystack_len = strlen($haystack); + $i = $i + strlen($needle) + strlen($start_tag) + strlen($end_tag); + } + } + return $haystack; +} + +/** * From http://us2.php.net/urldecode - decode %uXXXX * @param string The urlencoded string * @return string diff -r 41c45314ac27 -r 5e8fd89c02ea includes/template.php --- a/includes/template.php Wed Jun 18 22:43:16 2008 -0400 +++ b/includes/template.php Sun Jun 22 18:13:59 2008 -0400 @@ -47,6 +47,7 @@ function __construct() { global $db, $session, $paths, $template, $plugins; // Common objects + $this->tpl_bool = Array(); $this->tpl_strings = Array(); $this->sidebar_extra = ''; @@ -1166,14 +1167,6 @@ header('Content-type: application/xhtml+xml'); } - // Reassign one important variable that can need to be changed after init_vars(): ADDITIONAL_HEADERS - if ( !empty($this->additional_headers) ) - { - $this->assign_vars(array( - 'ADDITIONAL_HEADERS' => $this->additional_headers - )); - } - $headers_sent = true; if(!defined('ENANO_HEADERS_SENT')) define('ENANO_HEADERS_SENT', ''); @@ -1825,7 +1818,7 @@ function username_field($name, $value = false) { $randomid = md5( time() . microtime() . mt_rand() ); - $text = ''; return $text; } diff -r 41c45314ac27 -r 5e8fd89c02ea plugins/SpecialAdmin.php --- a/plugins/SpecialAdmin.php Wed Jun 18 22:43:16 2008 -0400 +++ b/plugins/SpecialAdmin.php Sun Jun 22 18:13:59 2008 -0400 @@ -2019,6 +2019,7 @@ if ( ajax.readyState == 4 && ajax.status == 200 ) { document.getElementById('ajaxPageContainer').innerHTML = ajax.responseText; fadeInfoBoxes(); + autofill_onload(); } }); } diff -r 41c45314ac27 -r 5e8fd89c02ea plugins/SpecialPageFuncs.php --- a/plugins/SpecialPageFuncs.php Wed Jun 18 22:43:16 2008 -0400 +++ b/plugins/SpecialPageFuncs.php Sun Jun 22 18:13:59 2008 -0400 @@ -67,6 +67,13 @@ \'namespace\'=>\'Special\', \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', )); + + $paths->add_page(Array( + \'name\'=>\'specialpage_autofill\', + \'urlname\'=>\'Autofill\', + \'namespace\'=>\'Special\', + \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', + )); '); // function names are IMPORTANT!!! The name pattern is: page__ @@ -828,4 +835,73 @@ $plugins->attachHook('compile_template', 'sidebar_add_tag_cloud();'); +function page_Special_Autofill() +{ + global $db, $session, $paths, $template, $plugins; // Common objects + global $lang; + + header('Content-type: text/javascript'); + + $dataset = array(); + if ( isset($_GET['type']) ) + { + switch($_GET['type']) + { + case 'username': + if ( isset($_GET['userinput']) && strlen($_GET['userinput']) >= 3 ) + { + $search = '%' . escape_string_like($_GET['userinput']) . '%'; + $q = $db->sql_query('SELECT username FROM ' . table_prefix . "users WHERE " . ENANO_SQLFUNC_LOWERCASE . "(username) LIKE '$search' AND user_id > 1"); + if ( !$q ) + $db->die_json(); + + while ( $row = $db->fetchrow() ) + { + $key = array( + 'name' => $row['username'], + 'name_highlight' => highlight_term($_GET['userinput'], $row['username'], '', '') + ); + $key = array_merge($key, $session->get_user_rank($row['username'])); + $key['rank_title'] = $lang->get($key['rank_title']); + $dataset[] = $key; + } + } + break; + case 'page': + if ( isset($_GET['userinput']) && strlen($_GET['userinput']) >= 3 ) + { + $search = '%' . escape_string_like($_GET['userinput']) . '%'; + $q = $db->sql_query('SELECT urlname, namespace, name FROM ' . table_prefix . "users\n" + . " WHERE (\n" + . " " . ENANO_SQLFUNC_LOWERCASE . "(urlname) LIKE '$search'\n" + . " OR " . ENANO_SQLFUNC_LOWERCASE . "(name) LIKE '$search'\n" + . " ) AND user_id > 1"); + if ( !$q ) + $db->die_json(); + + while ( $row = $db->fetchrow() ) + { + $pathskey = ( isset($paths->nslist[$row['namespace']]) ? $paths->nslist[$row['namespace']] : $row['namespace'] . substr($paths->nslist['Special'], -1) ) . $row['urlname']; + $key = array( + 'page_id' => $pathskey, + 'pid_highlight' => highlight_term($_GET['userinput'], dirtify_page_id($pathskey), '', ''), + 'name_highlight' => highlight_term($_GET['userinput'], $row['name'], '', '') + ); + $dataset[] = $key; + } + } + break; + default: + $code = $plugins->setHook('autofill_json_request'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + break; + } + } + + echo enano_json_encode($dataset); +} + ?> \ No newline at end of file