diff options
Diffstat (limited to 'js/dojo-1.7.2/dojox/html/_base.js')
| -rw-r--r-- | js/dojo-1.7.2/dojox/html/_base.js | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/js/dojo-1.7.2/dojox/html/_base.js b/js/dojo-1.7.2/dojox/html/_base.js new file mode 100644 index 0000000..bbd960d --- /dev/null +++ b/js/dojo-1.7.2/dojox/html/_base.js @@ -0,0 +1,386 @@ +//>>built +define("dojox/html/_base", [ + "dojo/_base/kernel", + "dojo/_base/lang", + "dojo/_base/xhr", + "dojo/_base/window", + "dojo/_base/sniff", + "dojo/_base/url", + "dojo/dom-construct", + "dojo/html", + "dojo/_base/declare" +], function (dojo, lang, xhrUtil, windowUtil, has, _Url, domConstruct, htmlUtil) { +/* + Status: dont know where this will all live exactly + Need to pull in the implementation of the various helper methods + Some can be static method, others maybe methods of the ContentSetter (?) + + Gut the ContentPane, replace its _setContent with our own call to dojox.html.set() + + +*/ + var html = dojo.getObject("dojox.html", true); + + if(has("ie")){ + var alphaImageLoader = /(AlphaImageLoader\([^)]*?src=(['"]))(?![a-z]+:|\/)([^\r\n;}]+?)(\2[^)]*\)\s*[;}]?)/g; + } + + // 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]+:|\/) + + var cssPaths = /(?:(?:@import\s*(['"])(?![a-z]+:|\/)([^\r\n;{]+?)\1)|url\(\s*(['"]?)(?![a-z]+:|\/)([^\r\n;]+?)\3\s*\))([a-z, \s]*[;}]?)/g; + + var adjustCssPaths = html._adjustCssPaths = function(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 _Url(cssUrl, './'+url).toString()) + post; + }); + } + + return cssText.replace(cssPaths, function(ignore, delimStr, strUrl, delimUrl, urlUrl, media){ + if(strUrl){ + return '@import "' + (new _Url(cssUrl, './'+strUrl).toString()) + '"' + media; + }else{ + return 'url(' + (new _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; + + var adjustHtmlPaths = html._adjustHtmlPaths = function(htmlUrl, cont){ + var url = htmlUrl || "./"; + + return cont.replace(htmlAttrPaths, + function(tag, start, name, delim, relUrl, delim2, cssText, end){ + return start + (name ? + (name + '=' + delim + (new _Url(url, relUrl).toString()) + delim) + : ('style=' + delim2 + adjustCssPaths(url, cssText) + delim2) + ) + end; + } + ); + }; + + var snarfStyles = html._snarfStyles = function (/*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 ""; + } + ); + }; + + var snarfScripts = html._snarfScripts = function(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 = ""; + + //Update script tags nested in comments so that the script tag collector doesn't pick + //them up. + cont = cont.replace(/<[!][-][-](.|\s)*?[-][-]>/g, + function(comment){ + return comment.replace(/<(\/?)script\b/ig,"<$1Script"); + } + ); + + function download(src){ + if(byRef.downloadRemote){ + // console.debug('downloading',src); + //Fix up src, in case there were entity character encodings in it. + //Probably only need to worry about a subset. + src = src.replace(/&([a-z0-9#]+);/g, function(m, name) { + switch(name) { + case "amp" : return "&"; + case "gt" : return ">"; + case "lt" : return "<"; + default: + return name.charAt(0)=="#" ? String.fromCharCode(name.substring(1)) : "&"+name+";"; + } + }); + xhrUtil.get({ + 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\/|text\/html\b))(?:[^>]*?(?:src=(['"]?)([^>]*?)\1[^>]*)?)*>([\s\S]*?)<\/script>/gi, + function(ignore, delim, src, code){ + if(src){ + download(src); + }else{ + byRef.code += code; + } + return ""; + } + ); + }; + + var evalInGlobal = html.evalInGlobal = function(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 || windowUtil.doc.body; + var n = appendNode.ownerDocument.createElement('script'); + n.type = "text/javascript"; + appendNode.appendChild(n); + n.text = code; // DOM 1 says this should work + }; + + html._ContentSetter = dojo.declare(/*===== "dojox.html._ContentSetter", =====*/ htmlUtil._ContentSetter, { + // adjustPaths: Boolean + // Adjust relative paths in html string content to point to this page + // Only useful if you grab content from a another folder than the current one + adjustPaths: false, + referencePath: ".", + renderStyles: false, + + executeScripts: false, + scriptHasHooks: false, + scriptHookReplacement: null, + + _renderStyles: function(styles){ + // insert css from content into document head + this._styleNodes = []; + var st, att, cssText, doc = this.node.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)); + } + } + }, + + empty: function() { + this.inherited("empty", arguments); + + // empty out the styles array from any previous use + this._styles = []; + }, + + onBegin: function() { + // summary + // Called after instantiation, but before set(); + // It allows modification of any of the object properties - including the node and content + // provided - before the set operation actually takes place + // This implementation extends that of dojo.html._ContentSetter + // to add handling for adjustPaths, renderStyles on the html string content before it is set + this.inherited("onBegin", arguments); + + var cont = this.content, + node = this.node; + + var styles = this._styles;// init vars + + if(lang.isString(cont)){ + if(this.adjustPaths && this.referencePath){ + cont = adjustHtmlPaths(this.referencePath, cont); + } + + if(this.renderStyles || this.cleanContent){ + cont = snarfStyles(this.referencePath, 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; + var byRef = { + downloadRemote: true, + errBack:function(e){ + _t._onError.call(_t, 'Exec', 'Error downloading remote script in "'+_t.id+'"', e); + } + }; + cont = snarfScripts(cont, byRef); + this._code = byRef.code; + } + } + this.content = cont; + }, + + onEnd: function() { + // summary + // Called after set(), when the new content has been pushed into the node + // It provides an opportunity for post-processing before handing back the node to the caller + // This implementation extends that of dojo.html._ContentSetter + + var code = this._code, + styles = this._styles; + + // clear old stylenodes from the DOM + // these were added by the last set call + // (in other words, if you dont keep and reuse the ContentSetter for a particular node + // .. you'll have no practical way to do this) + if(this._styleNodes && this._styleNodes.length){ + while(this._styleNodes.length){ + domConstruct.destroy(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 this.scriptHookReplace() + // the scriptHookReplacement can be a string + // or a function, which when invoked returns the string you want to substitute in + code = code.replace(/_container_(?!\s*=[^=])/g, this.scriptHookReplacement); + } + try{ + evalInGlobal(code, this.node); + }catch(e){ + this._onError('Exec', 'Error eval script in '+this.id+', '+e.message, e); + } + } + this.inherited("onEnd", arguments); + }, + tearDown: function() { + this.inherited(arguments); + delete this._styles; + // only tear down -or another set() - will explicitly throw away the + // references to the style nodes we added + if(this._styleNodes && this._styleNodes.length){ + while(this._styleNodes.length){ + domConstruct.destroy(this._styleNodes.pop()); + } + } + delete this._styleNodes; + // reset the defaults from the prototype + // XXX: not sure if this is the correct intended behaviour, it was originally + // dojo.getObject(this.declaredClass).prototype which will not work with anonymous + // modules + dojo.mixin(this, html._ContentSetter.prototype); + } + + }); + + html.set = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Object? */ params){ + // TODO: add all the other options + // summary: + // inserts (replaces) the given content into the given node + // node: + // the parent element that will receive the content + // cont: + // the content to be set on the parent element. + // This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes + // params: + // Optional flags/properties to configure the content-setting. See dojo.html._ContentSetter + // example: + // A safe string/node/nodelist content replacement/injection with hooks for extension + // Example Usage: + // dojo.html.set(node, "some string"); + // dojo.html.set(node, contentNode, {options}); + // dojo.html.set(node, myNode.childNodes, {options}); + + if(!params){ + // simple and fast + return htmlUtil._setNodeContent(node, cont, true); + }else{ + // more options but slower + var op = new html._ContentSetter(dojo.mixin( + params, + { content: cont, node: node } + )); + return op.set(); + } + }; + + return html; +});
\ No newline at end of file |
