PageRenderTime 92ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/backend/Metis/dist/assets/lib/rangy-1.3/uncompressed/rangy-serializer.js

https://gitlab.com/kaouech/theme
JavaScript | 295 lines | 239 code | 35 blank | 21 comment | 61 complexity | 27afbeeb8cfa3145ea189765c8bab444 MD5 | raw file
  1. /**
  2. * Serializer module for Rangy.
  3. * Serializes Ranges and Selections. An example use would be to store a user's selection on a particular page in a
  4. * cookie or local storage and restore it on the user's next visit to the same page.
  5. *
  6. * Part of Rangy, a cross-browser JavaScript range and selection library
  7. * http://code.google.com/p/rangy/
  8. *
  9. * Depends on Rangy core.
  10. *
  11. * Copyright 2013, Tim Down
  12. * Licensed under the MIT license.
  13. * Version: 1.3alpha.804
  14. * Build date: 8 December 2013
  15. */
  16. rangy.createModule("Serializer", ["WrappedSelection"], function(api, module) {
  17. var UNDEF = "undefined";
  18. // encodeURIComponent and decodeURIComponent are required for cookie handling
  19. if (typeof encodeURIComponent == UNDEF || typeof decodeURIComponent == UNDEF) {
  20. module.fail("Global object is missing encodeURIComponent and/or decodeURIComponent method");
  21. }
  22. // Checksum for checking whether range can be serialized
  23. var crc32 = (function() {
  24. function utf8encode(str) {
  25. var utf8CharCodes = [];
  26. for (var i = 0, len = str.length, c; i < len; ++i) {
  27. c = str.charCodeAt(i);
  28. if (c < 128) {
  29. utf8CharCodes.push(c);
  30. } else if (c < 2048) {
  31. utf8CharCodes.push((c >> 6) | 192, (c & 63) | 128);
  32. } else {
  33. utf8CharCodes.push((c >> 12) | 224, ((c >> 6) & 63) | 128, (c & 63) | 128);
  34. }
  35. }
  36. return utf8CharCodes;
  37. }
  38. var cachedCrcTable = null;
  39. function buildCRCTable() {
  40. var table = [];
  41. for (var i = 0, j, crc; i < 256; ++i) {
  42. crc = i;
  43. j = 8;
  44. while (j--) {
  45. if ((crc & 1) == 1) {
  46. crc = (crc >>> 1) ^ 0xEDB88320;
  47. } else {
  48. crc >>>= 1;
  49. }
  50. }
  51. table[i] = crc >>> 0;
  52. }
  53. return table;
  54. }
  55. function getCrcTable() {
  56. if (!cachedCrcTable) {
  57. cachedCrcTable = buildCRCTable();
  58. }
  59. return cachedCrcTable;
  60. }
  61. return function(str) {
  62. var utf8CharCodes = utf8encode(str), crc = -1, crcTable = getCrcTable();
  63. for (var i = 0, len = utf8CharCodes.length, y; i < len; ++i) {
  64. y = (crc ^ utf8CharCodes[i]) & 0xFF;
  65. crc = (crc >>> 8) ^ crcTable[y];
  66. }
  67. return (crc ^ -1) >>> 0;
  68. };
  69. })();
  70. var dom = api.dom;
  71. function escapeTextForHtml(str) {
  72. return str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
  73. }
  74. function nodeToInfoString(node, infoParts) {
  75. infoParts = infoParts || [];
  76. var nodeType = node.nodeType, children = node.childNodes, childCount = children.length;
  77. var nodeInfo = [nodeType, node.nodeName, childCount].join(":");
  78. var start = "", end = "";
  79. switch (nodeType) {
  80. case 3: // Text node
  81. start = escapeTextForHtml(node.nodeValue);
  82. break;
  83. case 8: // Comment
  84. start = "<!--" + escapeTextForHtml(node.nodeValue) + "-->";
  85. break;
  86. default:
  87. start = "<" + nodeInfo + ">";
  88. end = "</>";
  89. break;
  90. }
  91. if (start) {
  92. infoParts.push(start);
  93. }
  94. for (var i = 0; i < childCount; ++i) {
  95. nodeToInfoString(children[i], infoParts);
  96. }
  97. if (end) {
  98. infoParts.push(end);
  99. }
  100. return infoParts;
  101. }
  102. // Creates a string representation of the specified element's contents that is similar to innerHTML but omits all
  103. // attributes and comments and includes child node counts. This is done instead of using innerHTML to work around
  104. // IE <= 8's policy of including element properties in attributes, which ruins things by changing an element's
  105. // innerHTML whenever the user changes an input within the element.
  106. function getElementChecksum(el) {
  107. var info = nodeToInfoString(el).join("");
  108. return crc32(info).toString(16);
  109. }
  110. function serializePosition(node, offset, rootNode) {
  111. var pathParts = [], n = node;
  112. rootNode = rootNode || dom.getDocument(node).documentElement;
  113. while (n && n != rootNode) {
  114. pathParts.push(dom.getNodeIndex(n, true));
  115. n = n.parentNode;
  116. }
  117. return pathParts.join("/") + ":" + offset;
  118. }
  119. function deserializePosition(serialized, rootNode, doc) {
  120. if (!rootNode) {
  121. rootNode = (doc || document).documentElement;
  122. }
  123. var parts = serialized.split(":");
  124. var node = rootNode;
  125. var nodeIndices = parts[0] ? parts[0].split("/") : [], i = nodeIndices.length, nodeIndex;
  126. while (i--) {
  127. nodeIndex = parseInt(nodeIndices[i], 10);
  128. if (nodeIndex < node.childNodes.length) {
  129. node = node.childNodes[nodeIndex];
  130. } else {
  131. throw module.createError("deserializePosition() failed: node " + dom.inspectNode(node) +
  132. " has no child with index " + nodeIndex + ", " + i);
  133. }
  134. }
  135. return new dom.DomPosition(node, parseInt(parts[1], 10));
  136. }
  137. function serializeRange(range, omitChecksum, rootNode) {
  138. rootNode = rootNode || api.DomRange.getRangeDocument(range).documentElement;
  139. if (!dom.isOrIsAncestorOf(rootNode, range.commonAncestorContainer)) {
  140. throw module.createError("serializeRange(): range " + range.inspect() +
  141. " is not wholly contained within specified root node " + dom.inspectNode(rootNode));
  142. }
  143. var serialized = serializePosition(range.startContainer, range.startOffset, rootNode) + "," +
  144. serializePosition(range.endContainer, range.endOffset, rootNode);
  145. if (!omitChecksum) {
  146. serialized += "{" + getElementChecksum(rootNode) + "}";
  147. }
  148. return serialized;
  149. }
  150. var deserializeRegex = /^([^,]+),([^,\{]+)(\{([^}]+)\})?$/;
  151. function deserializeRange(serialized, rootNode, doc) {
  152. if (rootNode) {
  153. doc = doc || dom.getDocument(rootNode);
  154. } else {
  155. doc = doc || document;
  156. rootNode = doc.documentElement;
  157. }
  158. var result = deserializeRegex.exec(serialized);
  159. var checksum = result[4], rootNodeChecksum = getElementChecksum(rootNode);
  160. if (checksum && checksum !== getElementChecksum(rootNode)) {
  161. throw module.createError("deserializeRange(): checksums of serialized range root node (" + checksum +
  162. ") and target root node (" + rootNodeChecksum + ") do not match");
  163. }
  164. var start = deserializePosition(result[1], rootNode, doc), end = deserializePosition(result[2], rootNode, doc);
  165. var range = api.createRange(doc);
  166. range.setStartAndEnd(start.node, start.offset, end.node, end.offset);
  167. return range;
  168. }
  169. function canDeserializeRange(serialized, rootNode, doc) {
  170. if (!rootNode) {
  171. rootNode = (doc || document).documentElement;
  172. }
  173. var result = deserializeRegex.exec(serialized);
  174. var checksum = result[3];
  175. return !checksum || checksum === getElementChecksum(rootNode);
  176. }
  177. function serializeSelection(selection, omitChecksum, rootNode) {
  178. selection = api.getSelection(selection);
  179. var ranges = selection.getAllRanges(), serializedRanges = [];
  180. for (var i = 0, len = ranges.length; i < len; ++i) {
  181. serializedRanges[i] = serializeRange(ranges[i], omitChecksum, rootNode);
  182. }
  183. return serializedRanges.join("|");
  184. }
  185. function deserializeSelection(serialized, rootNode, win) {
  186. if (rootNode) {
  187. win = win || dom.getWindow(rootNode);
  188. } else {
  189. win = win || window;
  190. rootNode = win.document.documentElement;
  191. }
  192. var serializedRanges = serialized.split("|");
  193. var sel = api.getSelection(win);
  194. var ranges = [];
  195. for (var i = 0, len = serializedRanges.length; i < len; ++i) {
  196. ranges[i] = deserializeRange(serializedRanges[i], rootNode, win.document);
  197. }
  198. sel.setRanges(ranges);
  199. return sel;
  200. }
  201. function canDeserializeSelection(serialized, rootNode, win) {
  202. var doc;
  203. if (rootNode) {
  204. doc = win ? win.document : dom.getDocument(rootNode);
  205. } else {
  206. win = win || window;
  207. rootNode = win.document.documentElement;
  208. }
  209. var serializedRanges = serialized.split("|");
  210. for (var i = 0, len = serializedRanges.length; i < len; ++i) {
  211. if (!canDeserializeRange(serializedRanges[i], rootNode, doc)) {
  212. return false;
  213. }
  214. }
  215. return true;
  216. }
  217. var cookieName = "rangySerializedSelection";
  218. function getSerializedSelectionFromCookie(cookie) {
  219. var parts = cookie.split(/[;,]/);
  220. for (var i = 0, len = parts.length, nameVal, val; i < len; ++i) {
  221. nameVal = parts[i].split("=");
  222. if (nameVal[0].replace(/^\s+/, "") == cookieName) {
  223. val = nameVal[1];
  224. if (val) {
  225. return decodeURIComponent(val.replace(/\s+$/, ""));
  226. }
  227. }
  228. }
  229. return null;
  230. }
  231. function restoreSelectionFromCookie(win) {
  232. win = win || window;
  233. var serialized = getSerializedSelectionFromCookie(win.document.cookie);
  234. if (serialized) {
  235. deserializeSelection(serialized, win.doc);
  236. }
  237. }
  238. function saveSelectionCookie(win, props) {
  239. win = win || window;
  240. props = (typeof props == "object") ? props : {};
  241. var expires = props.expires ? ";expires=" + props.expires.toUTCString() : "";
  242. var path = props.path ? ";path=" + props.path : "";
  243. var domain = props.domain ? ";domain=" + props.domain : "";
  244. var secure = props.secure ? ";secure" : "";
  245. var serialized = serializeSelection(api.getSelection(win));
  246. win.document.cookie = encodeURIComponent(cookieName) + "=" + encodeURIComponent(serialized) + expires + path + domain + secure;
  247. }
  248. api.serializePosition = serializePosition;
  249. api.deserializePosition = deserializePosition;
  250. api.serializeRange = serializeRange;
  251. api.deserializeRange = deserializeRange;
  252. api.canDeserializeRange = canDeserializeRange;
  253. api.serializeSelection = serializeSelection;
  254. api.deserializeSelection = deserializeSelection;
  255. api.canDeserializeSelection = canDeserializeSelection;
  256. api.restoreSelectionFromCookie = restoreSelectionFromCookie;
  257. api.saveSelectionCookie = saveSelectionCookie;
  258. api.getElementChecksum = getElementChecksum;
  259. api.nodeToInfoString = nodeToInfoString;
  260. });