vendor/assets/javascripts/rangy-selectionsaverestore.js in rangy-rails-1.3alpha.780.0 vs vendor/assets/javascripts/rangy-selectionsaverestore.js in rangy-rails-1.3alpha.804.0
- old
+ new
@@ -7,9 +7,229 @@
*
* Depends on Rangy core.
*
* Copyright 2013, Tim Down
* Licensed under the MIT license.
- * Version: 1.3alpha.780M
- * Build date: 17 May 2013
+ * Version: 1.3alpha.804
+ * Build date: 8 December 2013
*/
-rangy.createModule("SaveRestore",["WrappedRange"],function(a,b){function e(a,b){return(b||document).getElementById(a)}function f(a,b){var e="selectionBoundary_"+ +(new Date)+"_"+(""+Math.random()).slice(2),f,g=c.getDocument(a.startContainer),h=a.cloneRange();return h.collapse(b),f=g.createElement("span"),f.id=e,f.style.lineHeight="0",f.style.display="none",f.className="rangySelectionBoundary",f.appendChild(g.createTextNode(d)),h.insertNode(f),h.detach(),f}function g(a,c,d,f){var g=e(d,a);g?(c[f?"setStartBefore":"setEndBefore"](g),g.parentNode.removeChild(g)):b.warn("Marker element has been removed. Cannot restore selection.")}function h(a,b){return b.compareBoundaryPoints(a.START_TO_START,a)}function i(b,c){var d,e,g=a.DomRange.getRangeDocument(b),h=b.toString();return b.collapsed?(e=f(b,!1),{document:g,markerId:e.id,collapsed:!0}):(e=f(b,!1),d=f(b,!0),{document:g,startMarkerId:d.id,endMarkerId:e.id,collapsed:!1,backward:c,toString:function(){return"original text: '"+h+"', new text: '"+b.toString()+"'"}})}function j(c,d){var f=c.document;typeof d=="undefined"&&(d=!0);var h=a.createRange(f);if(c.collapsed){var i=e(c.markerId,f);if(i){i.style.display="inline";var j=i.previousSibling;j&&j.nodeType==3?(i.parentNode.removeChild(i),h.collapseToPoint(j,j.length)):(h.collapseBefore(i),i.parentNode.removeChild(i))}else b.warn("Marker element has been removed. Cannot restore selection.")}else g(f,h,c.startMarkerId,!0),g(f,h,c.endMarkerId,!1);return d&&h.normalizeBoundaries(),h}function k(b,c){var d=[],f,g;b=b.slice(0),b.sort(h);for(var j=0,k=b.length;j<k;++j)d[j]=i(b[j],c);for(j=k-1;j>=0;--j)f=b[j],g=a.DomRange.getRangeDocument(f),f.collapsed?f.collapseAfter(e(d[j].markerId,g)):(f.setEndBefore(e(d[j].endMarkerId,g)),f.setStartAfter(e(d[j].startMarkerId,g)));return d}function l(c){if(!a.isSelectionValid(c))return b.warn("Cannot save selection. This usually happens when the selection is collapsed and the selection document has lost focus."),null;var d=a.getSelection(c),e=d.getAllRanges(),f=e.length==1&&d.isBackward(),g=k(e,f);return f?d.setSingleRange(e[0],"backward"):d.setRanges(e),{win:c,rangeInfos:g,restored:!1}}function m(a){var b=[],c=a.length;for(var d=c-1;d>=0;d--)b[d]=j(a[d],!0);return b}function n(b,c){if(!b.restored){var d=b.rangeInfos,e=a.getSelection(b.win),f=m(d),g=d.length;g==1&&c&&a.features.selectionHasExtend&&d[0].backward?(e.removeAllRanges(),e.addRange(f[0],!0)):e.setRanges(f),b.restored=!0}}function o(a,b){var c=e(b,a);c&&c.parentNode.removeChild(c)}function p(a){var b=a.rangeInfos;for(var c=0,d=b.length,e;c<d;++c)e=b[c],e.collapsed?o(a.doc,e.markerId):(o(a.doc,e.startMarkerId),o(a.doc,e.endMarkerId))}var c=a.dom,d="\ufeff";a.util.extend(a,{saveRange:i,restoreRange:j,saveRanges:k,restoreRanges:m,saveSelection:l,restoreSelection:n,removeMarkerElement:o,removeMarkers:p})})
\ No newline at end of file
+rangy.createModule("SaveRestore", ["WrappedRange"], function(api, module) {
+ var dom = api.dom;
+
+ var markerTextChar = "\ufeff";
+
+ function gEBI(id, doc) {
+ return (doc || document).getElementById(id);
+ }
+
+ function insertRangeBoundaryMarker(range, atStart) {
+ var markerId = "selectionBoundary_" + (+new Date()) + "_" + ("" + Math.random()).slice(2);
+ var markerEl;
+ var doc = dom.getDocument(range.startContainer);
+
+ // Clone the Range and collapse to the appropriate boundary point
+ var boundaryRange = range.cloneRange();
+ boundaryRange.collapse(atStart);
+
+ // Create the marker element containing a single invisible character using DOM methods and insert it
+ markerEl = doc.createElement("span");
+ markerEl.id = markerId;
+ markerEl.style.lineHeight = "0";
+ markerEl.style.display = "none";
+ markerEl.className = "rangySelectionBoundary";
+ markerEl.appendChild(doc.createTextNode(markerTextChar));
+
+ boundaryRange.insertNode(markerEl);
+ boundaryRange.detach();
+ return markerEl;
+ }
+
+ function setRangeBoundary(doc, range, markerId, atStart) {
+ var markerEl = gEBI(markerId, doc);
+ if (markerEl) {
+ range[atStart ? "setStartBefore" : "setEndBefore"](markerEl);
+ markerEl.parentNode.removeChild(markerEl);
+ } else {
+ module.warn("Marker element has been removed. Cannot restore selection.");
+ }
+ }
+
+ function compareRanges(r1, r2) {
+ return r2.compareBoundaryPoints(r1.START_TO_START, r1);
+ }
+
+ function saveRange(range, backward) {
+ var startEl, endEl, doc = api.DomRange.getRangeDocument(range), text = range.toString();
+
+ if (range.collapsed) {
+ endEl = insertRangeBoundaryMarker(range, false);
+ return {
+ document: doc,
+ markerId: endEl.id,
+ collapsed: true
+ };
+ } else {
+ endEl = insertRangeBoundaryMarker(range, false);
+ startEl = insertRangeBoundaryMarker(range, true);
+
+ return {
+ document: doc,
+ startMarkerId: startEl.id,
+ endMarkerId: endEl.id,
+ collapsed: false,
+ backward: backward,
+ toString: function() {
+ return "original text: '" + text + "', new text: '" + range.toString() + "'";
+ }
+ };
+ }
+ }
+
+ function restoreRange(rangeInfo, normalize) {
+ var doc = rangeInfo.document;
+ if (typeof normalize == "undefined") {
+ normalize = true;
+ }
+ var range = api.createRange(doc);
+ if (rangeInfo.collapsed) {
+ var markerEl = gEBI(rangeInfo.markerId, doc);
+ if (markerEl) {
+ markerEl.style.display = "inline";
+ var previousNode = markerEl.previousSibling;
+
+ // Workaround for issue 17
+ if (previousNode && previousNode.nodeType == 3) {
+ markerEl.parentNode.removeChild(markerEl);
+ range.collapseToPoint(previousNode, previousNode.length);
+ } else {
+ range.collapseBefore(markerEl);
+ markerEl.parentNode.removeChild(markerEl);
+ }
+ } else {
+ module.warn("Marker element has been removed. Cannot restore selection.");
+ }
+ } else {
+ setRangeBoundary(doc, range, rangeInfo.startMarkerId, true);
+ setRangeBoundary(doc, range, rangeInfo.endMarkerId, false);
+ }
+
+ if (normalize) {
+ range.normalizeBoundaries();
+ }
+
+ return range;
+ }
+
+ function saveRanges(ranges, backward) {
+ var rangeInfos = [], range, doc;
+
+ // Order the ranges by position within the DOM, latest first, cloning the array to leave the original untouched
+ ranges = ranges.slice(0);
+ ranges.sort(compareRanges);
+
+ for (var i = 0, len = ranges.length; i < len; ++i) {
+ rangeInfos[i] = saveRange(ranges[i], backward);
+ }
+
+ // Now that all the markers are in place and DOM manipulation over, adjust each range's boundaries to lie
+ // between its markers
+ for (i = len - 1; i >= 0; --i) {
+ range = ranges[i];
+ doc = api.DomRange.getRangeDocument(range);
+ if (range.collapsed) {
+ range.collapseAfter(gEBI(rangeInfos[i].markerId, doc));
+ } else {
+ range.setEndBefore(gEBI(rangeInfos[i].endMarkerId, doc));
+ range.setStartAfter(gEBI(rangeInfos[i].startMarkerId, doc));
+ }
+ }
+
+ return rangeInfos;
+ }
+
+ function saveSelection(win) {
+ if (!api.isSelectionValid(win)) {
+ module.warn("Cannot save selection. This usually happens when the selection is collapsed and the selection document has lost focus.");
+ return null;
+ }
+ var sel = api.getSelection(win);
+ var ranges = sel.getAllRanges();
+ var backward = (ranges.length == 1 && sel.isBackward());
+
+ var rangeInfos = saveRanges(ranges, backward);
+
+ // Ensure current selection is unaffected
+ if (backward) {
+ sel.setSingleRange(ranges[0], "backward");
+ } else {
+ sel.setRanges(ranges);
+ }
+
+ return {
+ win: win,
+ rangeInfos: rangeInfos,
+ restored: false
+ };
+ }
+
+ function restoreRanges(rangeInfos) {
+ var ranges = [];
+
+ // Ranges are in reverse order of appearance in the DOM. We want to restore earliest first to avoid
+ // normalization affecting previously restored ranges.
+ var rangeCount = rangeInfos.length;
+
+ for (var i = rangeCount - 1; i >= 0; i--) {
+ ranges[i] = restoreRange(rangeInfos[i], true);
+ }
+
+ return ranges;
+ }
+
+ function restoreSelection(savedSelection, preserveDirection) {
+ if (!savedSelection.restored) {
+ var rangeInfos = savedSelection.rangeInfos;
+ var sel = api.getSelection(savedSelection.win);
+ var ranges = restoreRanges(rangeInfos), rangeCount = rangeInfos.length;
+
+ if (rangeCount == 1 && preserveDirection && api.features.selectionHasExtend && rangeInfos[0].backward) {
+ sel.removeAllRanges();
+ sel.addRange(ranges[0], true);
+ } else {
+ sel.setRanges(ranges);
+ }
+
+ savedSelection.restored = true;
+ }
+ }
+
+ function removeMarkerElement(doc, markerId) {
+ var markerEl = gEBI(markerId, doc);
+ if (markerEl) {
+ markerEl.parentNode.removeChild(markerEl);
+ }
+ }
+
+ function removeMarkers(savedSelection) {
+ var rangeInfos = savedSelection.rangeInfos;
+ for (var i = 0, len = rangeInfos.length, rangeInfo; i < len; ++i) {
+ rangeInfo = rangeInfos[i];
+ if (rangeInfo.collapsed) {
+ removeMarkerElement(savedSelection.doc, rangeInfo.markerId);
+ } else {
+ removeMarkerElement(savedSelection.doc, rangeInfo.startMarkerId);
+ removeMarkerElement(savedSelection.doc, rangeInfo.endMarkerId);
+ }
+ }
+ }
+
+ api.util.extend(api, {
+ saveRange: saveRange,
+ restoreRange: restoreRange,
+ saveRanges: saveRanges,
+ restoreRanges: restoreRanges,
+ saveSelection: saveSelection,
+ restoreSelection: restoreSelection,
+ removeMarkerElement: removeMarkerElement,
+ removeMarkers: removeMarkers
+ });
+});