diff options
author | Andrew Dolgov <[email protected]> | 2013-03-18 10:26:24 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2013-03-18 10:26:26 +0400 |
commit | f0cfe83e3725f9a3928da97a6e3085e79cb25309 (patch) | |
tree | 4b0af188defaa807c7bc6ff3a101b41c9166c463 /lib/dojo/html.js.uncompressed.js | |
parent | 9a2885da170ffd64358b99194095851a2d09c1b6 (diff) |
upgrade dojo to 1.8.3 (refs #570)
Diffstat (limited to 'lib/dojo/html.js.uncompressed.js')
-rw-r--r-- | lib/dojo/html.js.uncompressed.js | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/lib/dojo/html.js.uncompressed.js b/lib/dojo/html.js.uncompressed.js new file mode 100644 index 000000000..0e3339cf2 --- /dev/null +++ b/lib/dojo/html.js.uncompressed.js @@ -0,0 +1,374 @@ +define("dojo/html", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/declare", "./dom", "./dom-construct", "./parser"], + function(kernel, lang, darray, declare, dom, domConstruct, parser){ + // module: + // dojo/html + + var html = { + // summary: + // TODOC + }; + lang.setObject("dojo.html", html); + + // the parser might be needed.. + + // idCounter is incremented with each instantiation to allow assignment of a unique id for tracking, logging purposes + var idCounter = 0; + + html._secureForInnerHtml = function(/*String*/ cont){ + // summary: + // removes !DOCTYPE and title elements from the html string. + // + // 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 + // cont: + // An html string for insertion into the dom + // + return cont.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String + }; + + html._emptyNode = domConstruct.empty; + /*===== + dojo.html._emptyNode = function(node){ + // summary: + // Removes all child nodes from the given node. Deprecated, should use dojo/dom-constuct.empty() directly + // instead. + // node: DOMNode + // the parent element + }; + =====*/ + + html._setNodeContent = function(/*DomNode*/ node, /*String|DomNode|NodeList*/ cont){ + // summary: + // inserts the given content into the given node + // node: + // the parent element + // content: + // 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 + + // always empty + domConstruct.empty(node); + + if(cont){ + if(typeof cont == "string"){ + cont = domConstruct.toDom(cont, node.ownerDocument); + } + if(!cont.nodeType && lang.isArrayLike(cont)){ + // handle as enumerable, but it may shrink as we enumerate it + for(var startlen=cont.length, i=0; i<cont.length; i=startlen==cont.length ? i+1 : 0){ + domConstruct.place( cont[i], node, "last"); + } + }else{ + // pass nodes, documentFragments and unknowns through to dojo.place + domConstruct.place(cont, node, "last"); + } + } + + // return DomNode + return node; + }; + + // we wrap up the content-setting operation in a object + html._ContentSetter = declare("dojo.html._ContentSetter", null, + { + // node: DomNode|String + // An node which will be the parent element that we set content into + node: "", + + // content: String|DomNode|DomNode[] + // The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes + content: "", + + // id: String? + // Usually only used internally, and auto-generated with each instance + id: "", + + // cleanContent: Boolean + // Should the content be treated as a full html document, + // and the real content stripped of <html>, <body> wrapper before injection + cleanContent: false, + + // extractContent: Boolean + // Should the content be treated as a full html document, + // and the real content stripped of `<html> <body>` wrapper before injection + extractContent: false, + + // parseContent: Boolean + // Should the node by passed to the parser after the new content is set + parseContent: false, + + // parserScope: String + // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo, + // will search for data-dojo-type (or dojoType). For backwards compatibility + // reasons defaults to dojo._scopeName (which is "dojo" except when + // multi-version support is used, when it will be something like dojo16, dojo20, etc.) + parserScope: kernel._scopeName, + + // startup: Boolean + // Start the child widgets after parsing them. Only obeyed if parseContent is true. + startup: true, + + // lifecycle methods + constructor: function(/*Object*/ params, /*String|DomNode*/ node){ + // summary: + // Provides a configurable, extensible object to wrap the setting on content on a node + // call the set() method to actually set the content.. + + // the original params are mixed directly into the instance "this" + lang.mixin(this, params || {}); + + // give precedence to params.node vs. the node argument + // and ensure its a node, not an id string + node = this.node = dom.byId( this.node || node ); + + if(!this.id){ + this.id = [ + "Setter", + (node) ? node.id || node.tagName : "", + idCounter++ + ].join("_"); + } + }, + set: function(/* String|DomNode|NodeList? */ cont, /*Object?*/ params){ + // summary: + // front-end to the set-content sequence + // cont: + // An html string, node or enumerable list of nodes for insertion into the dom + // If not provided, the object's content property will be used + if(undefined !== cont){ + this.content = cont; + } + // in the re-use scenario, set needs to be able to mixin new configuration + if(params){ + this._mixin(params); + } + + this.onBegin(); + this.setContent(); + + var ret = this.onEnd(); + + if(ret && ret.then){ + // Make dojox/html/_ContentSetter.set() return a Promise that resolves when load and parse complete. + return ret; + }else{ + // Vanilla dojo/html._ContentSetter.set() returns a DOMNode for back compat. For 2.0, switch it to + // return a Deferred like above. + return this.node; + } + }, + + setContent: function(){ + // summary: + // sets the content on the node + + var node = this.node; + if(!node){ + // can't proceed + throw new Error(this.declaredClass + ": setContent given no node"); + } + try{ + node = html._setNodeContent(node, this.content); + }catch(e){ + // check if a domfault occurs when we are appending this.errorMessage + // like for instance if domNode is a UL and we try append a DIV + + // FIXME: need to allow the user to provide a content error message string + var errMess = this.onContentError(e); + try{ + node.innerHTML = errMess; + }catch(e){ + console.error('Fatal ' + this.declaredClass + '.setContent could not change content due to '+e.message, e); + } + } + // always put back the node for the next method + this.node = node; // DomNode + }, + + empty: function(){ + // summary: + // cleanly empty out existing content + + // If there is a parse in progress, cancel it. + if(this.parseDeferred){ + if(!this.parseDeferred.isResolved()){ + this.parseDeferred.cancel(); + } + delete this.parseDeferred; + } + + // destroy any widgets from a previous run + // NOTE: if you don't want this you'll need to empty + // the parseResults array property yourself to avoid bad things happening + if(this.parseResults && this.parseResults.length){ + darray.forEach(this.parseResults, function(w){ + if(w.destroy){ + w.destroy(); + } + }); + delete this.parseResults; + } + // this is fast, but if you know its already empty or safe, you could + // override empty to skip this step + domConstruct.empty(this.node); + }, + + 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 default implementation checks for cleanContent and extractContent flags to + // optionally pre-process html string content + var cont = this.content; + + if(lang.isString(cont)){ + if(this.cleanContent){ + cont = html._secureForInnerHtml(cont); + } + + if(this.extractContent){ + var match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im); + if(match){ cont = match[1]; } + } + } + + // clean out the node and any cruft associated with it - like widgets + this.empty(); + + this.content = cont; + return this.node; // DomNode + }, + + 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 default implementation checks a parseContent flag to optionally run the dojo parser over the new content + if(this.parseContent){ + // populates this.parseResults and this.parseDeferred if you need those.. + this._parse(); + } + return this.node; // DomNode + // TODO: for 2.0 return a Promise indicating that the parse completed. + }, + + tearDown: function(){ + // summary: + // manually reset the Setter instance if its being re-used for example for another set() + // description: + // tearDown() is not called automatically. + // In normal use, the Setter instance properties are simply allowed to fall out of scope + // but the tearDown method can be called to explicitly reset this instance. + delete this.parseResults; + delete this.parseDeferred; + delete this.node; + delete this.content; + }, + + onContentError: function(err){ + return "Error occurred setting content: " + err; + }, + + onExecError: function(err){ + return "Error occurred executing scripts: " + err; + }, + + _mixin: function(params){ + // mix properties/methods into the instance + // TODO: the intention with tearDown is to put the Setter's state + // back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params) + // so we could do something here to move the original properties aside for later restoration + var empty = {}, key; + for(key in params){ + if(key in empty){ continue; } + // TODO: here's our opportunity to mask the properties we don't consider configurable/overridable + // .. but history shows we'll almost always guess wrong + this[key] = params[key]; + } + }, + _parse: function(){ + // summary: + // runs the dojo parser over the node contents, storing any results in this.parseResults + // and the parse promise in this.parseDeferred + // Any errors resulting from parsing are passed to _onError for handling + + var rootNode = this.node; + try{ + // store the results (widgets, whatever) for potential retrieval + var inherited = {}; + darray.forEach(["dir", "lang", "textDir"], function(name){ + if(this[name]){ + inherited[name] = this[name]; + } + }, this); + var self = this; + this.parseDeferred = parser.parse({ + rootNode: rootNode, + noStart: !this.startup, + inherited: inherited, + scope: this.parserScope + }).then(function(results){ + return self.parseResults = results; + }); + }catch(e){ + this._onError('Content', e, "Error parsing in _ContentSetter#"+this.id); + } + }, + + _onError: function(type, err, consoleText){ + // summary: + // shows user the string that is returned by on[type]Error + // override/implement on[type]Error and return your own string to customize + var errText = this['on' + type + 'Error'].call(this, err); + if(consoleText){ + console.error(consoleText, err); + }else if(errText){ // a empty string won't change current content + html._setNodeContent(this.node, errText, true); + } + } + }); // end declare() + + html.set = function(/*DomNode*/ node, /*String|DomNode|NodeList*/ cont, /*Object?*/ params){ + // summary: + // inserts (replaces) the given content into the given node. dojo.place(cont, node, "only") + // may be a better choice for simple HTML insertion. + // description: + // Unless you need to use the params capabilities of this method, you should use + // dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting + // an HTML string into the DOM, but it only handles inserting an HTML string as DOM + // elements, or inserting a DOM node. dojo.place does not handle NodeList insertions + // or the other capabilities as defined by the params object for this method. + // 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: + // | html.set(node, "some string"); + // | html.set(node, contentNode, {options}); + // | html.set(node, myNode.childNodes, {options}); + if(undefined == cont){ + console.warn("dojo.html.set: no cont argument provided, using empty string"); + cont = ""; + } + if(!params){ + // simple and fast + return html._setNodeContent(node, cont, true); + }else{ + // more options but slower + // note the arguments are reversed in order, to match the convention for instantiation via the parser + var op = new html._ContentSetter(lang.mixin( + params, + { content: cont, node: node } + )); + return op.set(); + } + }; + + return html; +}); |