rangy-rails 1.3alpha.804.0 → 1.3.1.pre.dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -3
- data/lib/rangy-rails/version.rb +1 -1
- data/vendor/assets/javascripts/rangy-core.js +3157 -3050
- data/vendor/assets/javascripts/rangy-cssclassapplier.js +908 -790
- data/vendor/assets/javascripts/rangy-highlighter.js +550 -429
- data/vendor/assets/javascripts/rangy-selectionsaverestore.js +199 -182
- data/vendor/assets/javascripts/rangy-serializer.js +255 -236
- data/vendor/assets/javascripts/rangy-textrange.js +1565 -1547
- metadata +3 -5
- data/vendor/assets/javascripts/rangy-position.js +0 -524
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rangy-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1.pre.dev
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mario Zigliotto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
A simple Rails asset pipeline wrapper
|
@@ -31,7 +31,6 @@ files:
|
|
31
31
|
- vendor/assets/javascripts/rangy-core.js
|
32
32
|
- vendor/assets/javascripts/rangy-cssclassapplier.js
|
33
33
|
- vendor/assets/javascripts/rangy-highlighter.js
|
34
|
-
- vendor/assets/javascripts/rangy-position.js
|
35
34
|
- vendor/assets/javascripts/rangy-selectionsaverestore.js
|
36
35
|
- vendor/assets/javascripts/rangy-serializer.js
|
37
36
|
- vendor/assets/javascripts/rangy-textrange.js
|
@@ -54,9 +53,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
53
|
version: 1.3.1
|
55
54
|
requirements: []
|
56
55
|
rubyforge_project:
|
57
|
-
rubygems_version: 2.
|
56
|
+
rubygems_version: 2.4.8
|
58
57
|
signing_key:
|
59
58
|
specification_version: 4
|
60
59
|
summary: Rails asset pipeline wrapper for the Rangy library
|
61
60
|
test_files: []
|
62
|
-
has_rdoc:
|
@@ -1,524 +0,0 @@
|
|
1
|
-
rangy.createModule("Position", ["WrappedSelection"], function(api, module) {
|
2
|
-
//var log = log4javascript.getLogger("rangy.position");
|
3
|
-
|
4
|
-
var NUMBER = "number", UNDEF = "undefined";
|
5
|
-
var WrappedRange = api.WrappedRange;
|
6
|
-
var WrappedTextRange = api.WrappedTextRange;
|
7
|
-
var dom = api.dom, util = api.util, DomPosition = dom.DomPosition;
|
8
|
-
|
9
|
-
// Feature detection
|
10
|
-
|
11
|
-
//var caretPositionFromPointSupported = (typeof document.caretPositionFromPoint != UNDEF);
|
12
|
-
|
13
|
-
// Since Rangy can deal with multiple documents which could be in different modes, we have to do the checks every
|
14
|
-
// time, unless we cache a getScrollPosition function in each document. This would necessarily pollute the
|
15
|
-
// document's global namespace, which I'm choosing to view as a greater evil than a slight performance hit.
|
16
|
-
function getScrollPosition(win) {
|
17
|
-
var x = 0, y = 0;
|
18
|
-
if (typeof win.pageXOffset == NUMBER && typeof win.pageYOffset == NUMBER) {
|
19
|
-
x = win.pageXOffset;
|
20
|
-
y = win.pageYOffset;
|
21
|
-
} else {
|
22
|
-
var doc = win.document;
|
23
|
-
var docEl = doc.documentElement;
|
24
|
-
var compatMode = doc.compatMode;
|
25
|
-
var scrollEl = (typeof compatMode == "string" && compatMode.indexOf("CSS") >= 0 && docEl)
|
26
|
-
? docEl : dom.getBody(doc);
|
27
|
-
|
28
|
-
if (scrollEl && typeof scrollEl.scrollLeft == NUMBER && typeof scrollEl.scrollTop == NUMBER) {
|
29
|
-
try {
|
30
|
-
x = scrollEl.scrollLeft;
|
31
|
-
y = scrollEl.scrollTop;
|
32
|
-
} catch (ex) {}
|
33
|
-
}
|
34
|
-
}
|
35
|
-
return { x: x, y: y };
|
36
|
-
}
|
37
|
-
|
38
|
-
function getAncestorElement(node, tagName) {
|
39
|
-
tagName = tagName.toLowerCase();
|
40
|
-
while (node) {
|
41
|
-
if (node.nodeType == 1 && node.tagName.toLowerCase() == tagName) {
|
42
|
-
return node;
|
43
|
-
}
|
44
|
-
node = node.parentNode;
|
45
|
-
}
|
46
|
-
return null;
|
47
|
-
}
|
48
|
-
|
49
|
-
function Rect(top, right, bottom, left) {
|
50
|
-
this.top = top;
|
51
|
-
this.right = right;
|
52
|
-
this.bottom = bottom;
|
53
|
-
this.left = left;
|
54
|
-
this.width = right - left;
|
55
|
-
this.height = bottom - top;
|
56
|
-
}
|
57
|
-
|
58
|
-
function createRelativeRect(rect, dx, dy) {
|
59
|
-
return new Rect(rect.top + dy, rect.right + dx, rect.bottom + dy, rect.left + dx);
|
60
|
-
}
|
61
|
-
|
62
|
-
function adjustClientRect(rect, doc) {
|
63
|
-
// Older IEs have an issue with a two pixel margin on the body element
|
64
|
-
var dx = 0, dy = 0;
|
65
|
-
var docEl = doc.documentElement, body = dom.getBody(doc);
|
66
|
-
var container = (docEl.clientWidth === 0 && typeof body.clientTop == NUMBER) ? body : docEl;
|
67
|
-
var clientLeft = container.clientLeft, clientTop = container.clientTop;
|
68
|
-
if (clientLeft) {
|
69
|
-
dx = -clientLeft;
|
70
|
-
}
|
71
|
-
if (clientTop) {
|
72
|
-
dy = -clientTop;
|
73
|
-
}
|
74
|
-
return createRelativeRect(rect, dx, dy);
|
75
|
-
}
|
76
|
-
|
77
|
-
function mergeRects(rects) {
|
78
|
-
var tops = [], bottoms = [], lefts = [], rights = [];
|
79
|
-
for (var i = 0, len = rects.length, rect; i < len; ++i) {
|
80
|
-
rect = rects[i];
|
81
|
-
if (rect) {
|
82
|
-
tops.push(rect.top);
|
83
|
-
bottoms.push(rect.bottom);
|
84
|
-
lefts.push(rect.left);
|
85
|
-
rights.push(rect.right);
|
86
|
-
}
|
87
|
-
}
|
88
|
-
return new Rect(
|
89
|
-
Math.min.apply(Math, tops),
|
90
|
-
Math.max.apply(Math, rights),
|
91
|
-
Math.max.apply(Math, bottoms),
|
92
|
-
Math.min.apply(Math, lefts)
|
93
|
-
);
|
94
|
-
}
|
95
|
-
|
96
|
-
function getTextRangePosition(doc, x, y) {
|
97
|
-
var textRange = dom.getBody(doc).createTextRange();
|
98
|
-
textRange.moveToPoint(x, y);
|
99
|
-
var range = new api.WrappedTextRange(textRange);
|
100
|
-
return new DomPosition(range.startContainer, range.startOffset);
|
101
|
-
}
|
102
|
-
|
103
|
-
function caretPositionFromPoint(doc, x, y) {
|
104
|
-
var pos = doc.caretPositionFromPoint(x, y);
|
105
|
-
return new DomPosition(pos.offsetNode, pos.offset);
|
106
|
-
}
|
107
|
-
|
108
|
-
function caretRangeFromPoint(doc, x, y) {
|
109
|
-
var range = doc.caretRangeFromPoint(x, y);
|
110
|
-
return new DomPosition(range.startContainer, range.startOffset);
|
111
|
-
}
|
112
|
-
|
113
|
-
function getLastRangeRect(range) {
|
114
|
-
var rects = (range.nativeRange || range).getClientRects();
|
115
|
-
return (rects.length > 0) ? rects[rects.length - 1] : null;
|
116
|
-
}
|
117
|
-
|
118
|
-
function pointIsInOrAboveRect(x, y, rect) {
|
119
|
-
console.log("pointIsInOrAboveRect", x, y, Math.floor(rect.top), Math.floor(rect.right), Math.floor(rect.bottom), Math.floor(rect.left))
|
120
|
-
return y < rect.bottom && x >= rect.left && x <= rect.right;
|
121
|
-
}
|
122
|
-
|
123
|
-
function positionFromPoint(doc, x, y, favourPrecedingPosition) {
|
124
|
-
var el = doc.elementFromPoint(x, y);
|
125
|
-
|
126
|
-
console.log("elementFromPoint is ", el);
|
127
|
-
|
128
|
-
var range = api.createRange(doc);
|
129
|
-
range.selectNodeContents(el);
|
130
|
-
range.collapse(true);
|
131
|
-
|
132
|
-
var node = el.firstChild, offset, rect, textLen;
|
133
|
-
|
134
|
-
if (!node) {
|
135
|
-
node = el.parentNode;
|
136
|
-
offset = dom.getNodeIndex(el);
|
137
|
-
if (!favourPrecedingPosition) {
|
138
|
-
++offset;
|
139
|
-
}
|
140
|
-
} else {
|
141
|
-
// Search through the text node children of el
|
142
|
-
main: while (node) {
|
143
|
-
console.log(node);
|
144
|
-
if (node.nodeType == 3) {
|
145
|
-
// Go through the text node character by character
|
146
|
-
for (offset = 0, textLen = node.length; offset <= textLen; ++offset) {
|
147
|
-
range.setEnd(node, offset);
|
148
|
-
rect = getLastRangeRect(range);
|
149
|
-
if (rect && pointIsInOrAboveRect(x, y, rect)) {
|
150
|
-
// We've gone past the point. Now we check which side (left or right) of the character the point is nearer to
|
151
|
-
if (rect.right - x > x - rect.left) {
|
152
|
-
--offset;
|
153
|
-
}
|
154
|
-
break main;
|
155
|
-
}
|
156
|
-
}
|
157
|
-
} else {
|
158
|
-
// Handle elements
|
159
|
-
range.setEndAfter(node);
|
160
|
-
rect = getLastRangeRect(range);
|
161
|
-
if (rect && pointIsInOrAboveRect(x, y, rect)) {
|
162
|
-
offset = dom.getNodeIndex(node);
|
163
|
-
node = el.parentNode;
|
164
|
-
if (!favourPrecedingPosition) {
|
165
|
-
++offset;
|
166
|
-
}
|
167
|
-
break;
|
168
|
-
}
|
169
|
-
}
|
170
|
-
|
171
|
-
node = node.nextSibling;
|
172
|
-
}
|
173
|
-
if (!node) {
|
174
|
-
node = el;
|
175
|
-
offset = el.childNodes.length;
|
176
|
-
}
|
177
|
-
}
|
178
|
-
|
179
|
-
return new DomPosition(node, offset);
|
180
|
-
}
|
181
|
-
|
182
|
-
function createCaretPositionFromPointGetter(doc) {
|
183
|
-
if (api.features.implementsTextRange) {
|
184
|
-
return getTextRangePosition;
|
185
|
-
} else if (typeof doc.caretPositionFromPoint != UNDEF) {
|
186
|
-
return caretPositionFromPoint;
|
187
|
-
} else if (typeof doc.caretRangeFromPoint != UNDEF) {
|
188
|
-
return caretRangeFromPoint;
|
189
|
-
} else if (typeof doc.elementFromPoint != UNDEF && rangeSupportsGetClientRects) {
|
190
|
-
return positionFromPoint;
|
191
|
-
} else {
|
192
|
-
throw module.createError("createCaretPositionFromPointGetter(): Browser does not provide a recognised method to create a selection from pixel coordinates");
|
193
|
-
}
|
194
|
-
}
|
195
|
-
|
196
|
-
function createRangeFromPoints(startX, startY, endX, endY, doc) {
|
197
|
-
doc = dom.getContentDocument(doc, module, "createRangeFromPoints");
|
198
|
-
var positionFinder = createCaretPositionFromPointGetter(doc);
|
199
|
-
var startPos = positionFinder(doc, startX, startY, false);
|
200
|
-
var endPos = positionFinder(doc, endX, endY, true);
|
201
|
-
console.log(startPos.node, startPos.offset, endPos.node, endPos.offset);
|
202
|
-
var range = api.createRange(doc);
|
203
|
-
range.setStartAndEnd(startPos.node, startPos.offset, endPos.node, endPos.offset);
|
204
|
-
return range;
|
205
|
-
}
|
206
|
-
|
207
|
-
function moveSelectionToPoints(anchorX, anchorY, focusX, focusY, doc) {
|
208
|
-
var startX, startY, endX, endY;
|
209
|
-
|
210
|
-
// Detect backward selection for coordinates and flip start and end coordinates if necessary
|
211
|
-
var backward = focusY < anchorY || (anchorY == focusY && focusX < anchorX);
|
212
|
-
|
213
|
-
if (backward) {
|
214
|
-
startX = focusX;
|
215
|
-
startY = focusY;
|
216
|
-
endX = anchorX;
|
217
|
-
endY = anchorY;
|
218
|
-
} else {
|
219
|
-
startX = anchorX;
|
220
|
-
startY = anchorY;
|
221
|
-
endX = focusX;
|
222
|
-
endY = focusY;
|
223
|
-
}
|
224
|
-
|
225
|
-
var sel = rangy.getSelection(doc);
|
226
|
-
var range = createRangeFromPoints(startX, startY, endX, endY, doc);
|
227
|
-
sel.setSingleRange(range);
|
228
|
-
return sel;
|
229
|
-
}
|
230
|
-
|
231
|
-
// Test that <span> elements support getBoundingClientRect
|
232
|
-
var span = document.createElement("span");
|
233
|
-
var elementSupportsGetBoundingClientRect = util.isHostMethod(span, "getBoundingClientRect");
|
234
|
-
span = null;
|
235
|
-
|
236
|
-
// Test for getBoundingClientRect support in Range
|
237
|
-
var rangeSupportsGetClientRects = false, rangeSupportsGetBoundingClientRect = false;
|
238
|
-
if (api.features.implementsDomRange) {
|
239
|
-
var testRange = api.createNativeRange();
|
240
|
-
rangeSupportsGetClientRects = util.isHostMethod(testRange, "getClientRects");
|
241
|
-
rangeSupportsGetBoundingClientRect = util.isHostMethod(testRange, "getBoundingClientRect");
|
242
|
-
testRange.detach();
|
243
|
-
}
|
244
|
-
|
245
|
-
util.extend(api.features, {
|
246
|
-
rangeSupportsGetBoundingClientRect: rangeSupportsGetBoundingClientRect,
|
247
|
-
rangeSupportsGetClientRects: rangeSupportsGetClientRects,
|
248
|
-
elementSupportsGetBoundingClientRect: elementSupportsGetBoundingClientRect
|
249
|
-
});
|
250
|
-
|
251
|
-
var createClientBoundaryPosGetter = function(isStart) {
|
252
|
-
return function() {
|
253
|
-
var boundaryRange = this.cloneRange();
|
254
|
-
boundaryRange.collapse(isStart);
|
255
|
-
var rect = boundaryRange.getBoundingClientRect();
|
256
|
-
return {
|
257
|
-
x: rect[isStart ? "left" : "right"],
|
258
|
-
y: rect[isStart ? "top" : "bottom"]
|
259
|
-
};
|
260
|
-
};
|
261
|
-
};
|
262
|
-
|
263
|
-
var rangeProto = api.rangePrototype;
|
264
|
-
|
265
|
-
if (api.features.implementsTextRange && elementSupportsGetBoundingClientRect) {
|
266
|
-
rangeProto.getBoundingClientRect = function() {
|
267
|
-
// We need a TextRange
|
268
|
-
var textRange = WrappedTextRange.rangeToTextRange(this);
|
269
|
-
|
270
|
-
// Work around table problems (table cell bounding rects seem not to count if TextRange spans cells)
|
271
|
-
var cells = this.getNodes([1], function(el) {
|
272
|
-
return /^t[dh]$/i.test(el.tagName);
|
273
|
-
});
|
274
|
-
|
275
|
-
// Merge rects for each cell selected by the range into overall rect
|
276
|
-
var rect, rects = [];
|
277
|
-
if (cells.length > 0) {
|
278
|
-
var lastTable = getAncestorElement(this.startContainer, "table");
|
279
|
-
|
280
|
-
for (var i = 0, cell, tempTextRange, table, subRange, subRect; cell = cells[i]; ++i) {
|
281
|
-
// Handle non-table sections of the range
|
282
|
-
table = getAncestorElement(cell, "table");
|
283
|
-
if (!lastTable || table != lastTable) {
|
284
|
-
// There is a section of the range prior to the current table, or lying between tables.
|
285
|
-
// Merge in its rect
|
286
|
-
subRange = this.cloneRange();
|
287
|
-
if (lastTable) {
|
288
|
-
subRange.setStartAfter(lastTable);
|
289
|
-
}
|
290
|
-
subRange.setEndBefore(table);
|
291
|
-
rects.push(WrappedTextRange.rangeToTextRange(subRange).getBoundingClientRect());
|
292
|
-
}
|
293
|
-
|
294
|
-
if (this.containsNode(cell)) {
|
295
|
-
rects.push(cell.getBoundingClientRect());
|
296
|
-
} else {
|
297
|
-
tempTextRange = textRange.duplicate();
|
298
|
-
tempTextRange.moveToElementText(cell);
|
299
|
-
if (tempTextRange.compareEndPoints("StartToStart", textRange) == -1) {
|
300
|
-
tempTextRange.setEndPoint("StartToStart", textRange);
|
301
|
-
} else if (tempTextRange.compareEndPoints("EndToEnd", textRange) == 1) {
|
302
|
-
tempTextRange.setEndPoint("EndToEnd", textRange);
|
303
|
-
}
|
304
|
-
rects.push(tempTextRange.getBoundingClientRect());
|
305
|
-
}
|
306
|
-
lastTable = table;
|
307
|
-
}
|
308
|
-
|
309
|
-
// Merge in the rect for any content lying after the final table
|
310
|
-
var endTable = getAncestorElement(this.endContainer, "table");
|
311
|
-
if (!endTable && lastTable) {
|
312
|
-
subRange = this.cloneRange();
|
313
|
-
subRange.setStartAfter(lastTable);
|
314
|
-
rects.push(WrappedTextRange.rangeToTextRange(subRange).getBoundingClientRect());
|
315
|
-
}
|
316
|
-
rect = mergeRects(rects);
|
317
|
-
} else {
|
318
|
-
rect = textRange.getBoundingClientRect();
|
319
|
-
}
|
320
|
-
|
321
|
-
return adjustClientRect(rect, dom.getDocument(this.startContainer));
|
322
|
-
};
|
323
|
-
} else if (api.features.implementsDomRange) {
|
324
|
-
var createWrappedRange = function(range) {
|
325
|
-
return (range instanceof WrappedRange) ? range : new WrappedRange(range);
|
326
|
-
};
|
327
|
-
|
328
|
-
if (rangeSupportsGetBoundingClientRect) {
|
329
|
-
rangeProto.getBoundingClientRect = function() {
|
330
|
-
var nativeRange = createWrappedRange(this).nativeRange;
|
331
|
-
// Test for WebKit getBoundingClientRect bug (https://bugs.webkit.org/show_bug.cgi?id=65324)
|
332
|
-
var rect = nativeRange.getBoundingClientRect() || nativeRange.getClientRects()[0];
|
333
|
-
return adjustClientRect(rect, dom.getDocument(this.startContainer));
|
334
|
-
};
|
335
|
-
|
336
|
-
if (rangeSupportsGetClientRects) {
|
337
|
-
var getElementRectsForPosition = function(node, offset) {
|
338
|
-
var children = node.childNodes;
|
339
|
-
//if (offset < children.length)
|
340
|
-
};
|
341
|
-
|
342
|
-
createClientBoundaryPosGetter = function(isStart) {
|
343
|
-
return function() {
|
344
|
-
var rect, nativeRange = createWrappedRange(this).nativeRange;
|
345
|
-
var rects = nativeRange.getClientRects();
|
346
|
-
|
347
|
-
if (rects.length == 0 && elementSupportsGetBoundingClientRect) {
|
348
|
-
if (isStart) {
|
349
|
-
|
350
|
-
|
351
|
-
}
|
352
|
-
|
353
|
-
console.log(nativeRange, nativeRange.getClientRects(), nativeRange.getBoundingClientRect());
|
354
|
-
if (this.collapsed
|
355
|
-
&& this.startContainer.nodeType == 1
|
356
|
-
&& this.startOffset < this.startContainer.childNodes.length) {
|
357
|
-
var n = this.startContainer.childNodes[this.startOffset];
|
358
|
-
if (n.getClientRects) {
|
359
|
-
console.log(n, n.getClientRects(), this.startContainer.getClientRects())
|
360
|
-
}
|
361
|
-
|
362
|
-
}
|
363
|
-
}
|
364
|
-
|
365
|
-
if (rects.length > 0) {
|
366
|
-
if (isStart) {
|
367
|
-
rect = rects[0];
|
368
|
-
return { x: rect.left, y: rect.top };
|
369
|
-
} else {
|
370
|
-
rect = rects[rects.length - 1];
|
371
|
-
return { x: rect.right, y: rect.bottom };
|
372
|
-
}
|
373
|
-
} else {
|
374
|
-
throw module.createError("Cannot get position for range " + this.inspect());
|
375
|
-
}
|
376
|
-
};
|
377
|
-
}
|
378
|
-
}
|
379
|
-
} else {
|
380
|
-
var getElementBoundingClientRect = elementSupportsGetBoundingClientRect ?
|
381
|
-
function(el) {
|
382
|
-
return adjustClientRect(el.getBoundingClientRect(), dom.getDocument(el));
|
383
|
-
} :
|
384
|
-
|
385
|
-
// This implementation is very naive. There are many browser quirks that make it extremely
|
386
|
-
// difficult to get accurate element coordinates in all situations
|
387
|
-
function(el) {
|
388
|
-
var x = 0, y = 0, offsetEl = el, width = el.offsetWidth, height = el.offsetHeight;
|
389
|
-
while (offsetEl) {
|
390
|
-
x += offsetEl.offsetLeft;
|
391
|
-
y += offsetEl.offsetTop;
|
392
|
-
offsetEl = offsetEl.offsetParent;
|
393
|
-
}
|
394
|
-
|
395
|
-
return adjustClientRect(new Rect(y, x + width, y + height, x), dom.getDocument(el));
|
396
|
-
};
|
397
|
-
|
398
|
-
var getRectFromBoundaries = function(range) {
|
399
|
-
var rect;
|
400
|
-
range.splitBoundaries();
|
401
|
-
var span = document.createElement("span");
|
402
|
-
|
403
|
-
if (range.collapsed) {
|
404
|
-
range.insertNode(span);
|
405
|
-
rect = getElementBoundingClientRect(span);
|
406
|
-
span.parentNode.removeChild(span);
|
407
|
-
} else {
|
408
|
-
// TODO: This isn't right. I'm not sure it can be made right sensibly. Consider what to do.
|
409
|
-
// This doesn't consider all the line boxes it needs to consider.
|
410
|
-
var workingRange = range.cloneRange();
|
411
|
-
|
412
|
-
// Get the start rectangle
|
413
|
-
workingRange.collapse(true);
|
414
|
-
workingRange.insertNode(span);
|
415
|
-
var startRect = getElementBoundingClientRect(span);
|
416
|
-
span.parentNode.removeChild(span);
|
417
|
-
|
418
|
-
// Get the end rectangle
|
419
|
-
workingRange.collapseToPoint(range.endContainer, range.endOffset);
|
420
|
-
workingRange.insertNode(span);
|
421
|
-
var endRect = getElementBoundingClientRect(span);
|
422
|
-
span.parentNode.removeChild(span);
|
423
|
-
|
424
|
-
// Merge the start and end rects
|
425
|
-
var rects = [startRect, endRect];
|
426
|
-
|
427
|
-
// Merge in rectangles for all elements in the range
|
428
|
-
var elements = range.getNodes([1], function(el) {
|
429
|
-
return range.containsNode(el);
|
430
|
-
});
|
431
|
-
|
432
|
-
for (var i = 0, len = elements.length; i < len; ++i) {
|
433
|
-
rects.push(getElementBoundingClientRect(elements[i]));
|
434
|
-
}
|
435
|
-
rect = mergeRects(rects)
|
436
|
-
}
|
437
|
-
|
438
|
-
// Clean up
|
439
|
-
range.normalizeBoundaries();
|
440
|
-
return rect;
|
441
|
-
};
|
442
|
-
|
443
|
-
rangeProto.getBoundingClientRect = function(range) {
|
444
|
-
return getRectFromBoundaries(createWrappedRange(range));
|
445
|
-
};
|
446
|
-
}
|
447
|
-
|
448
|
-
function createDocumentBoundaryPosGetter(isStart) {
|
449
|
-
return function() {
|
450
|
-
var pos = this["get" + (isStart ? "Start" : "End") + "ClientPos"]();
|
451
|
-
var scrollPos = getScrollPosition( dom.getWindow(this.startContainer) );
|
452
|
-
return { x: pos.x + scrollPos.x, y: pos.y + scrollPos.y };
|
453
|
-
};
|
454
|
-
}
|
455
|
-
}
|
456
|
-
|
457
|
-
util.extend(rangeProto, {
|
458
|
-
getBoundingDocumentRect: function() {
|
459
|
-
var scrollPos = getScrollPosition( dom.getWindow(this.startContainer) );
|
460
|
-
return createRelativeRect(this.getBoundingClientRect(), scrollPos.x, scrollPos.y);
|
461
|
-
},
|
462
|
-
|
463
|
-
getStartClientPos: createClientBoundaryPosGetter(true),
|
464
|
-
getEndClientPos: createClientBoundaryPosGetter(false),
|
465
|
-
|
466
|
-
getStartDocumentPos: createDocumentBoundaryPosGetter(true),
|
467
|
-
getEndDocumentPos: createDocumentBoundaryPosGetter(false)
|
468
|
-
});
|
469
|
-
|
470
|
-
// Add Selection methods
|
471
|
-
function compareRanges(r1, r2) {
|
472
|
-
return r1.compareBoundaryPoints(r2.START_TO_START, r2);
|
473
|
-
}
|
474
|
-
|
475
|
-
function createSelectionRectGetter(isDocument) {
|
476
|
-
return function() {
|
477
|
-
var rangeMethodName = "getBounding" + (isDocument ? "Document" : "Client") + "Rect";
|
478
|
-
var rects = [];
|
479
|
-
for (var i = 0, rect = null, rangeRect; i < this.rangeCount; ++i) {
|
480
|
-
rects.push(this.getRangeAt(i)[rangeMethodName]());
|
481
|
-
}
|
482
|
-
return mergeRects(rects);
|
483
|
-
};
|
484
|
-
}
|
485
|
-
|
486
|
-
function createSelectionBoundaryPosGetter(isStart, isDocument) {
|
487
|
-
return function() {
|
488
|
-
if (this.rangeCount == 0) {
|
489
|
-
return null;
|
490
|
-
}
|
491
|
-
|
492
|
-
var posType = isDocument ? "Document" : "Client";
|
493
|
-
|
494
|
-
var ranges = this.getAllRanges();
|
495
|
-
if (ranges.length > 1) {
|
496
|
-
// Order the ranges by position within the DOM
|
497
|
-
ranges.sort(compareRanges);
|
498
|
-
}
|
499
|
-
|
500
|
-
return isStart ?
|
501
|
-
ranges[0]["getStart" + posType + "Pos"]() :
|
502
|
-
ranges[ranges.length - 1]["getEnd" + posType + "Pos"]();
|
503
|
-
};
|
504
|
-
}
|
505
|
-
|
506
|
-
util.extend(api.selectionPrototype, {
|
507
|
-
getBoundingClientRect: createSelectionRectGetter(false),
|
508
|
-
getBoundingDocumentRect: createSelectionRectGetter(true),
|
509
|
-
|
510
|
-
getStartClientPos: createSelectionBoundaryPosGetter(true, false),
|
511
|
-
getEndClientPos: createSelectionBoundaryPosGetter(false, false),
|
512
|
-
|
513
|
-
getStartDocumentPos: createSelectionBoundaryPosGetter(true, true),
|
514
|
-
getEndDocumentPos: createSelectionBoundaryPosGetter(false, true)
|
515
|
-
});
|
516
|
-
|
517
|
-
api.positionFromPoint = function(x, y, doc) {
|
518
|
-
doc = dom.getContentDocument(doc, module, "positionFromPoint");
|
519
|
-
return createCaretPositionFromPointGetter(doc)(doc, x, y);
|
520
|
-
};
|
521
|
-
|
522
|
-
api.createRangeFromPoints = createRangeFromPoints;
|
523
|
-
api.moveSelectionToPoints = moveSelectionToPoints;
|
524
|
-
});
|