mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5282 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
706 lines
23 KiB
JavaScript
706 lines
23 KiB
JavaScript
/*
|
|
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.ContentPane");
|
|
|
|
dojo.require("dojo.widget.*");
|
|
dojo.require("dojo.io.*");
|
|
dojo.require("dojo.widget.HtmlWidget");
|
|
dojo.require("dojo.string");
|
|
dojo.require("dojo.string.extras");
|
|
dojo.require("dojo.html.style");
|
|
|
|
|
|
dojo.widget.defineWidget(
|
|
"dojo.widget.ContentPane",
|
|
dojo.widget.HtmlWidget,
|
|
function(){
|
|
// summary:
|
|
// A widget that can be used as a standalone widget
|
|
// or as a baseclass for other widgets
|
|
// Handles replacement of document fragment using either external uri or javascript/java
|
|
// generated markup or DomNode content, instanciating widgets within content and runs scripts.
|
|
// Dont confuse it with an iframe, it only needs document fragments.
|
|
// It's useful as a child of LayoutContainer, SplitContainer, or TabContainer.
|
|
// But note that those classes can contain any widget as a child.
|
|
// scriptScope: Function
|
|
// reference holder to the inline scripts container, if scriptSeparation is true
|
|
// bindArgs: String[]
|
|
// Send in extra args to the dojo.io.bind call
|
|
|
|
// per widgetImpl variables
|
|
this._styleNodes = [];
|
|
this._onLoadStack = [];
|
|
this._onUnloadStack = [];
|
|
this._callOnUnload = false;
|
|
this._ioBindObj;
|
|
// Note:
|
|
// dont change this value externally
|
|
this.scriptScope; // undefined for now
|
|
|
|
// loading option
|
|
// example:
|
|
// bindArgs="preventCache:false;" overrides cacheContent
|
|
this.bindArgs = {};
|
|
|
|
|
|
}, {
|
|
isContainer: true,
|
|
|
|
// loading options
|
|
// adjustPaths: Boolean
|
|
// adjust relative paths in markup to fit this page
|
|
adjustPaths: true,
|
|
|
|
// href: String
|
|
// The href of the content that displays now
|
|
// Set this at construction if you want to load externally,
|
|
// changing href after creation doesnt have any effect, see setUrl
|
|
href: "",
|
|
|
|
// extractContent Boolean: Extract visible content from inside of <body> .... </body>
|
|
extractContent: true,
|
|
|
|
// parseContent Boolean: Construct all widgets that is in content
|
|
parseContent: true,
|
|
|
|
// cacheContent Boolean: Cache content retreived externally
|
|
cacheContent: true,
|
|
|
|
// preload: Boolean
|
|
// Force load of data even if pane is hidden.
|
|
// Note:
|
|
// In order to delay download you need to initially hide the node it constructs from
|
|
preload: false,
|
|
|
|
// refreshOnShow: Boolean
|
|
// Refresh (re-download) content when pane goes from hidden to shown
|
|
refreshOnShow: false,
|
|
|
|
// handler: String||Function
|
|
// Generate pane content from a java function
|
|
// The name of the java proxy function
|
|
handler: "",
|
|
|
|
// executeScripts: Boolean
|
|
// Run scripts within content, extractContent has NO effect on this.
|
|
// Note:
|
|
// if true scripts in content will be evaled after content is innerHTML'ed
|
|
executeScripts: false,
|
|
|
|
// scriptSeparation: Boolean
|
|
// Run scripts in a separate scope, unique for each ContentPane
|
|
scriptSeparation: true,
|
|
|
|
// loadingMessage: String
|
|
// Message that shows while downloading
|
|
loadingMessage: "Loading...",
|
|
|
|
// isLoaded: Boolean
|
|
// Tells loading status
|
|
isLoaded: false,
|
|
|
|
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.ContentPane.superclass.show.call(this);
|
|
},
|
|
|
|
refresh: function(){
|
|
// summary:
|
|
// Force a refresh (re-download) of content, be sure to turn of cache
|
|
this.isLoaded=false;
|
|
this.loadContents();
|
|
},
|
|
|
|
loadContents: function() {
|
|
// summary:
|
|
// Download if isLoaded is false, else ignore
|
|
if ( this.isLoaded ){
|
|
return;
|
|
}
|
|
if ( dojo.lang.isFunction(this.handler)) {
|
|
this._runHandler();
|
|
} else if ( this.href != "" ) {
|
|
this._downloadExternalContent(this.href, this.cacheContent && !this.refreshOnShow);
|
|
}
|
|
},
|
|
|
|
setUrl: function(/*String||dojo.uri.Uri*/ url) {
|
|
// summary:
|
|
// Reset the (external defined) content of this pane and replace with new url
|
|
|
|
// Note:
|
|
// It delays the download until widget is shown if preload is false
|
|
this.href = url;
|
|
this.isLoaded = false;
|
|
if ( this.preload || this.isShowing() ){
|
|
this.loadContents();
|
|
}
|
|
},
|
|
|
|
abort: function(){
|
|
// summary
|
|
// Aborts a inflight download of content
|
|
var bind = this._ioBindObj;
|
|
if(!bind || !bind.abort){ return; }
|
|
bind.abort();
|
|
delete this._ioBindObj;
|
|
},
|
|
|
|
_downloadExternalContent: function(url, useCache) {
|
|
this.abort();
|
|
this._handleDefaults(this.loadingMessage, "onDownloadStart");
|
|
var self = this;
|
|
this._ioBindObj = dojo.io.bind(
|
|
this._cacheSetting({
|
|
url: url,
|
|
mimetype: "text/html",
|
|
handler: function(type, data, xhr){
|
|
delete self._ioBindObj; // makes sure abort doesnt clear cache
|
|
if(type=="load"){
|
|
self.onDownloadEnd.call(self, url, data);
|
|
}else{
|
|
// XHR isnt a normal JS object, IE doesnt have prototype on XHR so we cant extend it or shallowCopy it
|
|
var e = {
|
|
responseText: xhr.responseText,
|
|
status: xhr.status,
|
|
statusText: xhr.statusText,
|
|
responseHeaders: xhr.getAllResponseHeaders(),
|
|
text: "Error loading '" + url + "' (" + xhr.status + " "+ xhr.statusText + ")"
|
|
};
|
|
self._handleDefaults.call(self, e, "onDownloadError");
|
|
self.onLoad();
|
|
}
|
|
}
|
|
}, useCache)
|
|
);
|
|
},
|
|
|
|
_cacheSetting: function(bindObj, useCache){
|
|
for(var x in this.bindArgs){
|
|
if(dojo.lang.isUndefined(bindObj[x])){
|
|
bindObj[x] = this.bindArgs[x];
|
|
}
|
|
}
|
|
|
|
if(dojo.lang.isUndefined(bindObj.useCache)){ bindObj.useCache = useCache; }
|
|
if(dojo.lang.isUndefined(bindObj.preventCache)){ bindObj.preventCache = !useCache; }
|
|
if(dojo.lang.isUndefined(bindObj.mimetype)){ bindObj.mimetype = "text/html"; }
|
|
return bindObj;
|
|
},
|
|
|
|
onLoad: function(e){
|
|
// summary:
|
|
// Event hook, is called after everything is loaded and widgetified
|
|
this._runStack("_onLoadStack");
|
|
this.isLoaded=true;
|
|
},
|
|
|
|
onUnLoad: function(e){
|
|
// summary:
|
|
// Deprecated, use onUnload (lowercased load)
|
|
dojo.deprecated(this.widgetType+".onUnLoad, use .onUnload (lowercased load)", 0.5);
|
|
},
|
|
|
|
onUnload: function(e){
|
|
// summary:
|
|
// Event hook, is called before old content is cleared
|
|
this._runStack("_onUnloadStack");
|
|
delete this.scriptScope;
|
|
// FIXME: remove for 0.5 along with onUnLoad
|
|
if(this.onUnLoad !== dojo.widget.ContentPane.prototype.onUnLoad){
|
|
this.onUnLoad.apply(this, arguments);
|
|
}
|
|
},
|
|
|
|
_runStack: function(stName){
|
|
var st = this[stName]; var err = "";
|
|
var scope = this.scriptScope || window;
|
|
for(var i = 0;i < st.length; i++){
|
|
try{
|
|
st[i].call(scope);
|
|
}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", "debug");
|
|
}
|
|
},
|
|
|
|
addOnLoad: function(obj, func){
|
|
// summary
|
|
// Stores function refs and calls them one by one in the order they came in
|
|
// when load event occurs.
|
|
// obj: Function||Object?
|
|
// holder object
|
|
// func: Function
|
|
// function that will be called
|
|
this._pushOnStack(this._onLoadStack, obj, func);
|
|
},
|
|
|
|
addOnUnload: function(obj, func){
|
|
// summary
|
|
// Stores function refs and calls them one by one in the order they came in
|
|
// when unload event occurs.
|
|
// obj: Function||Object
|
|
// holder object
|
|
// func: Function
|
|
// function that will be called
|
|
this._pushOnStack(this._onUnloadStack, obj, func);
|
|
},
|
|
|
|
addOnUnLoad: function(){
|
|
// summary:
|
|
// Deprecated use addOnUnload (lower cased load)
|
|
dojo.deprecated(this.widgetType + ".addOnUnLoad, use addOnUnload instead. (lowercased Load)", 0.5);
|
|
this.addOnUnload.apply(this, arguments);
|
|
},
|
|
|
|
_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.ContentPane.superclass.destroy.call(this);
|
|
},
|
|
|
|
onExecError: function(/*Object*/e){
|
|
// summary:
|
|
// called when content script eval error or Java error occurs, preventDefault-able
|
|
// default is to debug not alert as in 0.3.1
|
|
},
|
|
|
|
onContentError: function(/*Object*/e){
|
|
// summary:
|
|
// called on DOM faults, require fault etc in content, preventDefault-able
|
|
// default is to display errormessage inside pane
|
|
},
|
|
|
|
onDownloadError: function(/*Object*/e){
|
|
// summary:
|
|
// called when download error occurs, preventDefault-able
|
|
// default is to display errormessage inside pane
|
|
},
|
|
|
|
onDownloadStart: function(/*Object*/e){
|
|
// summary:
|
|
// called before download starts, preventDefault-able
|
|
// default is to display loadingMessage inside pane
|
|
// by changing e.text in your event handler you can change loading message
|
|
},
|
|
|
|
//
|
|
onDownloadEnd: function(url, data){
|
|
// summary:
|
|
// called when download is finished
|
|
//
|
|
// url String: url that downloaded data
|
|
// data String: the markup that was downloaded
|
|
data = this.splitAndFixPaths(data, url);
|
|
this.setContent(data);
|
|
},
|
|
|
|
// useful if user wants to prevent default behaviour ie: _setContent("Error...")
|
|
_handleDefaults: function(e, handler, messType){
|
|
if(!handler){ handler = "onContentError"; }
|
|
|
|
if(dojo.lang.isString(e)){ e = {text: e}; }
|
|
|
|
if(!e.text){ e.text = e.toString(); }
|
|
|
|
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){
|
|
switch(messType){
|
|
case true: // fallthrough, old compat
|
|
case "alert":
|
|
alert(e.toString()); break;
|
|
case "debug":
|
|
dojo.debug(e.toString()); break;
|
|
default:
|
|
// makes sure scripts can clean up after themselves, before we setContent
|
|
if(this._callOnUnload){ this.onUnload(); }
|
|
// makes sure we dont try to call onUnLoad again on this event,
|
|
// ie onUnLoad before 'Loading...' but not before clearing 'Loading...'
|
|
this._callOnUnload = false;
|
|
|
|
// we might end up in a endless recursion here if domNode cant append content
|
|
if(arguments.callee._loopStop){
|
|
dojo.debug(e.toString());
|
|
}else{
|
|
arguments.callee._loopStop = true;
|
|
this._setContent(e.toString());
|
|
}
|
|
}
|
|
}
|
|
arguments.callee._loopStop = false;
|
|
},
|
|
|
|
// pathfixes, require calls, css stuff and neccesary content clean
|
|
splitAndFixPaths: function(s, url){
|
|
// summary:
|
|
// adjusts all relative paths in (hopefully) all cases, images, remote scripts, links etc.
|
|
// splits up content in different pieces, scripts, title, style, link and whats left becomes .xml
|
|
// s String: The markup in string
|
|
// url (String||dojo.uri.Uri?) url that pulled in markup
|
|
|
|
var titles = [], scripts = [],tmp = [];// init vars
|
|
var match = [], requires = [], attr = [], styles = [];
|
|
var str = '', path = '', fix = '', tagFix = '', tag = '', origPath = '';
|
|
|
|
if(!url) { url = "./"; } // point to this page if not set
|
|
|
|
if(s){ // make sure we dont run regexes on empty content
|
|
|
|
/************** <title> ***********/
|
|
// khtml is picky about dom faults, you can't attach a <style> or <title> node as child of body
|
|
// must go into head, so we need to cut out those tags
|
|
var regex = /<title[^>]*>([\s\S]*?)<\/title>/i;
|
|
while(match = regex.exec(s)){
|
|
titles.push(match[1]);
|
|
s = s.substring(0, match.index) + s.substr(match.index + match[0].length);
|
|
};
|
|
|
|
/************** adjust paths *****************/
|
|
if(this.adjustPaths){
|
|
// attributepaths one tag can have multiple paths example:
|
|
// <input src="..." style="url(..)"/> or <a style="url(..)" href="..">
|
|
// strip out the tag and run fix on that.
|
|
// this guarantees that we won't run replace on another tag's attribute + it was easier do
|
|
var regexFindTag = /<[a-z][a-z0-9]*[^>]*\s(?:(?:src|href|style)=[^>])+[^>]*>/i;
|
|
var regexFindAttr = /\s(src|href|style)=(['"]?)([\w()\[\]\/.,\\'"-:;#=&?\s@]+?)\2/i;
|
|
// these are the supported protocols, all other is considered relative
|
|
var regexProtocols = /^(?:[#]|(?:(?:https?|ftps?|file|javascript|mailto|news):))/;
|
|
|
|
while(tag = regexFindTag.exec(s)){
|
|
str += s.substring(0, tag.index);
|
|
s = s.substring((tag.index + tag[0].length), s.length);
|
|
tag = tag[0];
|
|
|
|
// loop through attributes
|
|
tagFix = '';
|
|
while(attr = regexFindAttr.exec(tag)){
|
|
path = ""; origPath = attr[3];
|
|
switch(attr[1].toLowerCase()){
|
|
case "src":// falltrough
|
|
case "href":
|
|
if(regexProtocols.exec(origPath)){
|
|
path = origPath;
|
|
} else {
|
|
path = (new dojo.uri.Uri(url, origPath).toString());
|
|
}
|
|
break;
|
|
case "style":// style
|
|
path = dojo.html.fixPathsInCssText(origPath, url);
|
|
break;
|
|
default:
|
|
path = origPath;
|
|
}
|
|
fix = " " + attr[1] + "=" + attr[2] + path + attr[2];
|
|
// slices up tag before next attribute check
|
|
tagFix += tag.substring(0, attr.index) + fix;
|
|
tag = tag.substring((attr.index + attr[0].length), tag.length);
|
|
}
|
|
str += tagFix + tag; //dojo.debug(tagFix + tag);
|
|
}
|
|
s = str+s;
|
|
}
|
|
|
|
/**************** cut out all <style> and <link rel="stylesheet" href=".."> **************/
|
|
regex = /(?:<(style)[^>]*>([\s\S]*?)<\/style>|<link ([^>]*rel=['"]?stylesheet['"]?[^>]*)>)/i;
|
|
while(match = regex.exec(s)){
|
|
if(match[1] && match[1].toLowerCase() == "style"){
|
|
styles.push(dojo.html.fixPathsInCssText(match[2],url));
|
|
}else if(attr = match[3].match(/href=(['"]?)([^'">]*)\1/i)){
|
|
styles.push({path: attr[2]});
|
|
}
|
|
s = s.substring(0, match.index) + s.substr(match.index + match[0].length);
|
|
};
|
|
|
|
/***************** cut out all <script> tags, push them into scripts array ***************/
|
|
var regex = /<script([^>]*)>([\s\S]*?)<\/script>/i;
|
|
var regexSrc = /src=(['"]?)([^"']*)\1/i;
|
|
var regexDojoJs = /.*(\bdojo\b\.js(?:\.uncompressed\.js)?)$/;
|
|
var regexInvalid = /(?:var )?\bdjConfig\b(?:[\s]*=[\s]*\{[^}]+\}|\.[\w]*[\s]*=[\s]*[^;\n]*)?;?|dojo\.hostenv\.writeIncludes\(\s*\);?/g;
|
|
var regexRequires = /dojo\.(?:(?:require(?:After)?(?:If)?)|(?:widget\.(?:manager\.)?registerWidgetPackage)|(?:(?:hostenv\.)?setModulePrefix|registerModulePath)|defineNamespace)\((['"]).*?\1\)\s*;?/;
|
|
|
|
while(match = regex.exec(s)){
|
|
if(this.executeScripts && match[1]){
|
|
if(attr = regexSrc.exec(match[1])){
|
|
// remove a dojo.js or dojo.js.uncompressed.js from remoteScripts
|
|
// we declare all files named dojo.js as bad, regardless of path
|
|
if(regexDojoJs.exec(attr[2])){
|
|
dojo.debug("Security note! inhibit:"+attr[2]+" from being loaded again.");
|
|
}else{
|
|
scripts.push({path: attr[2]});
|
|
}
|
|
}
|
|
}
|
|
if(match[2]){
|
|
// remove all invalid variables etc like djConfig and dojo.hostenv.writeIncludes()
|
|
var sc = match[2].replace(regexInvalid, "");
|
|
if(!sc){ continue; }
|
|
|
|
// cut out all dojo.require (...) calls, if we have execute
|
|
// scripts false widgets dont get there require calls
|
|
// takes out possible widgetpackage registration as well
|
|
while(tmp = regexRequires.exec(sc)){
|
|
requires.push(tmp[0]);
|
|
sc = sc.substring(0, tmp.index) + sc.substr(tmp.index + tmp[0].length);
|
|
}
|
|
if(this.executeScripts){
|
|
scripts.push(sc);
|
|
}
|
|
}
|
|
s = s.substr(0, match.index) + s.substr(match.index + match[0].length);
|
|
}
|
|
|
|
/********* extract content *********/
|
|
if(this.extractContent){
|
|
match = s.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
|
|
if(match) { s = match[1]; }
|
|
}
|
|
|
|
/*** replace scriptScope prefix in html Event handler
|
|
* working order: find tags with scriptScope in a tag attribute
|
|
* then replace all standalone scriptScope occurencies with reference to to this widget
|
|
* valid onClick="scriptScope.func()" or onClick="scriptScope['func']();scriptScope.i++"
|
|
* not valid onClick="var.scriptScope.ref" nor onClick="var['scriptScope'].ref" */
|
|
if(this.executeScripts && this.scriptSeparation){
|
|
var regex = /(<[a-zA-Z][a-zA-Z0-9]*\s[^>]*?\S=)((['"])[^>]*scriptScope[^>]*>)/;
|
|
var regexAttr = /([\s'";:\(])scriptScope(.*)/; // we rely on that attribute begins ' or "
|
|
str = "";
|
|
while(tag = regex.exec(s)){
|
|
tmp = ((tag[3]=="'") ? '"': "'");fix= "";
|
|
str += s.substring(0, tag.index) + tag[1];
|
|
while(attr = regexAttr.exec(tag[2])){
|
|
tag[2] = tag[2].substring(0, attr.index) + attr[1] + "dojo.widget.byId("+ tmp + this.widgetId + tmp + ").scriptScope" + attr[2];
|
|
}
|
|
str += tag[2];
|
|
s = s.substr(tag.index + tag[0].length);
|
|
}
|
|
s = str + s;
|
|
}
|
|
}
|
|
|
|
return {"xml": s, // Object
|
|
"styles": styles,
|
|
"titles": titles,
|
|
"requires": requires,
|
|
"scripts": scripts,
|
|
"url": url};
|
|
},
|
|
|
|
|
|
_setContent: function(cont){
|
|
this.destroyChildren();
|
|
|
|
// remove old stylenodes from HEAD
|
|
for(var i = 0; i < this._styleNodes.length; i++){
|
|
if(this._styleNodes[i] && this._styleNodes[i].parentNode){
|
|
this._styleNodes[i].parentNode.removeChild(this._styleNodes[i]);
|
|
}
|
|
}
|
|
this._styleNodes = [];
|
|
|
|
try{
|
|
var node = this.containerNode || this.domNode;
|
|
while(node.firstChild){
|
|
dojo.html.destroyNode(node.firstChild);
|
|
}
|
|
if(typeof cont != "string"){
|
|
node.appendChild(cont);
|
|
}else{
|
|
node.innerHTML = cont;
|
|
}
|
|
}catch(e){
|
|
e.text = "Couldn't load content:"+e.description;
|
|
this._handleDefaults(e, "onContentError");
|
|
}
|
|
},
|
|
|
|
setContent: function(data){
|
|
// summary:
|
|
// Replaces old content with data content, include style classes from old content
|
|
// data String||DomNode: new content, be it Document fragment or a DomNode chain
|
|
// If data contains style tags, link rel=stylesheet it inserts those styles into DOM
|
|
this.abort();
|
|
if(this._callOnUnload){ this.onUnload(); }// this tells a remote script clean up after itself
|
|
this._callOnUnload = true;
|
|
|
|
if(!data || dojo.html.isNode(data)){
|
|
// if we do a clean using setContent(""); or setContent(#node) bypass all parsing, extractContent etc
|
|
this._setContent(data);
|
|
this.onResized();
|
|
this.onLoad();
|
|
}else{
|
|
// need to run splitAndFixPaths? ie. manually setting content
|
|
// adjustPaths is taken care of inside splitAndFixPaths
|
|
if(typeof data.xml != "string"){
|
|
this.href = ""; // so we can refresh safely
|
|
data = this.splitAndFixPaths(data);
|
|
}
|
|
|
|
this._setContent(data.xml);
|
|
|
|
// insert styles from content (in same order they came in)
|
|
for(var i = 0; i < data.styles.length; i++){
|
|
if(data.styles[i].path){
|
|
this._styleNodes.push(dojo.html.insertCssFile(data.styles[i].path, dojo.doc(), false, true));
|
|
}else{
|
|
this._styleNodes.push(dojo.html.insertCssText(data.styles[i]));
|
|
}
|
|
}
|
|
|
|
if(this.parseContent){
|
|
for(var i = 0; i < data.requires.length; i++){
|
|
try{
|
|
eval(data.requires[i]);
|
|
} catch(e){
|
|
e.text = "ContentPane: error in package loading calls, " + (e.description||e);
|
|
this._handleDefaults(e, "onContentError", "debug");
|
|
}
|
|
}
|
|
}
|
|
// need to allow async load, Xdomain uses it
|
|
// is inline function because we cant send args to dojo.addOnLoad
|
|
var _self = this;
|
|
function asyncParse(){
|
|
if(_self.executeScripts){
|
|
_self._executeScripts(data.scripts);
|
|
}
|
|
|
|
if(_self.parseContent){
|
|
var node = _self.containerNode || _self.domNode;
|
|
var parser = new dojo.xml.Parse();
|
|
var frag = parser.parseElement(node, null, true);
|
|
// createSubComponents not createComponents because frag has already been created
|
|
dojo.widget.getParser().createSubComponents(frag, _self);
|
|
}
|
|
|
|
_self.onResized();
|
|
_self.onLoad();
|
|
}
|
|
// try as long as possible to make setContent sync call
|
|
if(dojo.hostenv.isXDomain && data.requires.length){
|
|
dojo.addOnLoad(asyncParse);
|
|
}else{
|
|
asyncParse();
|
|
}
|
|
}
|
|
},
|
|
|
|
setHandler: function(/*Function*/ handler) {
|
|
// summary:
|
|
// Generate pane content from given java function
|
|
var fcn = dojo.lang.isFunction(handler) ? handler : window[handler];
|
|
if(!dojo.lang.isFunction(fcn)) {
|
|
// FIXME: needs testing! somebody with java knowledge needs to try this
|
|
this._handleDefaults("Unable to set handler, '" + handler + "' not a function.", "onExecError", true);
|
|
return;
|
|
}
|
|
this.handler = function() {
|
|
return fcn.apply(this, arguments);
|
|
}
|
|
},
|
|
|
|
_runHandler: function() {
|
|
var ret = true;
|
|
if(dojo.lang.isFunction(this.handler)) {
|
|
this.handler(this, this.domNode);
|
|
ret = false;
|
|
}
|
|
this.onLoad();
|
|
return ret;
|
|
},
|
|
|
|
_executeScripts: function(scripts) {
|
|
// loop through the scripts in the order they came in
|
|
var self = this;
|
|
var tmp = "", code = "";
|
|
for(var i = 0; i < scripts.length; i++){
|
|
if(scripts[i].path){ // remotescript
|
|
dojo.io.bind(this._cacheSetting({
|
|
"url": scripts[i].path,
|
|
"load": function(type, scriptStr){
|
|
dojo.lang.hitch(self, tmp = ";"+scriptStr);
|
|
},
|
|
"error": function(type, error){
|
|
error.text = type + " downloading remote script";
|
|
self._handleDefaults.call(self, error, "onExecError", "debug");
|
|
},
|
|
"mimetype": "text/plain",
|
|
"sync": true
|
|
}, this.cacheContent));
|
|
code += tmp;
|
|
}else{
|
|
code += scripts[i];
|
|
}
|
|
}
|
|
|
|
|
|
try{
|
|
if(this.scriptSeparation){
|
|
// initialize a new anonymous container for our script, dont make it part of this widgets scope chain
|
|
// instead send in a variable that points to this widget, useful to connect events to onLoad, onUnload etc..
|
|
delete this.scriptScope;
|
|
this.scriptScope = new (new Function('_container_', code+'; return this;'))(self);
|
|
}else{
|
|
// exec in global, lose the _container_ feature
|
|
var djg = dojo.global();
|
|
if(djg.execScript){
|
|
djg.execScript(code);
|
|
}else{
|
|
var djd = dojo.doc();
|
|
var sc = djd.createElement("script");
|
|
sc.appendChild(djd.createTextNode(code));
|
|
(this.containerNode||this.domNode).appendChild(sc);
|
|
}
|
|
}
|
|
}catch(e){
|
|
e.text = "Error running scripts from content:\n"+e.description;
|
|
this._handleDefaults(e, "onExecError", "debug");
|
|
}
|
|
}
|
|
}
|
|
);
|