123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- if (!dojo._hasResource["dojox.layout.ContentPane"]) { // _hasResource checks
- // added by build. Do
- // not use _hasResource
- // directly in your
- // code.
- dojo._hasResource["dojox.layout.ContentPane"] = true;
- dojo.provide("dojox.layout.ContentPane");
- dojo.require("dijit.layout.ContentPane");
- (function() { // private scope, sort of a namespace
- // TODO: should these methods be moved to dojox.html.cssPathAdjust or
- // something?
- // css at-rules must be set before any css declarations according to CSS
- // spec
- // match:
- // @import 'http://dojotoolkit.org/dojo.css';
- // @import 'you/never/thought/' print;
- // @import url("it/would/work") tv, screen;
- // @import url(/did/you/now.css);
- // but not:
- // @namespace dojo "http://dojotoolkit.org/dojo.css"; /* namespace URL
- // should always be a absolute URI */
- // @charset 'utf-8';
- // @media print{ #menuRoot {display:none;} }
- // we adjust all paths that dont start on '/' or contains ':'
- // (?![a-z]+:|\/)
- if (dojo.isIE) {
- var alphaImageLoader = /(AlphaImageLoader\([^)]*?src=(['"]))(?![a-z]+:|\/)([^\r\n;}]+?)(\2[^)]*\)\s*[;}]?)/g;
- }
- var cssPaths = /(?:(?:@import\s*(['"])(?![a-z]+:|\/)([^\r\n;{]+?)\1)|url\(\s*(['"]?)(?![a-z]+:|\/)([^\r\n;]+?)\3\s*\))([a-z, \s]*[;}]?)/g;
- function adjustCssPaths(cssUrl, cssText) {
- // summary:
- // adjusts relative paths in cssText to be relative to cssUrl
- // a path is considered relative if it doesn't start with '/' and
- // not contains ':'
- // description:
- // Say we fetch a HTML page from level1/page.html
- // It has some inline CSS:
- // @import "css/page.css" tv, screen;
- // ...
- // background-image: url(images/aplhaimage.png);
- //
- // as we fetched this HTML and therefore this CSS
- // from level1/page.html, these paths needs to be adjusted to:
- // @import 'level1/css/page.css' tv, screen;
- // ...
- // background-image: url(level1/images/alphaimage.png);
- //
- // In IE it will also adjust relative paths in AlphaImageLoader()
- // filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/alphaimage.png');
- // will be adjusted to:
- // filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='level1/images/alphaimage.png');
- //
- // Please note that any relative paths in AlphaImageLoader in
- // external css files wont work, as
- // the paths in AlphaImageLoader is MUST be declared relative to the
- // HTML page,
- // not relative to the CSS file that declares it
- if (!cssText || !cssUrl) {
- return;
- }
- // support the ImageAlphaFilter if it exists, most people use it in
- // IE 6 for transparent PNGs
- // We are NOT going to kill it in IE 7 just because the PNGs work
- // there. Somebody might have
- // other uses for it.
- // If user want to disable css filter in IE6 he/she should
- // unset filter in a declaration that just IE 6 doesn't understands
- // like * > .myselector { filter:none; }
- if (alphaImageLoader) {
- cssText = cssText.replace(alphaImageLoader, function(ignore,
- pre, delim, url, post) {
- return pre
- + (new dojo._Url(cssUrl, './' + url)
- .toString()) + post;
- });
- }
- return cssText.replace(cssPaths, function(ignore, delimStr, strUrl,
- delimUrl, urlUrl, media) {
- if (strUrl) {
- return '@import "'
- + (new dojo._Url(cssUrl, './' + strUrl)
- .toString()) + '"' + media;
- } else {
- return 'url('
- + (new dojo._Url(cssUrl, './' + urlUrl)
- .toString()) + ')' + media;
- }
- });
- }
- // attributepaths one tag can have multiple paths, example:
- // <input src="..." style="url(..)"/> or <a style="url(..)" href="..">
- // <img
- // style='filter:progid...AlphaImageLoader(src="noticeTheSrcHereRunsThroughHtmlSrc")'
- // src="img">
- var htmlAttrPaths = /(<[a-z][a-z0-9]*\s[^>]*)(?:(href|src)=(['"]?)([^>]*?)\3|style=(['"]?)([^>]*?)\5)([^>]*>)/gi;
- function adjustHtmlPaths(htmlUrl, cont) {
- var url = htmlUrl || "./";
- return cont.replace(htmlAttrPaths, function(tag, start, name,
- delim, relUrl, delim2, cssText, end) {
- return start
- + (name
- ? (name
- + '='
- + delim
- + (new dojo._Url(url, relUrl)
- .toString()) + delim)
- : ('style=' + delim2
- + adjustCssPaths(url, cssText) + delim2))
- + end;
- });
- }
- function secureForInnerHtml(cont) {
- /** ******* remove <!DOCTYPE.. and <title>..</title> tag ********* */
- // 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
- return cont.replace(
- /(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig,
- "");
- }
- function snarfStyles(/* String */cssUrl, /* String */cont, /* Array */
- styles) {
- /**
- * ************** cut out all <style> and <link rel="stylesheet"
- * href=".."> *************
- */
- // also return any attributes from this tag (might be a media
- // attribute)
- // if cssUrl is set it will adjust paths accordingly
- styles.attributes = [];
- return cont
- .replace(
- /(?:<style([^>]*)>([\s\S]*?)<\/style>|<link\s+(?=[^>]*rel=['"]?stylesheet)([^>]*?href=(['"])([^>]*?)\4[^>\/]*)\/?>)/gi,
- function(ignore, styleAttr, cssText, linkAttr,
- delim, href) {
- // trim attribute
- var i, attr = (styleAttr || linkAttr || "")
- .replace(/^\s*([\s\S]*?)\s*$/i, "$1");
- if (cssText) {
- i = styles.push(cssUrl ? adjustCssPaths(
- cssUrl, cssText) : cssText);
- } else {
- i = styles.push('@import "' + href + '";')
- attr = attr
- .replace(
- /\s*(?:rel|href)=(['"])?[^\s]*\1\s*/gi,
- ""); // remove rel=...
- // and href=...
- }
- if (attr) {
- attr = attr.split(/\s+/);// split on both
- // "\n", "\t", "
- // " etc
- var atObj = {}, tmp;
- for (var j = 0, e = attr.length; j < e; j++) {
- tmp = attr[j].split('=')// split
- // name='value'
- atObj[tmp[0]] = tmp[1].replace(
- /^\s*['"]?([\s\S]*?)['"]?\s*$/,
- "$1"); // trim and remove ''
- }
- styles.attributes[i - 1] = atObj;
- }
- return ""; // squelsh the <style> or <link>
- });
- }
- function snarfScripts(cont, byRef) {
- // summary
- // strips out script tags from cont
- // invoke with
- // byRef = {errBack:function(){/*add your download error code
- // here*/, downloadRemote: true(default false)}}
- // byRef will have {code: 'jscode'} when this scope leaves
- byRef.code = "";
- function download(src) {
- if (byRef.downloadRemote) {
- // console.debug('downloading',src);
- dojo.xhrGet({
- url : src,
- sync : true,
- load : function(code) {
- byRef.code += code + ";";
- },
- error : byRef.errBack
- });
- }
- }
- // match <script>, <script type="text/..., but not <script
- // type="dojo(/method)...
- return cont
- .replace(
- /<script\s*(?![^>]*type=['"]?dojo)(?:[^>]*?(?:src=(['"]?)([^>]*?)\1[^>]*)?)*>([\s\S]*?)<\/script>/gi,
- function(ignore, delim, src, code) {
- if (src) {
- download(src);
- } else {
- byRef.code += code;
- }
- return "";
- });
- }
- function evalInGlobal(code, appendNode) {
- // we do our own eval here as dojo.eval doesn't eval in global
- // crossbrowser
- // This work X browser but but it relies on a DOM
- // plus it doesn't return anything, thats unrelevant here but not
- // for dojo core
- appendNode = appendNode || dojo.doc.body;
- var n = appendNode.ownerDocument.createElement('script');
- n.type = "text/javascript";
- appendNode.appendChild(n);
- n.text = code; // DOM 1 says this should work
- }
- /*
- * ===== dojox.layout.ContentPane.DeferredHandle = { // cancel: Function
- * cancel: function(){ // summary: cancel a in flight download },
- *
- * addOnLoad: function(func){ // summary: add a callback to the onLoad
- * chain // func: Function },
- *
- * addOnUnload: function(func){ // summary: add a callback to the
- * onUnload chain // func: Function } } =====
- */
- dojo.declare("dojox.layout.ContentPane", dijit.layout.ContentPane, {
- // summary:
- // An extended version of dijit.layout.ContentPane
- // Supports infile scrips and external ones declared by <script
- // src=''
- // relative path adjustments (content fetched from a different
- // folder)
- // <style> and <link rel='stylesheet' href='..'> tags,
- // css paths inside cssText is adjusted (if you set adjustPaths =
- // true)
- //
- // NOTE that dojo.require in script in the fetched file isn't
- // recommended
- // Many widgets need to be required at page load to work properly
- // adjustPaths: Boolean
- // Adjust relative paths in html string content to point to this
- // page
- // Only usefull if you grab content from a another folder then the
- // current one
- adjustPaths : false,
- // cleanContent: Boolean
- // summary:
- // cleans content to make it less likly to generate DOM/JS errors.
- // description:
- // usefull if you send contentpane a complete page, instead of a
- // html fragment
- // scans for
- // style nodes, inserts in Document head
- // title Node, remove
- // DOCTYPE tag, remove
- // <!-- *JS code here* -->
- // <![CDATA[ *JS code here* ]]>
- cleanContent : false,
- // renderStyles: Boolean
- // trigger/load styles in the content
- renderStyles : false,
- // executeScripts: Boolean
- // Execute (eval) scripts that is found in the content
- executeScripts : true,
- // scriptHasHooks: Boolean
- // replace keyword '_container_' in scripts with
- // 'dijit.byId(this.id)'
- // NOTE this name might change in the near future
- scriptHasHooks : false,
- /*
- * ====== // ioMethod: dojo.xhrGet|dojo.xhrPost // reference to the
- * method that should grab the content ioMethod: dojo.xhrGet,
- * // ioArgs: Object // makes it possible to add custom args to
- * xhrGet, like ioArgs.headers['X-myHeader'] = 'true' ioArgs: {},
- * // onLoadDeferred: dojo.Deferred // callbackchain will start
- * when onLoad occurs onLoadDeferred: new dojo.Deferred(),
- * // onUnloadDeferred: dojo.Deferred // callbackchain will start
- * when onUnload occurs onUnloadDeferred: new dojo.Deferred(),
- *
- * setHref: function(url){ // summary: replace current content with
- * url's content return ;// dojox.layout.ContentPane.DeferredHandle },
- *
- * refresh: function(){ summary: force a re-download of content
- * return ;// dojox.layout.ContentPane.DeferredHandle },
- *
- * ======
- */
- constructor : function() {
- // init per instance properties, initializer doesn't work here
- // because how things is hooked up in dijit._Widget
- this.ioArgs = {};
- this.ioMethod = dojo.xhrGet;
- this.onLoadDeferred = new dojo.Deferred();
- this.onUnloadDeferred = new dojo.Deferred();
- },
- postCreate : function() {
- // override to support loadDeferred
- this._setUpDeferreds();
- dijit.layout.ContentPane.prototype.postCreate.apply(this,
- arguments);
- },
- onExecError : function(e) {
- // summary
- // event callback, called on script error or on java handler
- // error
- // overide and return your own html string if you want a some
- // text
- // displayed within the ContentPane
- },
- setContent : function(data) {
- // summary: set data as new content, sort of like innerHTML
- // data: String|DomNode|NodeList|dojo.NodeList
- if (!this._isDownloaded) {
- var defObj = this._setUpDeferreds();
- }
- dijit.layout.ContentPane.prototype.setContent.apply(this,
- arguments);
- return defObj; // dojox.layout.ContentPane.DeferredHandle
- },
- cancel : function() {
- // summary: cancels a inflight download
- if (this._xhrDfd && this._xhrDfd.fired == -1) {
- // we are still in flight, which means we should reset our
- // DeferredHandle
- // otherwise we will trigger onUnLoad chain of the canceled
- // content,
- // the canceled content have never gotten onLoad so it
- // shouldn't get onUnload
- this.onUnloadDeferred = null;
- }
- dijit.layout.ContentPane.prototype.cancel
- .apply(this, arguments);
- },
- _setUpDeferreds : function() {
- var _t = this, cancel = function() {
- _t.cancel();
- }
- var onLoad = (_t.onLoadDeferred = new dojo.Deferred());
- var onUnload = (_t._nextUnloadDeferred = new dojo.Deferred());
- return {
- cancel : cancel,
- addOnLoad : function(func) {
- onLoad.addCallback(func);
- },
- addOnUnload : function(func) {
- onUnload.addCallback(func);
- }
- };
- },
- _onLoadHandler : function() {
- dijit.layout.ContentPane.prototype._onLoadHandler.apply(this,
- arguments);
- if (this.onLoadDeferred) {
- this.onLoadDeferred.callback(true);
- }
- },
- _onUnloadHandler : function() {
- this.isLoaded = false;
- this.cancel();// need to cancel so we don't get any inflight
- // suprises
- if (this.onUnloadDeferred) {
- this.onUnloadDeferred.callback(true);
- }
- dijit.layout.ContentPane.prototype._onUnloadHandler.apply(this,
- arguments);
- if (this._nextUnloadDeferred) {
- this.onUnloadDeferred = this._nextUnloadDeferred;
- }
- },
- _onError : function(type, err) {
- dijit.layout.ContentPane.prototype._onError.apply(this,
- arguments);
- if (this.onLoadDeferred) {
- this.onLoadDeferred.errback(err);
- }
- },
- _prepareLoad : function(forceLoad) {
- // sets up for a xhrLoad, load is deferred until widget is
- // showing
- var defObj = this._setUpDeferreds();
- dijit.layout.ContentPane.prototype._prepareLoad.apply(this,
- arguments);
- return defObj;
- },
- _setContent : function(cont) {
- // override dijit.layout.ContentPane._setContent, to enable path
- // adjustments
- var styles = [];// init vars
- if (dojo.isString(cont)) {
- if (this.adjustPaths && this.href) {
- cont = adjustHtmlPaths(this.href, cont);
- }
- if (this.cleanContent) {
- cont = secureForInnerHtml(cont);
- }
- if (this.renderStyles || this.cleanContent) {
- cont = snarfStyles(this.href, cont, styles);
- }
- // because of a bug in IE, script tags that is first in html
- // hierarchy doesnt make it into the DOM
- // when content is innerHTML'ed, so we can't use dojo.query
- // to retrieve scripts from DOM
- if (this.executeScripts) {
- var _t = this, code, byRef = {
- downloadRemote : true,
- errBack : function(e) {
- _t._onError.call(_t, 'Exec',
- 'Error downloading remote script in "'
- + _t.id + '"', e);
- }
- };
- cont = snarfScripts(cont, byRef);
- code = byRef.code;
- }
- // rationale for this block:
- // if containerNode/domNode is a table derivate tag, some
- // browsers dont allow innerHTML on those
- var node = (this.containerNode || this.domNode), pre = post = '', walk = 0;
- switch (name = node.nodeName.toLowerCase()) {
- case 'tr' :
- pre = '<tr>';
- post = '</tr>';
- walk += 1;// fallthrough
- case 'tbody' :
- case 'thead' :// children of THEAD is of same type as
- // TBODY
- pre = '<tbody>' + pre;
- post += '</tbody>';
- walk += 1;// falltrough
- case 'table' :
- pre = '<table>' + pre;
- post += '</table>';
- walk += 1;
- break;
- }
- if (walk) {
- var n = node.ownerDocument.createElement('div');
- n.innerHTML = pre + cont + post;
- do {
- n = n.firstChild;
- } while (--walk);
- cont = n.childNodes;
- }
- }
- // render the content
- dijit.layout.ContentPane.prototype._setContent.call(this, cont);
- // clear old stylenodes from the DOM
- if (this._styleNodes && this._styleNodes.length) {
- while (this._styleNodes.length) {
- dojo._destroyElement(this._styleNodes.pop());
- }
- }
- // render new style nodes
- if (this.renderStyles && styles && styles.length) {
- this._renderStyles(styles);
- }
- if (this.executeScripts && code) {
- if (this.cleanContent) {
- // clean JS from html comments and other crap that
- // browser
- // parser takes care of in a normal page load
- code = code.replace(
- /(<!--|(?:\/\/)?-->|<!\[CDATA\[|\]\]>)/g, '');
- }
- if (this.scriptHasHooks) {
- // replace _container_ with dijit.byId(this.id)
- code = code.replace(/_container_(?!\s*=[^=])/g,
- "dijit.byId('" + this.id + "')");
- }
- try {
- evalInGlobal(code, (this.containerNode || this.domNode));
- } catch (e) {
- this._onError('Exec', 'Error eval script in ' + this.id
- + ', ' + e.message, e);
- }
- }
- },
- _renderStyles : function(styles) {
- // insert css from content into document head
- this._styleNodes = [];
- var st, att, cssText, doc = this.domNode.ownerDocument;
- var head = doc.getElementsByTagName('head')[0];
- for (var i = 0, e = styles.length; i < e; i++) {
- cssText = styles[i];
- att = styles.attributes[i];
- st = doc.createElement('style');
- st.setAttribute("type", "text/css"); // this is required
- // in CSS spec!
- for (var x in att) {
- st.setAttribute(x, att[x])
- }
- this._styleNodes.push(st);
- head.appendChild(st); // must insert into DOM before
- // setting cssText
- if (st.styleSheet) { // IE
- st.styleSheet.cssText = cssText;
- } else { // w3c
- st.appendChild(doc.createTextNode(cssText));
- }
- }
- }
- });
- })();
- }
|