]>
git.wh0rd.org - tt-rss.git/blob - lib/dojo/html.js
2 Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
8 if(!dojo
._hasResource
["dojo.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9 dojo
._hasResource
["dojo.html"] = true;
10 dojo
.provide("dojo.html");
11 dojo
.require("dojo.parser");
13 dojo
.getObject("html", true, dojo
);
15 // the parser might be needed..
16 (function(){ // private scope, sort of a namespace
18 // idCounter is incremented with each instantiation to allow asignment of a unique id for tracking, logging purposes
22 dojo
.html
._secureForInnerHtml = function(/*String*/ cont
){
24 // removes !DOCTYPE and title elements from the html string.
26 // khtml is picky about dom faults, you can't attach a style or <title> node as child of body
27 // must go into head, so we need to cut out those tags
29 // An html string for insertion into the dom
31 return cont
.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String
35 dojo.html._emptyNode = function(node){
37 // removes all child nodes from the given node
42 dojo
.html
._emptyNode
= dojo
.empty
;
44 dojo
.html
._setNodeContent = function(/* DomNode */ node
, /* String|DomNode|NodeList */ cont
){
46 // inserts the given content into the given node
50 // the content to be set on the parent element.
51 // This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
57 if(typeof cont
== "string") {
58 cont
= d
._toDom(cont
, node
.ownerDocument
);
60 if(!cont
.nodeType
&& d
.isArrayLike(cont
)) {
61 // handle as enumerable, but it may shrink as we enumerate it
62 for(var startlen
=cont
.length
, i
=0; i
<cont
.length
; i
=startlen
==cont
.length
? i
+1 : 0) {
63 d
.place( cont
[i
], node
, "last");
66 // pass nodes, documentFragments and unknowns through to dojo.place
67 d
.place(cont
, node
, "last");
75 // we wrap up the content-setting operation in a object
76 dojo
.declare("dojo.html._ContentSetter", null,
78 // node: DomNode|String
79 // An node which will be the parent element that we set content into
82 // content: String|DomNode|DomNode[]
83 // The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes
87 // Usually only used internally, and auto-generated with each instance
90 // cleanContent: Boolean
91 // Should the content be treated as a full html document,
92 // and the real content stripped of <html>, <body> wrapper before injection
95 // extractContent: Boolean
96 // Should the content be treated as a full html document, and the real content stripped of <html>, <body> wrapper before injection
97 extractContent
: false,
99 // parseContent: Boolean
100 // Should the node by passed to the parser after the new content is set
103 // parserScope: String
104 // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo,
105 // will search for data-dojo-type (or dojoType). For backwards compatibility
106 // reasons defaults to dojo._scopeName (which is "dojo" except when
107 // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
108 parserScope
: dojo
._scopeName
,
111 // Start the child widgets after parsing them. Only obeyed if parseContent is true.
115 constructor: function(/* Object */params
, /* String|DomNode */node
){
117 // Provides a configurable, extensible object to wrap the setting on content on a node
118 // call the set() method to actually set the content..
120 // the original params are mixed directly into the instance "this"
121 dojo
.mixin(this, params
|| {});
123 // give precedence to params.node vs. the node argument
124 // and ensure its a node, not an id string
125 node
= this.node
= dojo
.byId( this.node
|| node
);
130 (node
) ? node
.id
|| node
.tagName
: "",
135 set: function(/* String|DomNode|NodeList? */ cont
, /* Object? */ params
){
137 // front-end to the set-content sequence
139 // An html string, node or enumerable list of nodes for insertion into the dom
140 // If not provided, the object's content property will be used
141 if(undefined !== cont
){
144 // in the re-use scenario, set needs to be able to mixin new configuration
155 setContent: function(){
157 // sets the content on the node
159 var node
= this.node
;
162 throw new Error(this.declaredClass
+ ": setContent given no node");
165 node
= dojo
.html
._setNodeContent(node
, this.content
);
167 // check if a domfault occurs when we are appending this.errorMessage
168 // like for instance if domNode is a UL and we try append a DIV
170 // FIXME: need to allow the user to provide a content error message string
171 var errMess
= this.onContentError(e
);
173 node
.innerHTML
= errMess
;
175 console
.error('Fatal ' + this.declaredClass
+ '.setContent could not change content due to '+e
.message
, e
);
178 // always put back the node for the next method
179 this.node
= node
; // DomNode
184 // cleanly empty out existing content
186 // destroy any widgets from a previous run
187 // NOTE: if you dont want this you'll need to empty
188 // the parseResults array property yourself to avoid bad things happenning
189 if(this.parseResults
&& this.parseResults
.length
) {
190 dojo
.forEach(this.parseResults
, function(w
) {
195 delete this.parseResults
;
197 // this is fast, but if you know its already empty or safe, you could
198 // override empty to skip this step
199 dojo
.html
._emptyNode(this.node
);
204 // Called after instantiation, but before set();
205 // It allows modification of any of the object properties
206 // - including the node and content provided - before the set operation actually takes place
207 // This default implementation checks for cleanContent and extractContent flags to
208 // optionally pre-process html string content
209 var cont
= this.content
;
211 if(dojo
.isString(cont
)){
212 if(this.cleanContent
){
213 cont
= dojo
.html
._secureForInnerHtml(cont
);
216 if(this.extractContent
){
217 var match
= cont
.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
218 if(match
){ cont
= match
[1]; }
222 // clean out the node and any cruft associated with it - like widgets
226 return this.node
; /* DomNode */
231 // Called after set(), when the new content has been pushed into the node
232 // It provides an opportunity for post-processing before handing back the node to the caller
233 // This default implementation checks a parseContent flag to optionally run the dojo parser over the new content
234 if(this.parseContent
){
235 // populates this.parseResults if you need those..
238 return this.node
; /* DomNode */
241 tearDown: function(){
243 // manually reset the Setter instance if its being re-used for example for another set()
245 // tearDown() is not called automatically.
246 // In normal use, the Setter instance properties are simply allowed to fall out of scope
247 // but the tearDown method can be called to explicitly reset this instance.
248 delete this.parseResults
;
253 onContentError: function(err
){
254 return "Error occured setting content: " + err
;
257 _mixin: function(params
){
258 // mix properties/methods into the instance
259 // TODO: the intention with tearDown is to put the Setter's state
260 // back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params)
261 // so we could do something here to move the original properties aside for later restoration
264 if(key
in empty
){ continue; }
265 // TODO: here's our opportunity to mask the properties we dont consider configurable/overridable
266 // .. but history shows we'll almost always guess wrong
267 this[key
] = params
[key
];
272 // runs the dojo parser over the node contents, storing any results in this.parseResults
273 // Any errors resulting from parsing are passed to _onError for handling
275 var rootNode
= this.node
;
277 // store the results (widgets, whatever) for potential retrieval
279 dojo
.forEach(["dir", "lang", "textDir"], function(name
){
281 inherited
[name
] = this[name
];
284 this.parseResults
= dojo
.parser
.parse({
286 noStart
: !this.startup
,
287 inherited
: inherited
,
288 scope
: this.parserScope
291 this._onError('Content', e
, "Error parsing in _ContentSetter#"+this.id
);
295 _onError: function(type
, err
, consoleText
){
297 // shows user the string that is returned by on[type]Error
298 // overide/implement on[type]Error and return your own string to customize
299 var errText
= this['on' + type
+ 'Error'].call(this, err
);
301 console
.error(consoleText
, err
);
302 }else if(errText
){ // a empty string won't change current content
303 dojo
.html
._setNodeContent(this.node
, errText
, true);
306 }); // end dojo.declare()
308 dojo
.html
.set = function(/* DomNode */ node
, /* String|DomNode|NodeList */ cont
, /* Object? */ params
){
310 // inserts (replaces) the given content into the given node. dojo.place(cont, node, "only")
311 // may be a better choice for simple HTML insertion.
313 // Unless you need to use the params capabilities of this method, you should use
314 // dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting
315 // an HTML string into the DOM, but it only handles inserting an HTML string as DOM
316 // elements, or inserting a DOM node. dojo.place does not handle NodeList insertions
317 // or the other capabilities as defined by the params object for this method.
319 // the parent element that will receive the content
321 // the content to be set on the parent element.
322 // This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
324 // Optional flags/properties to configure the content-setting. See dojo.html._ContentSetter
326 // A safe string/node/nodelist content replacement/injection with hooks for extension
328 // dojo.html.set(node, "some string");
329 // dojo.html.set(node, contentNode, {options});
330 // dojo.html.set(node, myNode.childNodes, {options});
331 if(undefined == cont
){
332 console
.warn("dojo.html.set: no cont argument provided, using empty string");
337 return dojo
.html
._setNodeContent(node
, cont
, true);
339 // more options but slower
340 // note the arguments are reversed in order, to match the convention for instantiation via the parser
341 var op
= new dojo
.html
._ContentSetter(dojo
.mixin(
343 { content
: cont
, node
: node
}