/cfidescripts/ajax/spry/widgets/htmlpanel/SpryHTMLPanel.js
JavaScript | 478 lines | 334 code | 81 blank | 63 comment | 92 complexity | de7b9295535e9f77befcee34bc97b2e5 MD5 | raw file
- // SpryHTMLPanel.js - version 0.4 - Spry Pre-Release 1.6
- //
- // 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.HTMLPanel = function(ele, opts)
- {
- Spry.Widget.HTMLPanel.Notifier.call(this);
- this.element = Spry.Widget.HTMLPanel.$(ele);
- // evalScripts controls whether or not we execute any script that is within
- // an HTML fragment we load into the panel's container. The default value for
- // this comes from our global flag, but users can override this setting for
- // a specific HTMLPanel instance with an evalScripts constructor option.
- this.evalScripts = Spry.Widget.HTMLPanel.evalScripts;
- // These class names are used to identify content *inside* the panel's container
- // when the panel is first created. If the HTMLPanel finds any elements
- // with these class names, it will remove the elements from the document
- // and tuck away their content. The HTMLPanel will then inject this content
- // back into the its container at the appropriate time.
- //
- // This gives the designer an option for specifying content they want shown
- // when the HTMLPanel is loading content or has encountered an error.
- this.loadingContentClass = "HTMLPanelLoadingContent";
- this.errorContentClass = "HTMLPanelErrorContent";
- this.loadingStateContent = "";
- this.errorStateContent = "";
- // These class names are placed on the panel's container whenever the HTMLPanel
- // loads content, or has encountered an error. This is an alternative to specifying
- // content to use during loading and error states. Instead, the designer would simply
- // define CSS rules that use these class names to alter the appearance of the panel's
- // container.
- this.loadingStateClass = "HTMLPanelLoading";
- this.errorStateClass = "HTMLPanelError";
- // The current request that is pending completion.
- this.pendingRequest = null;
- Spry.Widget.HTMLPanel.setOptions(this, opts);
- // Find any content within the panel's container that is supposed to be
- // used for the loading and error states.
- var elements = this.element.getElementsByTagName("*");
- var numElements = elements.length;
- var errorEle = null;
- var loadingEle = null;
- var d = document.createElement("div");
- for (var i = 0; i < numElements && (!loadingEle || !errorEle); i++)
- {
- var e = elements[i];
- if (Spry.Widget.HTMLPanel.hasClassName(e, this.loadingContentClass))
- loadingEle = e;
- if (Spry.Widget.HTMLPanel.hasClassName(e, this.errorContentClass))
- errorEle = e;
- }
- if (loadingEle)
- this.loadingStateContent = Spry.Widget.HTMLPanel.removeAndExtractContent(loadingEle, this.loadingContentClass);
- if (errorEle)
- this.errorStateContent = Spry.Widget.HTMLPanel.removeAndExtractContent(errorEle, this.errorContentClass);
- };
- // Global switch that decides whether or not HTMLPanels execute
- // script embedded within HTML fragments, after the fragment is inserted
- // into the DOM. If false, no HTMLPanel will execute any script embedded
- // within an HTML fragment.
- Spry.Widget.HTMLPanel.evalScripts = false;
- Spry.Widget.HTMLPanel.Notifier = function()
- {
- this.observers = [];
- this.suppressNotifications = 0;
- };
- Spry.Widget.HTMLPanel.Notifier.prototype.addObserver = function(observer)
- {
- if (!observer)
- return;
- // Make sure the observer isn't already on the list.
- var len = this.observers.length;
- for (var i = 0; i < len; i++)
- {
- if (this.observers[i] == observer)
- return;
- }
- this.observers[len] = observer;
- };
- Spry.Widget.HTMLPanel.Notifier.prototype.removeObserver = function(observer)
- {
- if (!observer)
- return;
- for (var i = 0; i < this.observers.length; i++)
- {
- if (this.observers[i] == observer)
- {
- this.observers.splice(i, 1);
- break;
- }
- }
- };
- Spry.Widget.HTMLPanel.Notifier.prototype.notifyObservers = function(methodName, data)
- {
- if (!methodName)
- return;
- if (!this.suppressNotifications)
- {
- var len = this.observers.length;
- for (var i = 0; i < len; i++)
- {
- var obs = this.observers[i];
- if (obs)
- {
- if (typeof obs == "function")
- obs(methodName, this, data);
- else if (obs[methodName])
- obs[methodName](this, data);
- }
- }
- }
- };
- Spry.Widget.HTMLPanel.Notifier.prototype.enableNotifications = function()
- {
- if (--this.suppressNotifications < 0)
- {
- this.suppressNotifications = 0;
- Spry.Debug.reportError("Unbalanced enableNotifications() call!\n");
- }
- };
- Spry.Widget.HTMLPanel.Notifier.prototype.disableNotifications = function()
- {
- ++this.suppressNotifications;
- };
- Spry.Widget.HTMLPanel.prototype = new Spry.Widget.HTMLPanel.Notifier();
- Spry.Widget.HTMLPanel.prototype.constructor = Spry.Widget.HTMLPanel;
- Spry.Widget.HTMLPanel.$ = function(ele)
- {
- if (ele && typeof ele == "string")
- return document.getElementById(ele);
- return ele;
- };
- Spry.Widget.HTMLPanel.setOptions = function(dstObj, srcObj, ignoreUndefinedProps)
- {
- if (srcObj)
- {
- for (var optionName in srcObj)
- {
- if (ignoreUndefinedProps && srcObj[optionName] == undefined)
- continue;
- dstObj[optionName] = srcObj[optionName];
- }
- }
- };
- Spry.Widget.HTMLPanel.addClassName = function(ele, className)
- {
- ele = Spry.Widget.HTMLPanel.$(ele);
- if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))
- return;
- ele.className += (ele.className ? " " : "") + className;
- };
- Spry.Widget.HTMLPanel.removeClassName = function(ele, className)
- {
- ele = Spry.Widget.HTMLPanel.$(ele);
- if (Spry.Widget.HTMLPanel.hasClassName(ele, className))
- ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
- };
- Spry.Widget.HTMLPanel.hasClassName = function(ele, className)
- {
- ele = Spry.Widget.HTMLPanel.$(ele);
- if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)
- return false;
- return true;
- };
- Spry.Widget.HTMLPanel.removeAndExtractContent = function(ele, className)
- {
- var d = document.createElement("div");
- if (ele)
- {
- d.appendChild(ele);
- if (className)
- Spry.Widget.HTMLPanel.removeClassName(ele, className);
- }
- return d.innerHTML;
- };
- Spry.Widget.HTMLPanel.findNodeById = function(id, node)
- {
- if (node && node.nodeType == 1 /* NODE.ELEMENT_NODE */)
- {
- if (node.id == id)
- return node;
- var child = node.firstChild;
- while (child)
- {
- var result = Spry.Widget.HTMLPanel.findNodeById(id, child);
- if (result)
- return result;
- child = child.nextSibling;
- }
- }
- return null;
- };
- Spry.Widget.HTMLPanel.disableSrcReferences = function (source)
- {
- if (source)
- source = source.replace(/<(img|script|link|frame|iframe|input)([^>]+)>/gi, function(a,b,c) {
- // b=tag name, c=tag attributes
- return '<' + b + c.replace(/\b(src|href)\s*=/gi, function(a, b) {
- // b=attribute name
- return 'spry_'+ b + '=';
- }) + '>';
- });
- return source;
- };
- Spry.Widget.HTMLPanel.enableSrcReferences = function (source)
- {
- source = source.replace(/<(img|script|link|frame|iframe|input)([^>]+)>/gi, function(a,b,c) {
- // b=tag name, c=tag attributes
- return '<' + b + c.replace(/\bspry_(src|href)\s*=/gi, function(a, b) {
- // b=attribute name
- return b + '=';
- }) + '>';
- });
- return source;
- };
- Spry.Widget.HTMLPanel.getFragByID = function(id, contentStr)
- {
- var frag = Spry.Widget.HTMLPanel.disableSrcReferences(contentStr);
- var div = document.createElement("div");
- div.innerHTML = frag;
- frag = "";
- var node = Spry.Widget.HTMLPanel.findNodeById(id, div);
- if (node)
- frag = node.innerHTML;
- return Spry.Widget.HTMLPanel.enableSrcReferences(frag);
- };
- Spry.Widget.HTMLPanel.prototype.setContent = function(contentStr, id)
- {
- var data = { content: contentStr, id: id };
- this.notifyObservers("onPreUpdate", data);
- // Observers are allowed to modify the data. Make sure
- // the fragment and id we use are from the data that was
- // past to our observers.
- contentStr = data.content;
- id = data.id;
- // If we have a valid id, extract the markup underneath
- // the element with that id from our html fragment.
- if (typeof id != "undefined")
- contentStr = Spry.Widget.HTMLPanel.getFragByID(id, contentStr);
- // Slam the html fragment into the DOM.
- Spry.Widget.HTMLPanel.setInnerHTML(this.element, contentStr, !this.evalScripts);
- this.removeStateClasses();
- this.notifyObservers("onPostUpdate", data);
- };
- Spry.Widget.HTMLPanel.prototype.loadContent = function(url, opts)
- {
- if (!this.element)
- return;
- this.cancelLoad();
- if (!opts)
- opts = new Object;
- opts.url = opts.url ? opts.url : url;
- opts.method = opts.method ? opts.method : "GET";
- opts.async = opts.async ? opts.async : true;
- opts.id = opts.id ? opts.id : undefined;
- var self = this;
- opts.errorCallback = function(req) { self.onLoadError(req); };
- this.notifyObservers("onPreLoad", opts);
- if (this.loadingStateContent)
- this.setContent(this.loadingStateContent);
- Spry.Widget.HTMLPanel.addClassName(this.element, this.loadingStateClass);
- this.pendingRequest = Spry.Widget.HTMLPanel.loadURL(opts.method, opts.url, opts.async, function(req){ self.onLoadSuccessful(req); }, opts);
- };
- Spry.Widget.HTMLPanel.prototype.cancelLoad = function()
- {
- try
- {
- if (this.pendingRequest && this.pendingRequest.xhRequest)
- {
- var xhr = this.pendingRequest.xhRequest;
- if (xhr.abort)
- xhr.abort();
- xhr.onreadystatechange = null;
- this.notifyObservers("onLoadCancelled", this.pendingRequest);
- }
- }
- catch(e) {}
- this.pendingRequest = null;
- };
- Spry.Widget.HTMLPanel.prototype.removeStateClasses = function()
- {
- Spry.Widget.HTMLPanel.removeClassName(this.element, this.loadingStateClass);
- Spry.Widget.HTMLPanel.removeClassName(this.element, this.errorStateClass);
- };
- Spry.Widget.HTMLPanel.prototype.onLoadSuccessful = function(req)
- {
- this.notifyObservers("onPostLoad", req);
- this.setContent(req.xhRequest.responseText, req.id);
- this.pendingRequest = null;
- };
- Spry.Widget.HTMLPanel.prototype.onLoadError = function(req)
- {
- this.notifyObservers("onLoadError", req);
- if (this.errorStateContent)
- this.setContent(this.errorStateContent);
- Spry.Widget.HTMLPanel.addClassName(this.element, this.errorStateClass);
- this.pendingRequest = null;
- };
- Spry.Widget.HTMLPanel.msProgIDs = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0"];
- Spry.Widget.HTMLPanel.createXMLHttpRequest = function()
- {
- var req = null;
- if (window.ActiveXObject)
- {
- while (!req && Spry.Widget.HTMLPanel.msProgIDs.length)
- {
- try { req = new ActiveXObject(Spry.Widget.HTMLPanel.msProgIDs[0]); } catch (e) { req = null; }
- if (!req)
- Spry.Widget.HTMLPanel.msProgIDs.splice(0, 1);
- }
- }
- if (!req && window.XMLHttpRequest) { try { req = new XMLHttpRequest(); } catch (e) { req = null; } }
- return req;
- };
- Spry.Widget.HTMLPanel.loadURL = function(method, url, async, callback, opts)
- {
- var req = new Object;
- req.method = method;
- req.url = url;
- req.async = async;
- req.successCallback = callback;
- Spry.Widget.HTMLPanel.setOptions(req, opts);
- try
- {
- req.xhRequest = Spry.Widget.HTMLPanel.createXMLHttpRequest();
- if (!req.xhRequest)
- return null;
- if (req.async)
- req.xhRequest.onreadystatechange = function() { Spry.Widget.HTMLPanel.loadURL.callback(req); };
- req.xhRequest.open(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.Widget.HTMLPanel.loadURL.callback(req);
- }
- catch(e) { if (req.errorCallback) req.errorCallback(req); req = null; }
- return req;
- };
- Spry.Widget.HTMLPanel.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.Widget.HTMLPanel.eval = function(str) { return eval(str); };
- Spry.Widget.HTMLPanel.setInnerHTML = function(ele, str, preventScripts)
- {
- if (!ele)
- return;
- if (!str) str = "";
- ele = Spry.Widget.HTMLPanel.$(ele);
- var scriptExpr = "<script[^>]*>(.|\s|\n|\r)*?</script>";
- ele.innerHTML = str.replace(new RegExp(scriptExpr, "img"), "");
- if (preventScripts)
- return;
- var matches = str.match(new RegExp(scriptExpr, "img"));
- if (matches)
- {
- var numMatches = matches.length;
- for (var i = 0; i < numMatches; i++)
- {
- var s = matches[i].replace(/<script[^>]*>[\s\r\n]*(<\!--)?|(-->)?[\s\r\n]*<\/script>/img, "");
- Spry.Widget.HTMLPanel.eval(s);
- }
- }
- };