]> git.wh0rd.org - tt-rss.git/blob - lib/dijit/_editor/html.js.uncompressed.js
upgrade dojo to 1.8.3 (refs #570)
[tt-rss.git] / lib / dijit / _editor / html.js.uncompressed.js
1 define("dijit/_editor/html", [
2 "dojo/_base/array",
3 "dojo/_base/lang", // lang.setObject
4 "dojo/sniff" // has("ie")
5 ], function(array, lang, has){
6
7 // module:
8 // dijit/_editor/html
9 // summary:
10 // HTML serialization utility functions used by editor
11
12 var exports = {};
13 lang.setObject("dijit._editor.html", exports);
14
15 var escape = exports.escapeXml = function(/*String*/ str, /*Boolean?*/ noSingleQuotes){
16 // summary:
17 // Adds escape sequences for special characters in XML: `&<>"'`.
18 // Optionally skips escapes for single quotes.
19 str = str.replace(/&/gm, "&amp;").replace(/</gm, "&lt;").replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
20 if(!noSingleQuotes){
21 str = str.replace(/'/gm, "&#39;");
22 }
23 return str; // string
24 };
25
26
27 exports.getNodeHtml = function(/*DomNode*/ node){
28 // summary:
29 // Return string representing HTML for node and it's children
30 var output = [];
31 exports.getNodeHtmlHelper(node, output);
32 return output.join("");
33 };
34
35 exports.getNodeHtmlHelper = function(/*DomNode*/ node, /*String[]*/ output){
36 // summary:
37 // Pushes array of strings into output[] which represent HTML for node and it's children
38 switch(node.nodeType){
39 case 1: // element node
40 var lName = node.nodeName.toLowerCase();
41 if(!lName || lName.charAt(0) == "/"){
42 // IE does some strange things with malformed HTML input, like
43 // treating a close tag </span> without an open tag <span>, as
44 // a new tag with tagName of /span. Corrupts output HTML, remove
45 // them. Other browsers don't prefix tags that way, so will
46 // never show up.
47 return "";
48 }
49 output.push('<', lName);
50
51 // store the list of attributes and sort it to have the
52 // attributes appear in the dictionary order
53 var attrarray = [], attrhash = {};
54 var attr;
55 if(has("dom-attributes-explicit") || has("dom-attributes-specified-flag")){
56 // IE8+ and all other browsers.
57 var i = 0;
58 while((attr = node.attributes[i++])){
59 // ignore all attributes starting with _dj which are
60 // internal temporary attributes used by the editor
61 var n = attr.name;
62 if(n.substr(0,3) !== '_dj' &&
63 (!has("dom-attributes-specified-flag") || attr.specified) &&
64 !(n in attrhash)){ // workaround repeated attributes bug in IE8 (LinkDialog test)
65 var v = attr.value;
66 if(n == 'src' || n == 'href'){
67 if(node.getAttribute('_djrealurl')){
68 v = node.getAttribute('_djrealurl');
69 }
70 }
71 if(has("ie") === 8 && n === "style"){
72 v = v.replace("HEIGHT:", "height:").replace("WIDTH:", "width:");
73 }
74 attrarray.push([n,v]);
75 attrhash[n] = v;
76 }
77 }
78 }else{
79 // IE6-7 code path
80 var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false);
81 var s = clone.outerHTML;
82 // Split up and manage the attrs via regexp
83 // similar to prettyPrint attr logic.
84 var rgxp_attrsMatch = /[\w-]+=("[^"]*"|'[^']*'|\S*)/gi
85 var attrSplit = s.match(rgxp_attrsMatch);
86 s = s.substr(0, s.indexOf('>'));
87 array.forEach(attrSplit, function(attr){
88 if(attr){
89 var idx = attr.indexOf("=");
90 if(idx > 0){
91 var key = attr.substring(0,idx);
92 if(key.substr(0,3) != '_dj'){
93 if(key == 'src' || key == 'href'){
94 if(node.getAttribute('_djrealurl')){
95 attrarray.push([key,node.getAttribute('_djrealurl')]);
96 return;
97 }
98 }
99 var val, match;
100 switch(key){
101 case 'style':
102 val = node.style.cssText.toLowerCase();
103 break;
104 case 'class':
105 val = node.className;
106 break;
107 case 'width':
108 if(lName === "img"){
109 // This somehow gets lost on IE for IMG tags and the like
110 // and we have to find it in outerHTML, known IE oddity.
111 match=/width=(\S+)/i.exec(s);
112 if(match){
113 val = match[1];
114 }
115 break;
116 }
117 case 'height':
118 if(lName === "img"){
119 // This somehow gets lost on IE for IMG tags and the like
120 // and we have to find it in outerHTML, known IE oddity.
121 match=/height=(\S+)/i.exec(s);
122 if(match){
123 val = match[1];
124 }
125 break;
126 }
127 default:
128 val = node.getAttribute(key);
129 }
130 if(val != null){
131 attrarray.push([key, val.toString()]);
132 }
133 }
134 }
135 }
136 }, this);
137 }
138 attrarray.sort(function(a,b){
139 return a[0] < b[0] ? -1 : (a[0] == b[0] ? 0 : 1);
140 });
141 var j = 0;
142 while((attr = attrarray[j++])){
143 output.push(' ', attr[0], '="',
144 (typeof attr[1] === "string" ? escape(attr[1], true) : attr[1]), '"');
145 }
146 switch(lName){
147 case 'br':
148 case 'hr':
149 case 'img':
150 case 'input':
151 case 'base':
152 case 'meta':
153 case 'area':
154 case 'basefont':
155 // These should all be singly closed
156 output.push(' />');
157 break;
158 case 'script':
159 // Browsers handle script tags differently in how you get content,
160 // but innerHTML always seems to work, so insert its content that way
161 // Yes, it's bad to allow script tags in the editor code, but some people
162 // seem to want to do it, so we need to at least return them right.
163 // other plugins/filters can strip them.
164 output.push('>', node.innerHTML, '</', lName, '>');
165 break;
166 default:
167 output.push('>');
168 if(node.hasChildNodes()){
169 exports.getChildrenHtmlHelper(node, output);
170 }
171 output.push('</', lName, '>');
172 }
173 break;
174 case 4: // cdata
175 case 3: // text
176 // FIXME:
177 output.push(escape(node.nodeValue, true));
178 break;
179 case 8: // comment
180 // FIXME:
181 output.push('<!--', escape(node.nodeValue, true), '-->');
182 break;
183 default:
184 output.push("<!-- Element not recognized - Type: ", node.nodeType, " Name: ", node.nodeName, "-->");
185 }
186 };
187
188 exports.getChildrenHtml = function(/*DomNode*/ node){
189 // summary:
190 // Returns the html content of a DomNode's children
191 var output = [];
192 exports.getChildrenHtmlHelper(node, output);
193 return output.join("");
194 };
195
196 exports.getChildrenHtmlHelper = function(/*DomNode*/ dom, /*String[]*/ output){
197 // summary:
198 // Pushes the html content of a DomNode's children into out[]
199
200 if(!dom){ return; }
201 var nodes = dom["childNodes"] || dom;
202
203 // IE issue.
204 // If we have an actual node we can check parent relationships on for IE,
205 // We should check, as IE sometimes builds invalid DOMS. If no parent, we can't check
206 // And should just process it and hope for the best.
207 var checkParent = !has("ie") || nodes !== dom;
208
209 var node, i = 0;
210 while((node = nodes[i++])){
211 // IE is broken. DOMs are supposed to be a tree. But in the case of malformed HTML, IE generates a graph
212 // meaning one node ends up with multiple references (multiple parents). This is totally wrong and invalid, but
213 // such is what it is. We have to keep track and check for this because otherwise the source output HTML will have dups.
214 // No other browser generates a graph. Leave it to IE to break a fundamental DOM rule. So, we check the parent if we can
215 // If we can't, nothing more we can do other than walk it.
216 if(!checkParent || node.parentNode == dom){
217 exports.getNodeHtmlHelper(node, output);
218 }
219 }
220 };
221
222 return exports;
223 });