diff options
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/dom/textrange.js')
-rw-r--r-- | contexts/data/lib/closure-library/closure/goog/dom/textrange.js | 614 |
1 files changed, 0 insertions, 614 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/dom/textrange.js b/contexts/data/lib/closure-library/closure/goog/dom/textrange.js deleted file mode 100644 index 1be6b57..0000000 --- a/contexts/data/lib/closure-library/closure/goog/dom/textrange.js +++ /dev/null @@ -1,614 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for working with text ranges in HTML documents. - * - * @author robbyw@google.com (Robby Walker) - * @author ojan@google.com (Ojan Vafai) - * @author jparent@google.com (Julie Parent) - */ - - -goog.provide('goog.dom.TextRange'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.AbstractRange'); -goog.require('goog.dom.RangeType'); -goog.require('goog.dom.SavedRange'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.TextRangeIterator'); -goog.require('goog.dom.browserrange'); -goog.require('goog.string'); -goog.require('goog.userAgent'); - - - -/** - * Create a new text selection with no properties. Do not use this constructor: - * use one of the goog.dom.Range.createFrom* methods instead. - * @constructor - * @extends {goog.dom.AbstractRange} - */ -goog.dom.TextRange = function() { -}; -goog.inherits(goog.dom.TextRange, goog.dom.AbstractRange); - - -/** - * Create a new range wrapper from the given browser range object. Do not use - * this method directly - please use goog.dom.Range.createFrom* instead. - * @param {Range|TextRange} range The browser range object. - * @param {boolean=} opt_isReversed Whether the focus node is before the anchor - * node. - * @return {goog.dom.TextRange} A range wrapper object. - */ -goog.dom.TextRange.createFromBrowserRange = function(range, opt_isReversed) { - return goog.dom.TextRange.createFromBrowserRangeWrapper_( - goog.dom.browserrange.createRange(range), opt_isReversed); -}; - - -/** - * Create a new range wrapper from the given browser range wrapper. - * @param {goog.dom.browserrange.AbstractRange} browserRange The browser range - * wrapper. - * @param {boolean=} opt_isReversed Whether the focus node is before the anchor - * node. - * @return {goog.dom.TextRange} A range wrapper object. - * @private - */ -goog.dom.TextRange.createFromBrowserRangeWrapper_ = function(browserRange, - opt_isReversed) { - var range = new goog.dom.TextRange(); - - // Initialize the range as a browser range wrapper type range. - range.browserRangeWrapper_ = browserRange; - range.isReversed_ = !!opt_isReversed; - - return range; -}; - - -/** - * Create a new range wrapper that selects the given node's text. Do not use - * this method directly - please use goog.dom.Range.createFrom* instead. - * @param {Node} node The node to select. - * @param {boolean=} opt_isReversed Whether the focus node is before the anchor - * node. - * @return {goog.dom.TextRange} A range wrapper object. - */ -goog.dom.TextRange.createFromNodeContents = function(node, opt_isReversed) { - return goog.dom.TextRange.createFromBrowserRangeWrapper_( - goog.dom.browserrange.createRangeFromNodeContents(node), - opt_isReversed); -}; - - -/** - * Create a new range wrapper that selects the area between the given nodes, - * accounting for the given offsets. Do not use this method directly - please - * use goog.dom.Range.createFrom* instead. - * @param {Node} anchorNode The node to start with. - * @param {number} anchorOffset The offset within the node to start. - * @param {Node} focusNode The node to end with. - * @param {number} focusOffset The offset within the node to end. - * @return {goog.dom.TextRange} A range wrapper object. - */ -goog.dom.TextRange.createFromNodes = function(anchorNode, anchorOffset, - focusNode, focusOffset) { - var range = new goog.dom.TextRange(); - range.isReversed_ = goog.dom.Range.isReversed(anchorNode, anchorOffset, - focusNode, focusOffset); - - // Avoid selecting BRs directly - if (anchorNode.tagName == 'BR') { - var parent = anchorNode.parentNode; - anchorOffset = goog.array.indexOf(parent.childNodes, anchorNode); - anchorNode = parent; - } - - if (focusNode.tagName == 'BR') { - var parent = focusNode.parentNode; - focusOffset = goog.array.indexOf(parent.childNodes, focusNode); - focusNode = parent; - } - - // Initialize the range as a W3C style range. - if (range.isReversed_) { - range.startNode_ = focusNode; - range.startOffset_ = focusOffset; - range.endNode_ = anchorNode; - range.endOffset_ = anchorOffset; - } else { - range.startNode_ = anchorNode; - range.startOffset_ = anchorOffset; - range.endNode_ = focusNode; - range.endOffset_ = focusOffset; - } - - return range; -}; - - -// Representation 1: a browser range wrapper. - - -/** - * The browser specific range wrapper. This can be null if one of the other - * representations of the range is specified. - * @type {goog.dom.browserrange.AbstractRange?} - * @private - */ -goog.dom.TextRange.prototype.browserRangeWrapper_ = null; - - -// Representation 2: two endpoints specified as nodes + offsets - - -/** - * The start node of the range. This can be null if one of the other - * representations of the range is specified. - * @type {Node} - * @private - */ -goog.dom.TextRange.prototype.startNode_ = null; - - -/** - * The start offset of the range. This can be null if one of the other - * representations of the range is specified. - * @type {?number} - * @private - */ -goog.dom.TextRange.prototype.startOffset_ = null; - - -/** - * The end node of the range. This can be null if one of the other - * representations of the range is specified. - * @type {Node} - * @private - */ -goog.dom.TextRange.prototype.endNode_ = null; - - -/** - * The end offset of the range. This can be null if one of the other - * representations of the range is specified. - * @type {?number} - * @private - */ -goog.dom.TextRange.prototype.endOffset_ = null; - - -/** - * Whether the focus node is before the anchor node. - * @type {boolean} - * @private - */ -goog.dom.TextRange.prototype.isReversed_ = false; - - -// Method implementations - - -/** - * @return {goog.dom.TextRange} A clone of this range. - * @override - */ -goog.dom.TextRange.prototype.clone = function() { - var range = new goog.dom.TextRange(); - range.browserRangeWrapper_ = this.browserRangeWrapper_; - range.startNode_ = this.startNode_; - range.startOffset_ = this.startOffset_; - range.endNode_ = this.endNode_; - range.endOffset_ = this.endOffset_; - range.isReversed_ = this.isReversed_; - - return range; -}; - - -/** @override */ -goog.dom.TextRange.prototype.getType = function() { - return goog.dom.RangeType.TEXT; -}; - - -/** @override */ -goog.dom.TextRange.prototype.getBrowserRangeObject = function() { - return this.getBrowserRangeWrapper_().getBrowserRange(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.setBrowserRangeObject = function(nativeRange) { - // Test if it's a control range by seeing if a control range only method - // exists. - if (goog.dom.AbstractRange.isNativeControlRange(nativeRange)) { - return false; - } - this.browserRangeWrapper_ = goog.dom.browserrange.createRange( - nativeRange); - this.clearCachedValues_(); - return true; -}; - - -/** - * Clear all cached values. - * @private - */ -goog.dom.TextRange.prototype.clearCachedValues_ = function() { - this.startNode_ = this.startOffset_ = this.endNode_ = this.endOffset_ = null; -}; - - -/** @override */ -goog.dom.TextRange.prototype.getTextRangeCount = function() { - return 1; -}; - - -/** @override */ -goog.dom.TextRange.prototype.getTextRange = function(i) { - return this; -}; - - -/** - * @return {goog.dom.browserrange.AbstractRange} The range wrapper object. - * @private - */ -goog.dom.TextRange.prototype.getBrowserRangeWrapper_ = function() { - return this.browserRangeWrapper_ || - (this.browserRangeWrapper_ = goog.dom.browserrange.createRangeFromNodes( - this.getStartNode(), this.getStartOffset(), - this.getEndNode(), this.getEndOffset())); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getContainer = function() { - return this.getBrowserRangeWrapper_().getContainer(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getStartNode = function() { - return this.startNode_ || - (this.startNode_ = this.getBrowserRangeWrapper_().getStartNode()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getStartOffset = function() { - return this.startOffset_ != null ? this.startOffset_ : - (this.startOffset_ = this.getBrowserRangeWrapper_().getStartOffset()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getEndNode = function() { - return this.endNode_ || - (this.endNode_ = this.getBrowserRangeWrapper_().getEndNode()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getEndOffset = function() { - return this.endOffset_ != null ? this.endOffset_ : - (this.endOffset_ = this.getBrowserRangeWrapper_().getEndOffset()); -}; - - -/** - * Moves a TextRange to the provided nodes and offsets. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the node to start. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the node to end. - * @param {boolean} isReversed Whether the range is reversed. - */ -goog.dom.TextRange.prototype.moveToNodes = function(startNode, startOffset, - endNode, endOffset, - isReversed) { - this.startNode_ = startNode; - this.startOffset_ = startOffset; - this.endNode_ = endNode; - this.endOffset_ = endOffset; - this.isReversed_ = isReversed; - this.browserRangeWrapper_ = null; -}; - - -/** @override */ -goog.dom.TextRange.prototype.isReversed = function() { - return this.isReversed_; -}; - - -/** @override */ -goog.dom.TextRange.prototype.containsRange = function(otherRange, - opt_allowPartial) { - var otherRangeType = otherRange.getType(); - if (otherRangeType == goog.dom.RangeType.TEXT) { - return this.getBrowserRangeWrapper_().containsRange( - otherRange.getBrowserRangeWrapper_(), opt_allowPartial); - } else if (otherRangeType == goog.dom.RangeType.CONTROL) { - var elements = otherRange.getElements(); - var fn = opt_allowPartial ? goog.array.some : goog.array.every; - return fn(elements, function(el) { - return this.containsNode(el, opt_allowPartial); - }, this); - } - return false; -}; - - -/** - * Tests if the given node is in a document. - * @param {Node} node The node to check. - * @return {boolean} Whether the given node is in the given document. - */ -goog.dom.TextRange.isAttachedNode = function(node) { - if (goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) { - var returnValue = false; - /** @preserveTry */ - try { - returnValue = node.parentNode; - } catch (e) { - // IE sometimes throws Invalid Argument errors when a node is detached. - // Note: trying to return a value from the above try block can cause IE - // to crash. It is necessary to use the local returnValue - } - return !!returnValue; - } else { - return goog.dom.contains(node.ownerDocument.body, node); - } -}; - - -/** @override */ -goog.dom.TextRange.prototype.isRangeInDocument = function() { - // Ensure any cached nodes are in the document. IE also allows ranges to - // become detached, so we check if the range is still in the document as - // well for IE. - return (!this.startNode_ || - goog.dom.TextRange.isAttachedNode(this.startNode_)) && - (!this.endNode_ || - goog.dom.TextRange.isAttachedNode(this.endNode_)) && - (!(goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) || - this.getBrowserRangeWrapper_().isRangeInDocument()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.isCollapsed = function() { - return this.getBrowserRangeWrapper_().isCollapsed(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getText = function() { - return this.getBrowserRangeWrapper_().getText(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getHtmlFragment = function() { - // TODO(robbyw): Generalize the code in browserrange so it is static and - // just takes an iterator. This would mean we don't always have to create a - // browser range. - return this.getBrowserRangeWrapper_().getHtmlFragment(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getValidHtml = function() { - return this.getBrowserRangeWrapper_().getValidHtml(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getPastableHtml = function() { - // TODO(robbyw): Get any attributes the table or tr has. - - var html = this.getValidHtml(); - - if (html.match(/^\s*<td\b/i)) { - // Match html starting with a TD. - html = '<table><tbody><tr>' + html + '</tr></tbody></table>'; - } else if (html.match(/^\s*<tr\b/i)) { - // Match html starting with a TR. - html = '<table><tbody>' + html + '</tbody></table>'; - } else if (html.match(/^\s*<tbody\b/i)) { - // Match html starting with a TBODY. - html = '<table>' + html + '</table>'; - } else if (html.match(/^\s*<li\b/i)) { - // Match html starting with an LI. - var container = this.getContainer(); - var tagType = goog.dom.TagName.UL; - while (container) { - if (container.tagName == goog.dom.TagName.OL) { - tagType = goog.dom.TagName.OL; - break; - } else if (container.tagName == goog.dom.TagName.UL) { - break; - } - container = container.parentNode; - } - html = goog.string.buildString('<', tagType, '>', html, '</', tagType, '>'); - } - - return html; -}; - - -/** - * Returns a TextRangeIterator over the contents of the range. Regardless of - * the direction of the range, the iterator will move in document order. - * @param {boolean=} opt_keys Unused for this iterator. - * @return {goog.dom.TextRangeIterator} An iterator over tags in the range. - * @override - */ -goog.dom.TextRange.prototype.__iterator__ = function(opt_keys) { - return new goog.dom.TextRangeIterator(this.getStartNode(), - this.getStartOffset(), this.getEndNode(), this.getEndOffset()); -}; - - -// RANGE ACTIONS - - -/** @override */ -goog.dom.TextRange.prototype.select = function() { - this.getBrowserRangeWrapper_().select(this.isReversed_); -}; - - -/** @override */ -goog.dom.TextRange.prototype.removeContents = function() { - this.getBrowserRangeWrapper_().removeContents(); - this.clearCachedValues_(); -}; - - -/** - * Surrounds the text range with the specified element (on Mozilla) or with a - * clone of the specified element (on IE). Returns a reference to the - * surrounding element if the operation was successful; returns null if the - * operation failed. - * @param {Element} element The element with which the selection is to be - * surrounded. - * @return {Element} The surrounding element (same as the argument on Mozilla, - * but not on IE), or null if unsuccessful. - */ -goog.dom.TextRange.prototype.surroundContents = function(element) { - var output = this.getBrowserRangeWrapper_().surroundContents(element); - this.clearCachedValues_(); - return output; -}; - - -/** @override */ -goog.dom.TextRange.prototype.insertNode = function(node, before) { - var output = this.getBrowserRangeWrapper_().insertNode(node, before); - this.clearCachedValues_(); - return output; -}; - - -/** @override */ -goog.dom.TextRange.prototype.surroundWithNodes = function(startNode, endNode) { - this.getBrowserRangeWrapper_().surroundWithNodes(startNode, endNode); - this.clearCachedValues_(); -}; - - -// SAVE/RESTORE - - -/** @override */ -goog.dom.TextRange.prototype.saveUsingDom = function() { - return new goog.dom.DomSavedTextRange_(this); -}; - - -// RANGE MODIFICATION - - -/** @override */ -goog.dom.TextRange.prototype.collapse = function(toAnchor) { - var toStart = this.isReversed() ? !toAnchor : toAnchor; - - if (this.browserRangeWrapper_) { - this.browserRangeWrapper_.collapse(toStart); - } - - if (toStart) { - this.endNode_ = this.startNode_; - this.endOffset_ = this.startOffset_; - } else { - this.startNode_ = this.endNode_; - this.startOffset_ = this.endOffset_; - } - - // Collapsed ranges can't be reversed - this.isReversed_ = false; -}; - - -// SAVED RANGE OBJECTS - - - -/** - * A SavedRange implementation using DOM endpoints. - * @param {goog.dom.AbstractRange} range The range to save. - * @constructor - * @extends {goog.dom.SavedRange} - * @private - */ -goog.dom.DomSavedTextRange_ = function(range) { - /** - * The anchor node. - * @type {Node} - * @private - */ - this.anchorNode_ = range.getAnchorNode(); - - /** - * The anchor node offset. - * @type {number} - * @private - */ - this.anchorOffset_ = range.getAnchorOffset(); - - /** - * The focus node. - * @type {Node} - * @private - */ - this.focusNode_ = range.getFocusNode(); - - /** - * The focus node offset. - * @type {number} - * @private - */ - this.focusOffset_ = range.getFocusOffset(); -}; -goog.inherits(goog.dom.DomSavedTextRange_, goog.dom.SavedRange); - - -/** - * @return {goog.dom.AbstractRange} The restored range. - * @override - */ -goog.dom.DomSavedTextRange_.prototype.restoreInternal = function() { - return goog.dom.Range.createFromNodes(this.anchorNode_, this.anchorOffset_, - this.focusNode_, this.focusOffset_); -}; - - -/** @override */ -goog.dom.DomSavedTextRange_.prototype.disposeInternal = function() { - goog.dom.DomSavedTextRange_.superClass_.disposeInternal.call(this); - - this.anchorNode_ = null; - this.focusNode_ = null; -}; |