rangy-rails 1.3alpha.772.0 → 1.3alpha.780.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +9 -6
- data/lib/rangy-rails/version.rb +1 -1
- data/vendor/assets/javascripts/rangy-core.js +3 -3637
- data/vendor/assets/javascripts/rangy-cssclassapplier.js +3 -923
- data/vendor/assets/javascripts/rangy-highlighter.js +3 -487
- data/vendor/assets/javascripts/rangy-position.js +15 -0
- data/vendor/assets/javascripts/rangy-selectionsaverestore.js +3 -225
- data/vendor/assets/javascripts/rangy-serializer.js +3 -281
- data/vendor/assets/javascripts/rangy-textrange.js +3 -1867
- metadata +3 -2
@@ -0,0 +1,15 @@
|
|
1
|
+
/**
|
2
|
+
* Position module for Rangy.
|
3
|
+
* Extensions to Range and Selection objects to provide access to pixel positions relative to the viewport or document.
|
4
|
+
*
|
5
|
+
* Part of Rangy, a cross-browser JavaScript range and selection library
|
6
|
+
* http://code.google.com/p/rangy/
|
7
|
+
*
|
8
|
+
* Depends on Rangy core.
|
9
|
+
*
|
10
|
+
* Copyright 2013, Tim Down
|
11
|
+
* Licensed under the MIT license.
|
12
|
+
* Version: 1.3alpha.780M
|
13
|
+
* Build date: 17 May 2013
|
14
|
+
*/
|
15
|
+
rangy.createModule("Position",["WrappedSelection"],function(a,b){function j(a){var b=0,d=0;if(typeof a.pageXOffset==c&&typeof a.pageYOffset==c)b=a.pageXOffset,d=a.pageYOffset;else{var e=a.document,f=e.documentElement,h=e.compatMode,i=typeof h=="string"&&h.indexOf("CSS")>=0&&f?f:g.getBody(e);if(i&&typeof i.scrollLeft==c&&typeof i.scrollTop==c)try{b=i.scrollLeft,d=i.scrollTop}catch(j){}}return{x:b,y:d}}function k(a,b){b=b.toLowerCase();while(a){if(a.nodeType==1&&a.tagName.toLowerCase()==b)return a;a=a.parentNode}return null}function l(a,b,c,d){this.top=a,this.right=b,this.bottom=c,this.left=d,this.width=b-d,this.height=c-a}function m(a,b,c){return new l(a.top+c,a.right+b,a.bottom+c,a.left+b)}function n(a,b){var d=0,e=0,f=b.documentElement,h=g.getBody(b),i=f.clientWidth===0&&typeof h.clientTop==c?h:f,j=i.clientLeft,k=i.clientTop;return j&&(d=-j),k&&(e=-k),m(a,d,e)}function o(a){var b=[],c=[],d=[],e=[];for(var f=0,g=a.length,h;f<g;++f)h=a[f],h&&(b.push(h.top),c.push(h.bottom),d.push(h.left),e.push(h.right));return new l(Math.min.apply(Math,b),Math.max.apply(Math,e),Math.max.apply(Math,c),Math.min.apply(Math,d))}function p(b,c,d){var e=g.getBody(b).createTextRange();e.moveToPoint(c,d);var f=new a.WrappedTextRange(e);return new i(f.startContainer,f.startOffset)}function q(a,b,c){var d=a.caretPositionFromPoint(b,c);return new i(d.offsetNode,d.offset)}function r(a,b,c){var d=a.caretRangeFromPoint(b,c);return new i(d.startContainer,d.startOffset)}function s(a){var b=(a.nativeRange||a).getClientRects();return b.length>0?b[b.length-1]:null}function t(a,b,c){return console.log("pointIsInOrAboveRect",a,b,Math.floor(c.top),Math.floor(c.right),Math.floor(c.bottom),Math.floor(c.left)),b<c.bottom&&a>=c.left&&a<=c.right}function u(b,c,d,e){var f=b.elementFromPoint(c,d);console.log("elementFromPoint is ",f);var h=a.createRange(b);h.selectNodeContents(f),h.collapse(!0);var j=f.firstChild,k,l,m;if(!j)j=f.parentNode,k=g.getNodeIndex(f),e||++k;else{a:while(j){console.log(j);if(j.nodeType==3)for(k=0,m=j.length;k<=m;++k){h.setEnd(j,k),l=s(h);if(l&&t(c,d,l)){l.right-c>c-l.left&&--k;break a}}else{h.setEndAfter(j),l=s(h);if(l&&t(c,d,l)){k=g.getNodeIndex(j),j=f.parentNode,e||++k;break}}j=j.nextSibling}j||(j=f,k=f.childNodes.length)}return new i(j,k)}function v(c){if(a.features.implementsTextRange)return p;if(typeof c.caretPositionFromPoint!=d)return q;if(typeof c.caretRangeFromPoint!=d)return r;if(typeof c.elementFromPoint!=d&&A)return u;throw b.createError("createCaretPositionFromPointGetter(): Browser does not provide a recognised method to create a selection from pixel coordinates")}function w(c,d,e,f,h){h=g.getContentDocument(h,b,"createRangeFromPoints");var i=v(h),j=i(h,c,d,!1),k=i(h,e,f,!0);console.log(j.node,j.offset,k.node,k.offset);var l=a.createRange(h);return l.setStartAndEnd(j.node,j.offset,k.node,k.offset),l}function x(a,b,c,d,e){var f,g,h,i,j=d<b||b==d&&c<a;j?(f=c,g=d,h=a,i=b):(f=a,g=b,h=c,i=d);var k=rangy.getSelection(e),l=w(f,g,h,i,e);return k.setSingleRange(l),k}function K(a,b){return a.compareBoundaryPoints(b.START_TO_START,b)}function L(a){return function(){var b="getBounding"+(a?"Document":"Client")+"Rect",c=[];for(var d=0,e=null,f;d<this.rangeCount;++d)c.push(this.getRangeAt(d)[b]());return o(c)}}function M(a,b){return function(){if(this.rangeCount==0)return null;var c=b?"Document":"Client",d=this.getAllRanges();return d.length>1&&d.sort(K),a?d[0]["getStart"+c+"Pos"]():d[d.length-1]["getEnd"+c+"Pos"]()}}var c="number",d="undefined",e=a.WrappedRange,f=a.WrappedTextRange,g=a.dom,h=a.util,i=g.DomPosition,y=document.createElement("span"),z=h.isHostMethod(y,"getBoundingClientRect");y=null;var A=!1,B=!1;if(a.features.implementsDomRange){var C=a.createNativeRange();A=h.isHostMethod(C,"getClientRects"),B=h.isHostMethod(C,"getBoundingClientRect"),C.detach()}h.extend(a.features,{rangeSupportsGetBoundingClientRect:B,rangeSupportsGetClientRects:A,elementSupportsGetBoundingClientRect:z});var D=function(a){return function(){var b=this.cloneRange();b.collapse(a);var c=b.getBoundingClientRect();return{x:c[a?"left":"right"],y:c[a?"top":"bottom"]}}},E=a.rangePrototype;if(a.features.implementsTextRange&&z)E.getBoundingClientRect=function(){var a=f.rangeToTextRange(this),b=this.getNodes([1],function(a){return/^t[dh]$/i.test(a.tagName)}),c,d=[];if(b.length>0){var e=k(this.startContainer,"table");for(var h=0,i,j,l,m,p;i=b[h];++h){l=k(i,"table");if(!e||l!=e)m=this.cloneRange(),e&&m.setStartAfter(e),m.setEndBefore(l),d.push(f.rangeToTextRange(m).getBoundingClientRect());this.containsNode(i)?d.push(i.getBoundingClientRect()):(j=a.duplicate(),j.moveToElementText(i),j.compareEndPoints("StartToStart",a)==-1?j.setEndPoint("StartToStart",a):j.compareEndPoints("EndToEnd",a)==1&&j.setEndPoint("EndToEnd",a),d.push(j.getBoundingClientRect())),e=l}var q=k(this.endContainer,"table");!q&&e&&(m=this.cloneRange(),m.setStartAfter(e),d.push(f.rangeToTextRange(m).getBoundingClientRect())),c=o(d)}else c=a.getBoundingClientRect();return n(c,g.getDocument(this.startContainer))};else if(a.features.implementsDomRange){var F=function(a){return a instanceof e?a:new e(a)};if(B){E.getBoundingClientRect=function(){var a=F(this).nativeRange,b=a.getBoundingClientRect()||a.getClientRects()[0];return n(b,g.getDocument(this.startContainer))};if(A){var G=function(a,b){var c=a.childNodes};D=function(a){return function(){var c,d=F(this).nativeRange,e=d.getClientRects();if(e.length==0&&z){!a,console.log(d,d.getClientRects(),d.getBoundingClientRect());if(this.collapsed&&this.startContainer.nodeType==1&&this.startOffset<this.startContainer.childNodes.length){var f=this.startContainer.childNodes[this.startOffset];f.getClientRects&&console.log(f,f.getClientRects(),this.startContainer.getClientRects())}}if(e.length>0)return a?(c=e[0],{x:c.left,y:c.top}):(c=e[e.length-1],{x:c.right,y:c.bottom});throw b.createError("Cannot get position for range "+this.inspect())}}}}else{var H=z?function(a){return n(a.getBoundingClientRect(),g.getDocument(a))}:function(a){var b=0,c=0,d=a,e=a.offsetWidth,f=a.offsetHeight;while(d)b+=d.offsetLeft,c+=d.offsetTop,d=d.offsetParent;return n(new l(c,b+e,c+f,b),g.getDocument(a))},I=function(a){var b;a.splitBoundaries();var c=document.createElement("span");if(a.collapsed)a.insertNode(c),b=H(c),c.parentNode.removeChild(c);else{var d=a.cloneRange();d.collapse(!0),d.insertNode(c);var e=H(c);c.parentNode.removeChild(c),d.collapseToPoint(a.endContainer,a.endOffset),d.insertNode(c);var f=H(c);c.parentNode.removeChild(c);var g=[e,f],h=a.getNodes([1],function(b){return a.containsNode(b)});for(var i=0,j=h.length;i<j;++i)g.push(H(h[i]));b=o(g)}return a.normalizeBoundaries(),b};E.getBoundingClientRect=function(a){return I(F(a))}}function J(a){return function(){var b=this["get"+(a?"Start":"End")+"ClientPos"](),c=j(g.getWindow(this.startContainer));return{x:b.x+c.x,y:b.y+c.y}}}}h.extend(E,{getBoundingDocumentRect:function(){var a=j(g.getWindow(this.startContainer));return m(this.getBoundingClientRect(),a.x,a.y)},getStartClientPos:D(!0),getEndClientPos:D(!1),getStartDocumentPos:J(!0),getEndDocumentPos:J(!1)}),h.extend(a.selectionPrototype,{getBoundingClientRect:L(!1),getBoundingDocumentRect:L(!0),getStartClientPos:M(!0,!1),getEndClientPos:M(!1,!1),getStartDocumentPos:M(!0,!0),getEndDocumentPos:M(!1,!0)}),a.positionFromPoint=function(a,c,d){return d=g.getContentDocument(d,b,"positionFromPoint"),v(d)(d,a,c)},a.createRangeFromPoints=w,a.moveSelectionToPoints=x})
|
@@ -9,229 +9,7 @@
|
|
9
9
|
*
|
10
10
|
* Copyright 2013, Tim Down
|
11
11
|
* Licensed under the MIT license.
|
12
|
-
* Version: 1.3alpha.
|
13
|
-
* Build date:
|
12
|
+
* Version: 1.3alpha.780M
|
13
|
+
* Build date: 17 May 2013
|
14
14
|
*/
|
15
|
-
rangy.createModule("SaveRestore", function(
|
16
|
-
api.requireModules( ["DomUtil", "DomRange", "WrappedRange"] );
|
17
|
-
|
18
|
-
var dom = api.dom;
|
19
|
-
|
20
|
-
var markerTextChar = "\ufeff";
|
21
|
-
|
22
|
-
function gEBI(id, doc) {
|
23
|
-
return (doc || document).getElementById(id);
|
24
|
-
}
|
25
|
-
|
26
|
-
function insertRangeBoundaryMarker(range, atStart) {
|
27
|
-
var markerId = "selectionBoundary_" + (+new Date()) + "_" + ("" + Math.random()).slice(2);
|
28
|
-
var markerEl;
|
29
|
-
var doc = dom.getDocument(range.startContainer);
|
30
|
-
|
31
|
-
// Clone the Range and collapse to the appropriate boundary point
|
32
|
-
var boundaryRange = range.cloneRange();
|
33
|
-
boundaryRange.collapse(atStart);
|
34
|
-
|
35
|
-
// Create the marker element containing a single invisible character using DOM methods and insert it
|
36
|
-
markerEl = doc.createElement("span");
|
37
|
-
markerEl.id = markerId;
|
38
|
-
markerEl.style.lineHeight = "0";
|
39
|
-
markerEl.style.display = "none";
|
40
|
-
markerEl.className = "rangySelectionBoundary";
|
41
|
-
markerEl.appendChild(doc.createTextNode(markerTextChar));
|
42
|
-
|
43
|
-
boundaryRange.insertNode(markerEl);
|
44
|
-
boundaryRange.detach();
|
45
|
-
return markerEl;
|
46
|
-
}
|
47
|
-
|
48
|
-
function setRangeBoundary(doc, range, markerId, atStart) {
|
49
|
-
var markerEl = gEBI(markerId, doc);
|
50
|
-
if (markerEl) {
|
51
|
-
range[atStart ? "setStartBefore" : "setEndBefore"](markerEl);
|
52
|
-
markerEl.parentNode.removeChild(markerEl);
|
53
|
-
} else {
|
54
|
-
module.warn("Marker element has been removed. Cannot restore selection.");
|
55
|
-
}
|
56
|
-
}
|
57
|
-
|
58
|
-
function compareRanges(r1, r2) {
|
59
|
-
return r2.compareBoundaryPoints(r1.START_TO_START, r1);
|
60
|
-
}
|
61
|
-
|
62
|
-
function saveRange(range, backward) {
|
63
|
-
var startEl, endEl, doc = api.DomRange.getRangeDocument(range), text = range.toString();
|
64
|
-
|
65
|
-
if (range.collapsed) {
|
66
|
-
endEl = insertRangeBoundaryMarker(range, false);
|
67
|
-
return {
|
68
|
-
document: doc,
|
69
|
-
markerId: endEl.id,
|
70
|
-
collapsed: true
|
71
|
-
};
|
72
|
-
} else {
|
73
|
-
endEl = insertRangeBoundaryMarker(range, false);
|
74
|
-
startEl = insertRangeBoundaryMarker(range, true);
|
75
|
-
|
76
|
-
return {
|
77
|
-
document: doc,
|
78
|
-
startMarkerId: startEl.id,
|
79
|
-
endMarkerId: endEl.id,
|
80
|
-
collapsed: false,
|
81
|
-
backward: backward,
|
82
|
-
toString: function() {
|
83
|
-
return "original text: '" + text + "', new text: '" + range.toString() + "'";
|
84
|
-
}
|
85
|
-
};
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
function restoreRange(rangeInfo, normalize) {
|
90
|
-
var doc = rangeInfo.document;
|
91
|
-
if (typeof normalize == "undefined") {
|
92
|
-
normalize = true;
|
93
|
-
}
|
94
|
-
var range = api.createRange(doc);
|
95
|
-
if (rangeInfo.collapsed) {
|
96
|
-
var markerEl = gEBI(rangeInfo.markerId, doc);
|
97
|
-
if (markerEl) {
|
98
|
-
markerEl.style.display = "inline";
|
99
|
-
var previousNode = markerEl.previousSibling;
|
100
|
-
|
101
|
-
// Workaround for issue 17
|
102
|
-
if (previousNode && previousNode.nodeType == 3) {
|
103
|
-
markerEl.parentNode.removeChild(markerEl);
|
104
|
-
range.collapseToPoint(previousNode, previousNode.length);
|
105
|
-
} else {
|
106
|
-
range.collapseBefore(markerEl);
|
107
|
-
markerEl.parentNode.removeChild(markerEl);
|
108
|
-
}
|
109
|
-
} else {
|
110
|
-
module.warn("Marker element has been removed. Cannot restore selection.");
|
111
|
-
}
|
112
|
-
} else {
|
113
|
-
setRangeBoundary(doc, range, rangeInfo.startMarkerId, true);
|
114
|
-
setRangeBoundary(doc, range, rangeInfo.endMarkerId, false);
|
115
|
-
}
|
116
|
-
|
117
|
-
if (normalize) {
|
118
|
-
range.normalizeBoundaries();
|
119
|
-
}
|
120
|
-
|
121
|
-
return range;
|
122
|
-
}
|
123
|
-
|
124
|
-
function saveRanges(ranges, backward) {
|
125
|
-
var rangeInfos = [], range, doc;
|
126
|
-
|
127
|
-
// Order the ranges by position within the DOM, latest first, cloning the array to leave the original untouched
|
128
|
-
ranges = ranges.slice(0);
|
129
|
-
ranges.sort(compareRanges);
|
130
|
-
|
131
|
-
for (var i = 0, len = ranges.length; i < len; ++i) {
|
132
|
-
rangeInfos[i] = saveRange(ranges[i], backward);
|
133
|
-
}
|
134
|
-
|
135
|
-
// Now that all the markers are in place and DOM manipulation over, adjust each range's boundaries to lie
|
136
|
-
// between its markers
|
137
|
-
for (i = len - 1; i >= 0; --i) {
|
138
|
-
range = ranges[i];
|
139
|
-
doc = api.DomRange.getRangeDocument(range);
|
140
|
-
if (range.collapsed) {
|
141
|
-
range.collapseAfter(gEBI(rangeInfos[i].markerId, doc));
|
142
|
-
} else {
|
143
|
-
range.setEndBefore(gEBI(rangeInfos[i].endMarkerId, doc));
|
144
|
-
range.setStartAfter(gEBI(rangeInfos[i].startMarkerId, doc));
|
145
|
-
}
|
146
|
-
}
|
147
|
-
|
148
|
-
return rangeInfos;
|
149
|
-
}
|
150
|
-
|
151
|
-
function saveSelection(win) {
|
152
|
-
if (!api.isSelectionValid(win)) {
|
153
|
-
module.warn("Cannot save selection. This usually happens when the selection is collapsed and the selection document has lost focus.");
|
154
|
-
return null;
|
155
|
-
}
|
156
|
-
var sel = api.getSelection(win);
|
157
|
-
var ranges = sel.getAllRanges();
|
158
|
-
var backward = (ranges.length == 1 && sel.isBackward());
|
159
|
-
|
160
|
-
var rangeInfos = saveRanges(ranges, backward);
|
161
|
-
|
162
|
-
// Ensure current selection is unaffected
|
163
|
-
if (backward) {
|
164
|
-
sel.setSingleRange(ranges[0], "backward");
|
165
|
-
} else {
|
166
|
-
sel.setRanges(ranges);
|
167
|
-
}
|
168
|
-
|
169
|
-
return {
|
170
|
-
win: win,
|
171
|
-
rangeInfos: rangeInfos,
|
172
|
-
restored: false
|
173
|
-
};
|
174
|
-
}
|
175
|
-
|
176
|
-
function restoreRanges(rangeInfos) {
|
177
|
-
var ranges = [];
|
178
|
-
|
179
|
-
// Ranges are in reverse order of appearance in the DOM. We want to restore earliest first to avoid
|
180
|
-
// normalization affecting previously restored ranges.
|
181
|
-
var rangeCount = rangeInfos.length;
|
182
|
-
|
183
|
-
for (var i = rangeCount - 1; i >= 0; i--) {
|
184
|
-
ranges[i] = restoreRange(rangeInfos[i], true);
|
185
|
-
}
|
186
|
-
|
187
|
-
return ranges;
|
188
|
-
}
|
189
|
-
|
190
|
-
function restoreSelection(savedSelection, preserveDirection) {
|
191
|
-
if (!savedSelection.restored) {
|
192
|
-
var rangeInfos = savedSelection.rangeInfos;
|
193
|
-
var sel = api.getSelection(savedSelection.win);
|
194
|
-
var ranges = restoreRanges(rangeInfos), rangeCount = rangeInfos.length;
|
195
|
-
|
196
|
-
if (rangeCount == 1 && preserveDirection && api.features.selectionHasExtend && rangeInfos[0].backward) {
|
197
|
-
sel.removeAllRanges();
|
198
|
-
sel.addRange(ranges[0], true);
|
199
|
-
} else {
|
200
|
-
sel.setRanges(ranges);
|
201
|
-
}
|
202
|
-
|
203
|
-
savedSelection.restored = true;
|
204
|
-
}
|
205
|
-
}
|
206
|
-
|
207
|
-
function removeMarkerElement(doc, markerId) {
|
208
|
-
var markerEl = gEBI(markerId, doc);
|
209
|
-
if (markerEl) {
|
210
|
-
markerEl.parentNode.removeChild(markerEl);
|
211
|
-
}
|
212
|
-
}
|
213
|
-
|
214
|
-
function removeMarkers(savedSelection) {
|
215
|
-
var rangeInfos = savedSelection.rangeInfos;
|
216
|
-
for (var i = 0, len = rangeInfos.length, rangeInfo; i < len; ++i) {
|
217
|
-
rangeInfo = rangeInfos[i];
|
218
|
-
if (rangeInfo.collapsed) {
|
219
|
-
removeMarkerElement(savedSelection.doc, rangeInfo.markerId);
|
220
|
-
} else {
|
221
|
-
removeMarkerElement(savedSelection.doc, rangeInfo.startMarkerId);
|
222
|
-
removeMarkerElement(savedSelection.doc, rangeInfo.endMarkerId);
|
223
|
-
}
|
224
|
-
}
|
225
|
-
}
|
226
|
-
|
227
|
-
api.util.extend(api, {
|
228
|
-
saveRange: saveRange,
|
229
|
-
restoreRange: restoreRange,
|
230
|
-
saveRanges: saveRanges,
|
231
|
-
restoreRanges: restoreRanges,
|
232
|
-
saveSelection: saveSelection,
|
233
|
-
restoreSelection: restoreSelection,
|
234
|
-
removeMarkerElement: removeMarkerElement,
|
235
|
-
removeMarkers: removeMarkers
|
236
|
-
});
|
237
|
-
});
|
15
|
+
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})})
|
@@ -10,285 +10,7 @@
|
|
10
10
|
*
|
11
11
|
* Copyright 2013, Tim Down
|
12
12
|
* Licensed under the MIT license.
|
13
|
-
* Version: 1.3alpha.
|
14
|
-
* Build date:
|
13
|
+
* Version: 1.3alpha.780M
|
14
|
+
* Build date: 17 May 2013
|
15
15
|
*/
|
16
|
-
rangy.createModule("Serializer", function(
|
17
|
-
api.requireModules( ["WrappedSelection", "WrappedRange"] );
|
18
|
-
var UNDEF = "undefined";
|
19
|
-
|
20
|
-
// encodeURIComponent and decodeURIComponent are required for cookie handling
|
21
|
-
if (typeof encodeURIComponent == UNDEF || typeof decodeURIComponent == UNDEF) {
|
22
|
-
module.fail("Global object is missing encodeURIComponent and/or decodeURIComponent method");
|
23
|
-
}
|
24
|
-
|
25
|
-
// Checksum for checking whether range can be serialized
|
26
|
-
var crc32 = (function() {
|
27
|
-
function utf8encode(str) {
|
28
|
-
var utf8CharCodes = [];
|
29
|
-
|
30
|
-
for (var i = 0, len = str.length, c; i < len; ++i) {
|
31
|
-
c = str.charCodeAt(i);
|
32
|
-
if (c < 128) {
|
33
|
-
utf8CharCodes.push(c);
|
34
|
-
} else if (c < 2048) {
|
35
|
-
utf8CharCodes.push((c >> 6) | 192, (c & 63) | 128);
|
36
|
-
} else {
|
37
|
-
utf8CharCodes.push((c >> 12) | 224, ((c >> 6) & 63) | 128, (c & 63) | 128);
|
38
|
-
}
|
39
|
-
}
|
40
|
-
return utf8CharCodes;
|
41
|
-
}
|
42
|
-
|
43
|
-
var cachedCrcTable = null;
|
44
|
-
|
45
|
-
function buildCRCTable() {
|
46
|
-
var table = [];
|
47
|
-
for (var i = 0, j, crc; i < 256; ++i) {
|
48
|
-
crc = i;
|
49
|
-
j = 8;
|
50
|
-
while (j--) {
|
51
|
-
if ((crc & 1) == 1) {
|
52
|
-
crc = (crc >>> 1) ^ 0xEDB88320;
|
53
|
-
} else {
|
54
|
-
crc >>>= 1;
|
55
|
-
}
|
56
|
-
}
|
57
|
-
table[i] = crc >>> 0;
|
58
|
-
}
|
59
|
-
return table;
|
60
|
-
}
|
61
|
-
|
62
|
-
function getCrcTable() {
|
63
|
-
if (!cachedCrcTable) {
|
64
|
-
cachedCrcTable = buildCRCTable();
|
65
|
-
}
|
66
|
-
return cachedCrcTable;
|
67
|
-
}
|
68
|
-
|
69
|
-
return function(str) {
|
70
|
-
var utf8CharCodes = utf8encode(str), crc = -1, crcTable = getCrcTable();
|
71
|
-
for (var i = 0, len = utf8CharCodes.length, y; i < len; ++i) {
|
72
|
-
y = (crc ^ utf8CharCodes[i]) & 0xFF;
|
73
|
-
crc = (crc >>> 8) ^ crcTable[y];
|
74
|
-
}
|
75
|
-
return (crc ^ -1) >>> 0;
|
76
|
-
};
|
77
|
-
})();
|
78
|
-
|
79
|
-
var dom = api.dom;
|
80
|
-
|
81
|
-
function escapeTextForHtml(str) {
|
82
|
-
return str.replace(/</g, "<").replace(/>/g, ">");
|
83
|
-
}
|
84
|
-
|
85
|
-
function nodeToInfoString(node, infoParts) {
|
86
|
-
infoParts = infoParts || [];
|
87
|
-
var nodeType = node.nodeType, children = node.childNodes, childCount = children.length;
|
88
|
-
var nodeInfo = [nodeType, node.nodeName, childCount].join(":");
|
89
|
-
var start = "", end = "";
|
90
|
-
switch (nodeType) {
|
91
|
-
case 3: // Text node
|
92
|
-
start = escapeTextForHtml(node.nodeValue);
|
93
|
-
break;
|
94
|
-
case 8: // Comment
|
95
|
-
start = "<!--" + escapeTextForHtml(node.nodeValue) + "-->";
|
96
|
-
break;
|
97
|
-
default:
|
98
|
-
start = "<" + nodeInfo + ">";
|
99
|
-
end = "</>";
|
100
|
-
break;
|
101
|
-
}
|
102
|
-
if (start) {
|
103
|
-
infoParts.push(start);
|
104
|
-
}
|
105
|
-
for (var i = 0; i < childCount; ++i) {
|
106
|
-
nodeToInfoString(children[i], infoParts);
|
107
|
-
}
|
108
|
-
if (end) {
|
109
|
-
infoParts.push(end);
|
110
|
-
}
|
111
|
-
return infoParts;
|
112
|
-
}
|
113
|
-
|
114
|
-
// Creates a string representation of the specified element's contents that is similar to innerHTML but omits all
|
115
|
-
// attributes and comments and includes child node counts. This is done instead of using innerHTML to work around
|
116
|
-
// IE <= 8's policy of including element properties in attributes, which ruins things by changing an element's
|
117
|
-
// innerHTML whenever the user changes an input within the element.
|
118
|
-
function getElementChecksum(el) {
|
119
|
-
var info = nodeToInfoString(el).join("");
|
120
|
-
return crc32(info).toString(16);
|
121
|
-
}
|
122
|
-
|
123
|
-
function serializePosition(node, offset, rootNode) {
|
124
|
-
var pathBits = [], n = node;
|
125
|
-
rootNode = rootNode || dom.getDocument(node).documentElement;
|
126
|
-
while (n && n != rootNode) {
|
127
|
-
pathBits.push(dom.getNodeIndex(n, true));
|
128
|
-
n = n.parentNode;
|
129
|
-
}
|
130
|
-
return pathBits.join("/") + ":" + offset;
|
131
|
-
}
|
132
|
-
|
133
|
-
function deserializePosition(serialized, rootNode, doc) {
|
134
|
-
if (!rootNode) {
|
135
|
-
rootNode = (doc || document).documentElement;
|
136
|
-
}
|
137
|
-
var bits = serialized.split(":");
|
138
|
-
var node = rootNode;
|
139
|
-
var nodeIndices = bits[0] ? bits[0].split("/") : [], i = nodeIndices.length, nodeIndex;
|
140
|
-
|
141
|
-
while (i--) {
|
142
|
-
nodeIndex = parseInt(nodeIndices[i], 10);
|
143
|
-
if (nodeIndex < node.childNodes.length) {
|
144
|
-
node = node.childNodes[nodeIndex];
|
145
|
-
} else {
|
146
|
-
throw module.createError("deserializePosition() failed: node " + dom.inspectNode(node) +
|
147
|
-
" has no child with index " + nodeIndex + ", " + i);
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
return new dom.DomPosition(node, parseInt(bits[1], 10));
|
152
|
-
}
|
153
|
-
|
154
|
-
function serializeRange(range, omitChecksum, rootNode) {
|
155
|
-
rootNode = rootNode || api.DomRange.getRangeDocument(range).documentElement;
|
156
|
-
if (!dom.isOrIsAncestorOf(rootNode, range.commonAncestorContainer)) {
|
157
|
-
throw module.createError("serializeRange(): range " + range.inspect() +
|
158
|
-
" is not wholly contained within specified root node " + dom.inspectNode(rootNode));
|
159
|
-
}
|
160
|
-
var serialized = serializePosition(range.startContainer, range.startOffset, rootNode) + "," +
|
161
|
-
serializePosition(range.endContainer, range.endOffset, rootNode);
|
162
|
-
if (!omitChecksum) {
|
163
|
-
serialized += "{" + getElementChecksum(rootNode) + "}";
|
164
|
-
}
|
165
|
-
return serialized;
|
166
|
-
}
|
167
|
-
|
168
|
-
function deserializeRange(serialized, rootNode, doc) {
|
169
|
-
if (rootNode) {
|
170
|
-
doc = doc || dom.getDocument(rootNode);
|
171
|
-
} else {
|
172
|
-
doc = doc || document;
|
173
|
-
rootNode = doc.documentElement;
|
174
|
-
}
|
175
|
-
var result = /^([^,]+),([^,\{]+)(\{([^}]+)\})?$/.exec(serialized);
|
176
|
-
var checksum = result[4], rootNodeChecksum = getElementChecksum(rootNode);
|
177
|
-
if (checksum && checksum !== getElementChecksum(rootNode)) {
|
178
|
-
throw module.createError("deserializeRange(): checksums of serialized range root node (" + checksum +
|
179
|
-
") and target root node (" + rootNodeChecksum + ") do not match");
|
180
|
-
}
|
181
|
-
var start = deserializePosition(result[1], rootNode, doc), end = deserializePosition(result[2], rootNode, doc);
|
182
|
-
var range = api.createRange(doc);
|
183
|
-
range.setStartAndEnd(start.node, start.offset, end.node, end.offset);
|
184
|
-
return range;
|
185
|
-
}
|
186
|
-
|
187
|
-
function canDeserializeRange(serialized, rootNode, doc) {
|
188
|
-
if (!rootNode) {
|
189
|
-
rootNode = (doc || document).documentElement;
|
190
|
-
}
|
191
|
-
var result = /^([^,]+),([^,]+)(\{([^}]+)\})?$/.exec(serialized);
|
192
|
-
var checksum = result[3];
|
193
|
-
return !checksum || checksum === getElementChecksum(rootNode);
|
194
|
-
}
|
195
|
-
|
196
|
-
function serializeSelection(selection, omitChecksum, rootNode) {
|
197
|
-
selection = api.getSelection(selection);
|
198
|
-
var ranges = selection.getAllRanges(), serializedRanges = [];
|
199
|
-
for (var i = 0, len = ranges.length; i < len; ++i) {
|
200
|
-
serializedRanges[i] = serializeRange(ranges[i], omitChecksum, rootNode);
|
201
|
-
}
|
202
|
-
return serializedRanges.join("|");
|
203
|
-
}
|
204
|
-
|
205
|
-
function deserializeSelection(serialized, rootNode, win) {
|
206
|
-
if (rootNode) {
|
207
|
-
win = win || dom.getWindow(rootNode);
|
208
|
-
} else {
|
209
|
-
win = win || window;
|
210
|
-
rootNode = win.document.documentElement;
|
211
|
-
}
|
212
|
-
var serializedRanges = serialized.split("|");
|
213
|
-
var sel = api.getSelection(win);
|
214
|
-
var ranges = [];
|
215
|
-
|
216
|
-
for (var i = 0, len = serializedRanges.length; i < len; ++i) {
|
217
|
-
ranges[i] = deserializeRange(serializedRanges[i], rootNode, win.document);
|
218
|
-
}
|
219
|
-
sel.setRanges(ranges);
|
220
|
-
|
221
|
-
return sel;
|
222
|
-
}
|
223
|
-
|
224
|
-
function canDeserializeSelection(serialized, rootNode, win) {
|
225
|
-
var doc;
|
226
|
-
if (rootNode) {
|
227
|
-
doc = win ? win.document : dom.getDocument(rootNode);
|
228
|
-
} else {
|
229
|
-
win = win || window;
|
230
|
-
rootNode = win.document.documentElement;
|
231
|
-
}
|
232
|
-
var serializedRanges = serialized.split("|");
|
233
|
-
|
234
|
-
for (var i = 0, len = serializedRanges.length; i < len; ++i) {
|
235
|
-
if (!canDeserializeRange(serializedRanges[i], rootNode, doc)) {
|
236
|
-
return false;
|
237
|
-
}
|
238
|
-
}
|
239
|
-
|
240
|
-
return true;
|
241
|
-
}
|
242
|
-
|
243
|
-
var cookieName = "rangySerializedSelection";
|
244
|
-
|
245
|
-
function getSerializedSelectionFromCookie(cookie) {
|
246
|
-
var parts = cookie.split(/[;,]/);
|
247
|
-
for (var i = 0, len = parts.length, nameVal, val; i < len; ++i) {
|
248
|
-
nameVal = parts[i].split("=");
|
249
|
-
if (nameVal[0].replace(/^\s+/, "") == cookieName) {
|
250
|
-
val = nameVal[1];
|
251
|
-
if (val) {
|
252
|
-
return decodeURIComponent(val.replace(/\s+$/, ""));
|
253
|
-
}
|
254
|
-
}
|
255
|
-
}
|
256
|
-
return null;
|
257
|
-
}
|
258
|
-
|
259
|
-
function restoreSelectionFromCookie(win) {
|
260
|
-
win = win || window;
|
261
|
-
var serialized = getSerializedSelectionFromCookie(win.document.cookie);
|
262
|
-
if (serialized) {
|
263
|
-
deserializeSelection(serialized, win.doc);
|
264
|
-
}
|
265
|
-
}
|
266
|
-
|
267
|
-
function saveSelectionCookie(win, props) {
|
268
|
-
win = win || window;
|
269
|
-
props = (typeof props == "object") ? props : {};
|
270
|
-
var expires = props.expires ? ";expires=" + props.expires.toUTCString() : "";
|
271
|
-
var path = props.path ? ";path=" + props.path : "";
|
272
|
-
var domain = props.domain ? ";domain=" + props.domain : "";
|
273
|
-
var secure = props.secure ? ";secure" : "";
|
274
|
-
var serialized = serializeSelection(api.getSelection(win));
|
275
|
-
win.document.cookie = encodeURIComponent(cookieName) + "=" + encodeURIComponent(serialized) + expires + path + domain + secure;
|
276
|
-
}
|
277
|
-
|
278
|
-
api.serializePosition = serializePosition;
|
279
|
-
api.deserializePosition = deserializePosition;
|
280
|
-
|
281
|
-
api.serializeRange = serializeRange;
|
282
|
-
api.deserializeRange = deserializeRange;
|
283
|
-
api.canDeserializeRange = canDeserializeRange;
|
284
|
-
|
285
|
-
api.serializeSelection = serializeSelection;
|
286
|
-
api.deserializeSelection = deserializeSelection;
|
287
|
-
api.canDeserializeSelection = canDeserializeSelection;
|
288
|
-
|
289
|
-
api.restoreSelectionFromCookie = restoreSelectionFromCookie;
|
290
|
-
api.saveSelectionCookie = saveSelectionCookie;
|
291
|
-
|
292
|
-
api.getElementChecksum = getElementChecksum;
|
293
|
-
api.nodeToInfoString = nodeToInfoString;
|
294
|
-
});
|
16
|
+
rangy.createModule("Serializer",["WrappedSelection"],function(a,b){function f(a){return a.replace(/</g,"<").replace(/>/g,">")}function g(a,b){b=b||[];var c=a.nodeType,d=a.childNodes,e=d.length,h=[c,a.nodeName,e].join(":"),i="",j="";switch(c){case 3:i=f(a.nodeValue);break;case 8:i="<!--"+f(a.nodeValue)+"-->";break;default:i="<"+h+">",j="</>"}i&&b.push(i);for(var k=0;k<e;++k)g(d[k],b);return j&&b.push(j),b}function h(a){var b=g(a).join("");return d(b).toString(16)}function i(a,b,c){var d=[],f=a;c=c||e.getDocument(a).documentElement;while(f&&f!=c)d.push(e.getNodeIndex(f,!0)),f=f.parentNode;return d.join("/")+":"+b}function j(a,c,d){c||(c=(d||document).documentElement);var f=a.split(":"),g=c,h=f[0]?f[0].split("/"):[],i=h.length,j;while(i--){j=parseInt(h[i],10);if(!(j<g.childNodes.length))throw b.createError("deserializePosition() failed: node "+e.inspectNode(g)+" has no child with index "+j+", "+i);g=g.childNodes[j]}return new e.DomPosition(g,parseInt(f[1],10))}function k(c,d,f){f=f||a.DomRange.getRangeDocument(c).documentElement;if(!e.isOrIsAncestorOf(f,c.commonAncestorContainer))throw b.createError("serializeRange(): range "+c.inspect()+" is not wholly contained within specified root node "+e.inspectNode(f));var g=i(c.startContainer,c.startOffset,f)+","+i(c.endContainer,c.endOffset,f);return d||(g+="{"+h(f)+"}"),g}function l(c,d,f){d?f=f||e.getDocument(d):(f=f||document,d=f.documentElement);var g=/^([^,]+),([^,\{]+)(\{([^}]+)\})?$/.exec(c),i=g[4],k=h(d);if(i&&i!==h(d))throw b.createError("deserializeRange(): checksums of serialized range root node ("+i+") and target root node ("+k+") do not match");var l=j(g[1],d,f),m=j(g[2],d,f),n=a.createRange(f);return n.setStartAndEnd(l.node,l.offset,m.node,m.offset),n}function m(a,b,c){b||(b=(c||document).documentElement);var d=/^([^,]+),([^,]+)(\{([^}]+)\})?$/.exec(a),e=d[3];return!e||e===h(b)}function n(b,c,d){b=a.getSelection(b);var e=b.getAllRanges(),f=[];for(var g=0,h=e.length;g<h;++g)f[g]=k(e[g],c,d);return f.join("|")}function o(b,c,d){c?d=d||e.getWindow(c):(d=d||window,c=d.document.documentElement);var f=b.split("|"),g=a.getSelection(d),h=[];for(var i=0,j=f.length;i<j;++i)h[i]=l(f[i],c,d.document);return g.setRanges(h),g}function p(a,b,c){var d;b?d=c?c.document:e.getDocument(b):(c=c||window,b=c.document.documentElement);var f=a.split("|");for(var g=0,h=f.length;g<h;++g)if(!m(f[g],b,d))return!1;return!0}function r(a){var b=a.split(/[;,]/);for(var c=0,d=b.length,e,f;c<d;++c){e=b[c].split("=");if(e[0].replace(/^\s+/,"")==q){f=e[1];if(f)return decodeURIComponent(f.replace(/\s+$/,""))}}return null}function s(a){a=a||window;var b=r(a.document.cookie);b&&o(b,a.doc)}function t(b,c){b=b||window,c=typeof c=="object"?c:{};var d=c.expires?";expires="+c.expires.toUTCString():"",e=c.path?";path="+c.path:"",f=c.domain?";domain="+c.domain:"",g=c.secure?";secure":"",h=n(a.getSelection(b));b.document.cookie=encodeURIComponent(q)+"="+encodeURIComponent(h)+d+e+f+g}var c="undefined";(typeof encodeURIComponent==c||typeof decodeURIComponent==c)&&b.fail("Global object is missing encodeURIComponent and/or decodeURIComponent method");var d=function(){function a(a){var b=[];for(var c=0,d=a.length,e;c<d;++c)e=a.charCodeAt(c),e<128?b.push(e):e<2048?b.push(e>>6|192,e&63|128):b.push(e>>12|224,e>>6&63|128,e&63|128);return b}function c(){var a=[];for(var b=0,c,d;b<256;++b){d=b,c=8;while(c--)(d&1)==1?d=d>>>1^3988292384:d>>>=1;a[b]=d>>>0}return a}function d(){return b||(b=c()),b}var b=null;return function(b){var c=a(b),e=-1,f=d();for(var g=0,h=c.length,i;g<h;++g)i=(e^c[g])&255,e=e>>>8^f[i];return(e^-1)>>>0}}(),e=a.dom,q="rangySerializedSelection";a.serializePosition=i,a.deserializePosition=j,a.serializeRange=k,a.deserializeRange=l,a.canDeserializeRange=m,a.serializeSelection=n,a.deserializeSelection=o,a.canDeserializeSelection=p,a.restoreSelectionFromCookie=s,a.saveSelectionCookie=t,a.getElementChecksum=h,a.nodeToInfoString=g})
|