/* Copyright (c) 2004-2006, The Dojo Foundation All Rights Reserved. Licensed under the Academic Free License version 2.1 or above OR the modified BSD license. For more information on Dojo licensing, see: http://dojotoolkit.org/community/licensing.shtml */ dojo.provide("dojo.widget.html.ContentPane"); dojo.require("dojo.widget.*"); dojo.require("dojo.io.*"); dojo.require("dojo.widget.HtmlWidget"); dojo.require("dojo.widget.ContentPane"); dojo.require("dojo.string"); dojo.require("dojo.string.extras"); dojo.require("dojo.style"); dojo.widget.html.ContentPane = function(){ this._onLoadStack = []; this._onUnLoadStack = []; dojo.widget.HtmlWidget.call(this); } dojo.inherits(dojo.widget.html.ContentPane, dojo.widget.HtmlWidget); dojo.lang.extend(dojo.widget.html.ContentPane, { widgetType: "ContentPane", isContainer: true, // remote loading options adjustPaths: true, href: "", extractContent: true, parseContent: true, cacheContent: true, preload: false, // force load of data even if pane is hidden refreshOnShow: false, handler: "", // generate pane content from a java function executeScripts: false, // if true scripts in content will be evaled after content is set and parsed scriptScope: null, // scopeContainer for downloaded scripts // If the user want a global in the remote script he/she just omitts the var // examples: //-------------------------- // these gets collected by scriptScope and is reached by dojo.widget.byId('..').scriptScope.myCustomproperty // this.myString = "dojo is a great javascript toolkit!"; // // this.alertMyString = function(){ // alert(myString); // } // ------------------------- // these go into the global namespace (window) notice lack of var, equiv to window.myString // myString = "dojo is a javascript toolkit!"; // // alertMyString = function(){ // alert(myString); // } // private _remoteStyles: null, // array of stylenodes inserted to document head // by remote content, used when we clean up for new content _callOnUnLoad: false, // used by setContent and _handleDefults, makes sure onUnLoad is only called once postCreate: function(args, frag, parentComp){ if ( this.handler != "" ){ this.setHandler(this.handler); } if(this.isShowing()||this.preload){ this.loadContents(); } }, show: function(){ // if refreshOnShow is true, reload the contents every time; otherwise, load only the first time if(this.refreshOnShow){ this.refresh(); }else{ this.loadContents(); } dojo.widget.html.ContentPane.superclass.show.call(this); }, refresh: function(){ this.isLoaded=false; this.loadContents(); }, loadContents: function() { if ( this.isLoaded ){ return; } this.isLoaded=true; if ( dojo.lang.isFunction(this.handler)) { this._runHandler(); } else if ( this.href != "" ) { this._downloadExternalContent(this.href, this.cacheContent); } }, setUrl: function(/*String*/ url) { // summary: // Reset the (external defined) content of this pane and replace with new url this.href = url; this.isLoaded = false; if ( this.preload || this.isShowing() ){ this.loadContents(); } }, _downloadExternalContent: function(url, useCache) { this._handleDefaults("Loading...", "onDownloadStart"); var self = this; dojo.io.bind({ url: url, useCache: useCache, preventCache: !useCache, mimetype: "text/html", handler: function(type, data, e) { if(type == "load") { self.onDownloadEnd.call(self, url, data); } else { // works best when from a live server instead of from file system self._handleDefaults.call(self, "Error loading '" + url + "' (" + e.status + " "+ e.statusText + ")", "onDownloadError"); self.onLoad(); } } }); }, // called when setContent is finished onLoad: function(e){ this._runStack("_onLoadStack"); }, // called before old content is cleared onUnLoad: function(e){ this._runStack("_onUnLoadStack"); this.scriptScope = null; }, _runStack: function(stName){ var st = this[stName]; var err = ""; for(var i = 0;i < st.length; i++){ try{ st[i].call(this.scriptScope); }catch(e){ err += "\n"+st[i]+" failed: "+e.description; } } this[stName] = []; if(err.length){ var name = (stName== "_onLoadStack") ? "addOnLoad" : "addOnUnLoad"; this._handleDefaults(name+" failure\n "+err, "onExecError", true); } }, addOnLoad: function(obj, func){ // summary // same as to dojo.addOnLoad but does not take "function_name" as a string this._pushOnStack(this._onLoadStack, obj, func); }, addOnUnLoad: function(obj, func){ // summary // same as to dojo.addUnOnLoad but does not take "function_name" as a string this._pushOnStack(this._onUnLoadStack, obj, func); }, _pushOnStack: function(stack, obj, func){ if(typeof func == 'undefined') { stack.push(obj); }else{ stack.push(function(){ obj[func](); }); } }, destroy: function(){ // make sure we call onUnLoad this.onUnLoad(); dojo.widget.html.ContentPane.superclass.destroy.call(this); }, // called when content script eval error or Java error occurs, preventDefault-able onExecError: function(e){ /*stub*/ }, // called on DOM faults, require fault etc in content, preventDefault-able onContentError: function(e){ /*stub*/ }, // called when download error occurs, preventDefault-able onDownloadError: function(e){ /*stub*/ }, // called before download starts, preventDefault-able onDownloadStart: function(e){ /*stub*/ }, // called when download is finished onDownloadEnd: function(url, data){ data = this.splitAndFixPaths(data, url); this.setContent(data); }, // usefull if user wants to prevent default behaviour ie: _setContent("Error...") _handleDefaults: function(e, handler, useAlert){ if(!handler){ handler = "onContentError"; } if(dojo.lang.isString(e)){ e = { "text": e, "toString": function(){ return this.text; } } } if(typeof e.returnValue != "boolean"){ e.returnValue = true; } if(typeof e.preventDefault != "function"){ e.preventDefault = function(){ this.returnValue = false; } } // call our handler this[handler](e); if(e.returnValue){ if(useAlert){ alert(e.toString()); }else{ if(this._callOnUnLoad){ this.onUnLoad(); // makes sure scripts can clean up after themselves, before we setContent } this._callOnUnLoad = false; // makes sure we dont try to call onUnLoad again on this event, // ie onUnLoad before 'Loading...' but not before clearing 'Loading...' this._setContent(e.toString()); } } }, splitAndFixPaths: function(/*String*/s, /*dojo.uri.Uri?*/url){ // summary: // fixes all remote paths in (hopefully) all cases for example images, remote scripts, links etc. // splits up content in different pieces, scripts, title, style, link and whats left becomes .xml if(!url) { url = "./"; } // point to this page if not set if(!s) { return ""; } // fix up paths in data var titles = []; var scripts = []; var linkStyles = []; var styles = []; var remoteScripts = []; var requires = []; // khtml is much more picky about dom faults, you can't for example attach a style node under body of document // must go into head, as does a title node, so we need to cut out those tags // cut out title tags var match = []; while(match){ match = s.match(/