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