Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/dom/browserrange/abstractrange.js
2868 views
1
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Definition of the browser range interface.
17
*
18
* DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead.
19
*
20
* @author [email protected] (Robby Walker)
21
*/
22
23
24
goog.provide('goog.dom.browserrange.AbstractRange');
25
26
goog.require('goog.array');
27
goog.require('goog.asserts');
28
goog.require('goog.dom');
29
goog.require('goog.dom.NodeType');
30
goog.require('goog.dom.RangeEndpoint');
31
goog.require('goog.dom.TagName');
32
goog.require('goog.dom.TextRangeIterator');
33
goog.require('goog.iter');
34
goog.require('goog.math.Coordinate');
35
goog.require('goog.string');
36
goog.require('goog.string.StringBuffer');
37
goog.require('goog.userAgent');
38
39
40
41
/**
42
* The constructor for abstract ranges. Don't call this from subclasses.
43
* @constructor
44
*/
45
goog.dom.browserrange.AbstractRange = function() {};
46
47
48
/**
49
* @return {goog.dom.browserrange.AbstractRange} A clone of this range.
50
*/
51
goog.dom.browserrange.AbstractRange.prototype.clone = goog.abstractMethod;
52
53
54
/**
55
* Returns the browser native implementation of the range. Please refrain from
56
* using this function - if you find you need the range please add wrappers for
57
* the functionality you need rather than just using the native range.
58
* @return {Range|TextRange} The browser native range object.
59
*/
60
goog.dom.browserrange.AbstractRange.prototype.getBrowserRange =
61
goog.abstractMethod;
62
63
64
/**
65
* Returns the deepest node in the tree that contains the entire range.
66
* @return {Node} The deepest node that contains the entire range.
67
*/
68
goog.dom.browserrange.AbstractRange.prototype.getContainer =
69
goog.abstractMethod;
70
71
72
/**
73
* Returns the node the range starts in.
74
* @return {Node} The element or text node the range starts in.
75
*/
76
goog.dom.browserrange.AbstractRange.prototype.getStartNode =
77
goog.abstractMethod;
78
79
80
/**
81
* Returns the offset into the node the range starts in.
82
* @return {number} The offset into the node the range starts in. For text
83
* nodes, this is an offset into the node value. For elements, this is
84
* an offset into the childNodes array.
85
*/
86
goog.dom.browserrange.AbstractRange.prototype.getStartOffset =
87
goog.abstractMethod;
88
89
90
/**
91
* @return {goog.math.Coordinate} The coordinate of the selection start node
92
* and offset.
93
*/
94
goog.dom.browserrange.AbstractRange.prototype.getStartPosition = function() {
95
return this.getPosition_(true);
96
};
97
98
99
/**
100
* Returns the node the range ends in.
101
* @return {Node} The element or text node the range ends in.
102
*/
103
goog.dom.browserrange.AbstractRange.prototype.getEndNode = goog.abstractMethod;
104
105
106
/**
107
* Returns the offset into the node the range ends in.
108
* @return {number} The offset into the node the range ends in. For text
109
* nodes, this is an offset into the node value. For elements, this is
110
* an offset into the childNodes array.
111
*/
112
goog.dom.browserrange.AbstractRange.prototype.getEndOffset =
113
goog.abstractMethod;
114
115
116
/**
117
* @return {goog.math.Coordinate} The coordinate of the selection end node
118
* and offset.
119
*/
120
goog.dom.browserrange.AbstractRange.prototype.getEndPosition = function() {
121
return this.getPosition_(false);
122
};
123
124
125
/**
126
* @param {boolean} start Whether to get the position of the start or end.
127
* @return {goog.math.Coordinate} The coordinate of the selection point.
128
* @private
129
*/
130
goog.dom.browserrange.AbstractRange.prototype.getPosition_ = function(start) {
131
goog.asserts.assert(
132
this.range_.getClientRects,
133
'Getting selection coordinates is not supported.');
134
135
var rects = this.range_.getClientRects();
136
if (rects.length) {
137
var r = start ? rects[0] : goog.array.peek(rects);
138
return new goog.math.Coordinate(
139
start ? r.left : r.right, start ? r.top : r.bottom);
140
}
141
return null;
142
};
143
144
145
/**
146
* Compares one endpoint of this range with the endpoint of another browser
147
* native range object.
148
* @param {Range|TextRange} range The browser native range to compare against.
149
* @param {goog.dom.RangeEndpoint} thisEndpoint The endpoint of this range
150
* to compare with.
151
* @param {goog.dom.RangeEndpoint} otherEndpoint The endpoint of the other
152
* range to compare with.
153
* @return {number} 0 if the endpoints are equal, negative if this range
154
* endpoint comes before the other range endpoint, and positive otherwise.
155
*/
156
goog.dom.browserrange.AbstractRange.prototype.compareBrowserRangeEndpoints =
157
goog.abstractMethod;
158
159
160
/**
161
* Tests if this range contains the given range.
162
* @param {goog.dom.browserrange.AbstractRange} abstractRange The range to test.
163
* @param {boolean=} opt_allowPartial If not set or false, the range must be
164
* entirely contained in the selection for this function to return true.
165
* @return {boolean} Whether this range contains the given range.
166
*/
167
goog.dom.browserrange.AbstractRange.prototype.containsRange = function(
168
abstractRange, opt_allowPartial) {
169
// IE sometimes misreports the boundaries for collapsed ranges. So if the
170
// other range is collapsed, make sure the whole range is contained. This is
171
// logically equivalent, and works around IE's bug.
172
var checkPartial = opt_allowPartial && !abstractRange.isCollapsed();
173
174
var range = abstractRange.getBrowserRange();
175
var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END;
176
177
try {
178
if (checkPartial) {
179
// There are two ways to not overlap. Being before, and being after.
180
// Before is represented by this.end before range.start: comparison < 0.
181
// After is represented by this.start after range.end: comparison > 0.
182
// The below is the negation of not overlapping.
183
return this.compareBrowserRangeEndpoints(range, end, start) >= 0 &&
184
this.compareBrowserRangeEndpoints(range, start, end) <= 0;
185
186
} else {
187
// Return true if this range bounds the parameter range from both sides.
188
return this.compareBrowserRangeEndpoints(range, end, end) >= 0 &&
189
this.compareBrowserRangeEndpoints(range, start, start) <= 0;
190
}
191
} catch (e) {
192
if (!goog.userAgent.IE) {
193
throw e;
194
}
195
// IE sometimes throws exceptions when one range is invalid, i.e. points
196
// to a node that has been removed from the document. Return false in this
197
// case.
198
return false;
199
}
200
};
201
202
203
/**
204
* Tests if this range contains the given node.
205
* @param {Node} node The node to test.
206
* @param {boolean=} opt_allowPartial If not set or false, the node must be
207
* entirely contained in the selection for this function to return true.
208
* @return {boolean} Whether this range contains the given node.
209
* @suppress {missingRequire} Cannot depend on goog.dom.browserrange because it
210
* creates a circular dependency.
211
*/
212
goog.dom.browserrange.AbstractRange.prototype.containsNode = function(
213
node, opt_allowPartial) {
214
/** @suppress {missingRequire} Circular dep with browserrange */
215
return this.containsRange(
216
goog.dom.browserrange.createRangeFromNodeContents(node),
217
opt_allowPartial);
218
};
219
220
221
/**
222
* Tests if the selection is collapsed - i.e. is just a caret.
223
* @return {boolean} Whether the range is collapsed.
224
*/
225
goog.dom.browserrange.AbstractRange.prototype.isCollapsed = goog.abstractMethod;
226
227
228
/**
229
* @return {string} The text content of the range.
230
*/
231
goog.dom.browserrange.AbstractRange.prototype.getText = goog.abstractMethod;
232
233
234
/**
235
* Returns the HTML fragment this range selects. This is slow on all browsers.
236
* @return {string} HTML fragment of the range, does not include context
237
* containing elements.
238
*/
239
goog.dom.browserrange.AbstractRange.prototype.getHtmlFragment = function() {
240
var output = new goog.string.StringBuffer();
241
goog.iter.forEach(this, function(node, ignore, it) {
242
if (node.nodeType == goog.dom.NodeType.TEXT) {
243
output.append(
244
goog.string.htmlEscape(
245
node.nodeValue.substring(
246
it.getStartTextOffset(), it.getEndTextOffset())));
247
} else if (node.nodeType == goog.dom.NodeType.ELEMENT) {
248
if (it.isEndTag()) {
249
if (goog.dom.canHaveChildren(node)) {
250
output.append('</' + node.tagName + '>');
251
}
252
} else {
253
var shallow = node.cloneNode(false);
254
var html = goog.dom.getOuterHtml(shallow);
255
if (goog.userAgent.IE && node.tagName == goog.dom.TagName.LI) {
256
// For an LI, IE just returns "<li>" with no closing tag
257
output.append(html);
258
} else {
259
var index = html.lastIndexOf('<');
260
output.append(index ? html.substr(0, index) : html);
261
}
262
}
263
}
264
}, this);
265
266
return output.toString();
267
};
268
269
270
/**
271
* Returns valid HTML for this range. This is fast on IE, and semi-fast on
272
* other browsers.
273
* @return {string} Valid HTML of the range, including context containing
274
* elements.
275
*/
276
goog.dom.browserrange.AbstractRange.prototype.getValidHtml =
277
goog.abstractMethod;
278
279
280
/**
281
* Returns a RangeIterator over the contents of the range. Regardless of the
282
* direction of the range, the iterator will move in document order.
283
* @param {boolean=} opt_keys Unused for this iterator.
284
* @return {!goog.dom.RangeIterator} An iterator over tags in the range.
285
*/
286
goog.dom.browserrange.AbstractRange.prototype.__iterator__ = function(
287
opt_keys) {
288
return new goog.dom.TextRangeIterator(
289
this.getStartNode(), this.getStartOffset(), this.getEndNode(),
290
this.getEndOffset());
291
};
292
293
294
// SELECTION MODIFICATION
295
296
297
/**
298
* Set this range as the selection in its window.
299
* @param {boolean=} opt_reverse Whether to select the range in reverse,
300
* if possible.
301
*/
302
goog.dom.browserrange.AbstractRange.prototype.select = goog.abstractMethod;
303
304
305
/**
306
* Removes the contents of the range from the document. As a side effect, the
307
* selection will be collapsed. The behavior of content removal is normalized
308
* across browsers. For instance, IE sometimes creates extra text nodes that
309
* a W3C browser does not. That behavior is corrected for.
310
*/
311
goog.dom.browserrange.AbstractRange.prototype.removeContents =
312
goog.abstractMethod;
313
314
315
/**
316
* Surrounds the text range with the specified element (on Mozilla) or with a
317
* clone of the specified element (on IE). Returns a reference to the
318
* surrounding element if the operation was successful; returns null if the
319
* operation failed.
320
* @param {Element} element The element with which the selection is to be
321
* surrounded.
322
* @return {Element} The surrounding element (same as the argument on Mozilla,
323
* but not on IE), or null if unsuccessful.
324
*/
325
goog.dom.browserrange.AbstractRange.prototype.surroundContents =
326
goog.abstractMethod;
327
328
329
/**
330
* Inserts a node before (or after) the range. The range may be disrupted
331
* beyond recovery because of the way this splits nodes.
332
* @param {Node} node The node to insert.
333
* @param {boolean} before True to insert before, false to insert after.
334
* @return {Node} The node added to the document. This may be different
335
* than the node parameter because on IE we have to clone it.
336
*/
337
goog.dom.browserrange.AbstractRange.prototype.insertNode = goog.abstractMethod;
338
339
340
/**
341
* Surrounds this range with the two given nodes. The range may be disrupted
342
* beyond recovery because of the way this splits nodes.
343
* @param {Element} startNode The node to insert at the start.
344
* @param {Element} endNode The node to insert at the end.
345
*/
346
goog.dom.browserrange.AbstractRange.prototype.surroundWithNodes =
347
goog.abstractMethod;
348
349
350
/**
351
* Collapses the range to one of its boundary points.
352
* @param {boolean} toStart Whether to collapse to the start of the range.
353
*/
354
goog.dom.browserrange.AbstractRange.prototype.collapse = goog.abstractMethod;
355
356