]>
git.wh0rd.org - tt-rss.git/blob - lib/dojo/html.js.uncompressed.js
1 define("dojo/html", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/declare", "./dom", "./dom-construct", "./parser"],
2 function(kernel
, lang
, darray
, declare
, dom
, domConstruct
, parser
){
10 lang
.setObject("dojo.html", html
);
12 // the parser might be needed..
14 // idCounter is incremented with each instantiation to allow assignment of a unique id for tracking, logging purposes
17 html
._secureForInnerHtml = function(/*String*/ cont
){
19 // removes !DOCTYPE and title elements from the html string.
21 // khtml is picky about dom faults, you can't attach a style or `<title>` node as child of body
22 // must go into head, so we need to cut out those tags
24 // An html string for insertion into the dom
26 return cont
.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String
29 html
._emptyNode
= domConstruct
.empty
;
31 dojo.html._emptyNode = function(node){
33 // Removes all child nodes from the given node. Deprecated, should use dojo/dom-constuct.empty() directly
40 html
._setNodeContent = function(/*DomNode*/ node
, /*String|DomNode|NodeList*/ cont
){
42 // inserts the given content into the given node
46 // the content to be set on the parent element.
47 // This can be an html string, a node reference or a NodeList, dojo/NodeList, Array or other enumerable list of nodes
50 domConstruct
.empty(node
);
53 if(typeof cont
== "string"){
54 cont
= domConstruct
.toDom(cont
, node
.ownerDocument
);
56 if(!cont
.nodeType
&& lang
.isArrayLike(cont
)){
57 // handle as enumerable, but it may shrink as we enumerate it
58 for(var startlen
=cont
.length
, i
=0; i
<cont
.length
; i
=startlen
==cont
.length
? i
+1 : 0){
59 domConstruct
.place( cont
[i
], node
, "last");
62 // pass nodes, documentFragments and unknowns through to dojo.place
63 domConstruct
.place(cont
, node
, "last");
71 // we wrap up the content-setting operation in a object
72 html
._ContentSetter
= declare("dojo.html._ContentSetter", null,
74 // node: DomNode|String
75 // An node which will be the parent element that we set content into
78 // content: String|DomNode|DomNode[]
79 // The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes
83 // Usually only used internally, and auto-generated with each instance
86 // cleanContent: Boolean
87 // Should the content be treated as a full html document,
88 // and the real content stripped of <html>, <body> wrapper before injection
91 // extractContent: Boolean
92 // Should the content be treated as a full html document,
93 // and the real content stripped of `<html> <body>` wrapper before injection
94 extractContent
: false,
96 // parseContent: Boolean
97 // Should the node by passed to the parser after the new content is set
100 // parserScope: String
101 // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo,
102 // will search for data-dojo-type (or dojoType). For backwards compatibility
103 // reasons defaults to dojo._scopeName (which is "dojo" except when
104 // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
105 parserScope
: kernel
._scopeName
,
108 // Start the child widgets after parsing them. Only obeyed if parseContent is true.
112 constructor: function(/*Object*/ params
, /*String|DomNode*/ node
){
114 // Provides a configurable, extensible object to wrap the setting on content on a node
115 // call the set() method to actually set the content..
117 // the original params are mixed directly into the instance "this"
118 lang
.mixin(this, params
|| {});
120 // give precedence to params.node vs. the node argument
121 // and ensure its a node, not an id string
122 node
= this.node
= dom
.byId( this.node
|| node
);
127 (node
) ? node
.id
|| node
.tagName
: "",
132 set: function(/* String|DomNode|NodeList? */ cont
, /*Object?*/ params
){
134 // front-end to the set-content sequence
136 // An html string, node or enumerable list of nodes for insertion into the dom
137 // If not provided, the object's content property will be used
138 if(undefined !== cont
){
141 // in the re-use scenario, set needs to be able to mixin new configuration
149 var ret
= this.onEnd();
152 // Make dojox/html/_ContentSetter.set() return a Promise that resolves when load and parse complete.
155 // Vanilla dojo/html._ContentSetter.set() returns a DOMNode for back compat. For 2.0, switch it to
156 // return a Deferred like above.
161 setContent: function(){
163 // sets the content on the node
165 var node
= this.node
;
168 throw new Error(this.declaredClass
+ ": setContent given no node");
171 node
= html
._setNodeContent(node
, this.content
);
173 // check if a domfault occurs when we are appending this.errorMessage
174 // like for instance if domNode is a UL and we try append a DIV
176 // FIXME: need to allow the user to provide a content error message string
177 var errMess
= this.onContentError(e
);
179 node
.innerHTML
= errMess
;
181 console
.error('Fatal ' + this.declaredClass
+ '.setContent could not change content due to '+e
.message
, e
);
184 // always put back the node for the next method
185 this.node
= node
; // DomNode
190 // cleanly empty out existing content
192 // If there is a parse in progress, cancel it.
193 if(this.parseDeferred
){
194 if(!this.parseDeferred
.isResolved()){
195 this.parseDeferred
.cancel();
197 delete this.parseDeferred
;
200 // destroy any widgets from a previous run
201 // NOTE: if you don't want this you'll need to empty
202 // the parseResults array property yourself to avoid bad things happening
203 if(this.parseResults
&& this.parseResults
.length
){
204 darray
.forEach(this.parseResults
, function(w
){
209 delete this.parseResults
;
211 // this is fast, but if you know its already empty or safe, you could
212 // override empty to skip this step
213 domConstruct
.empty(this.node
);
218 // Called after instantiation, but before set();
219 // It allows modification of any of the object properties -
220 // including the node and content provided - before the set operation actually takes place
221 // This default implementation checks for cleanContent and extractContent flags to
222 // optionally pre-process html string content
223 var cont
= this.content
;
225 if(lang
.isString(cont
)){
226 if(this.cleanContent
){
227 cont
= html
._secureForInnerHtml(cont
);
230 if(this.extractContent
){
231 var match
= cont
.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
232 if(match
){ cont
= match
[1]; }
236 // clean out the node and any cruft associated with it - like widgets
240 return this.node
; // DomNode
245 // Called after set(), when the new content has been pushed into the node
246 // It provides an opportunity for post-processing before handing back the node to the caller
247 // This default implementation checks a parseContent flag to optionally run the dojo parser over the new content
248 if(this.parseContent
){
249 // populates this.parseResults and this.parseDeferred if you need those..
252 return this.node
; // DomNode
253 // TODO: for 2.0 return a Promise indicating that the parse completed.
256 tearDown: function(){
258 // manually reset the Setter instance if its being re-used for example for another set()
260 // tearDown() is not called automatically.
261 // In normal use, the Setter instance properties are simply allowed to fall out of scope
262 // but the tearDown method can be called to explicitly reset this instance.
263 delete this.parseResults
;
264 delete this.parseDeferred
;
269 onContentError: function(err
){
270 return "Error occurred setting content: " + err
;
273 onExecError: function(err
){
274 return "Error occurred executing scripts: " + err
;
277 _mixin: function(params
){
278 // mix properties/methods into the instance
279 // TODO: the intention with tearDown is to put the Setter's state
280 // back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params)
281 // so we could do something here to move the original properties aside for later restoration
284 if(key
in empty
){ continue; }
285 // TODO: here's our opportunity to mask the properties we don't consider configurable/overridable
286 // .. but history shows we'll almost always guess wrong
287 this[key
] = params
[key
];
292 // runs the dojo parser over the node contents, storing any results in this.parseResults
293 // and the parse promise in this.parseDeferred
294 // Any errors resulting from parsing are passed to _onError for handling
296 var rootNode
= this.node
;
298 // store the results (widgets, whatever) for potential retrieval
300 darray
.forEach(["dir", "lang", "textDir"], function(name
){
302 inherited
[name
] = this[name
];
306 this.parseDeferred
= parser
.parse({
308 noStart
: !this.startup
,
309 inherited
: inherited
,
310 scope
: this.parserScope
311 }).then(function(results
){
312 return self
.parseResults
= results
;
315 this._onError('Content', e
, "Error parsing in _ContentSetter#"+this.id
);
319 _onError: function(type
, err
, consoleText
){
321 // shows user the string that is returned by on[type]Error
322 // override/implement on[type]Error and return your own string to customize
323 var errText
= this['on' + type
+ 'Error'].call(this, err
);
325 console
.error(consoleText
, err
);
326 }else if(errText
){ // a empty string won't change current content
327 html
._setNodeContent(this.node
, errText
, true);
332 html
.set = function(/*DomNode*/ node
, /*String|DomNode|NodeList*/ cont
, /*Object?*/ params
){
334 // inserts (replaces) the given content into the given node. dojo.place(cont, node, "only")
335 // may be a better choice for simple HTML insertion.
337 // Unless you need to use the params capabilities of this method, you should use
338 // dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting
339 // an HTML string into the DOM, but it only handles inserting an HTML string as DOM
340 // elements, or inserting a DOM node. dojo.place does not handle NodeList insertions
341 // or the other capabilities as defined by the params object for this method.
343 // the parent element that will receive the content
345 // the content to be set on the parent element.
346 // This can be an html string, a node reference or a NodeList, dojo/NodeList, Array or other enumerable list of nodes
348 // Optional flags/properties to configure the content-setting. See dojo/html/_ContentSetter
350 // A safe string/node/nodelist content replacement/injection with hooks for extension
352 // | html.set(node, "some string");
353 // | html.set(node, contentNode, {options});
354 // | html.set(node, myNode.childNodes, {options});
355 if(undefined == cont
){
356 console
.warn("dojo.html.set: no cont argument provided, using empty string");
361 return html
._setNodeContent(node
, cont
, true);
363 // more options but slower
364 // note the arguments are reversed in order, to match the convention for instantiation via the parser
365 var op
= new html
._ContentSetter(lang
.mixin(
367 { content
: cont
, node
: node
}