html.js.uncompressed.js 7.1 KB

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