Update wmts-hidpi, add nicer-api-docs
This commit is contained in:
470
nicer-api-docs/closure-library/closure/goog/dom/selection.js
Normal file
470
nicer-api-docs/closure-library/closure/goog/dom/selection.js
Normal file
@@ -0,0 +1,470 @@
|
||||
// Copyright 2006 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 selections in input boxes and text
|
||||
* areas.
|
||||
*
|
||||
* @see ../demos/dom_selection.html
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.dom.selection');
|
||||
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Sets the place where the selection should start inside a textarea or a text
|
||||
* input
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @param {number} pos The position to set the start of the selection at.
|
||||
*/
|
||||
goog.dom.selection.setStart = function(textfield, pos) {
|
||||
if (goog.dom.selection.useSelectionProperties_(textfield)) {
|
||||
textfield.selectionStart = pos;
|
||||
} else if (goog.userAgent.IE) {
|
||||
// destructuring assignment would have been sweet
|
||||
var tmp = goog.dom.selection.getRangeIe_(textfield);
|
||||
var range = tmp[0];
|
||||
var selectionRange = tmp[1];
|
||||
|
||||
if (range.inRange(selectionRange)) {
|
||||
pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos);
|
||||
|
||||
range.collapse(true);
|
||||
range.move('character', pos);
|
||||
range.select();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the place where the selection starts inside a textarea or a text
|
||||
* input
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @return {number} The position where the selection starts or 0 if it was
|
||||
* unable to find the position or no selection exists. Note that we can't
|
||||
* reliably tell the difference between an element that has no selection and
|
||||
* one where it starts at 0.
|
||||
*/
|
||||
goog.dom.selection.getStart = function(textfield) {
|
||||
return goog.dom.selection.getEndPoints_(textfield, true)[0];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the start and end points of the selection within a textarea in IE.
|
||||
* IE treats newline characters as \r\n characters, and we need to check for
|
||||
* these characters at the edge of our selection, to ensure that we return the
|
||||
* right cursor position.
|
||||
* @param {TextRange} range Complete range object, e.g., "Hello\r\n".
|
||||
* @param {TextRange} selRange Selected range object.
|
||||
* @param {boolean} getOnlyStart Value indicating if only start
|
||||
* cursor position is to be returned. In IE, obtaining the end position
|
||||
* involves extra work, hence we have this parameter for calls which need
|
||||
* only start position.
|
||||
* @return {Array.<number>} An array with the start and end positions where the
|
||||
* selection starts and ends or [0,0] if it was unable to find the
|
||||
* positions or no selection exists. Note that we can't reliably tell the
|
||||
* difference between an element that has no selection and one where
|
||||
* it starts and ends at 0. If getOnlyStart was true, we return
|
||||
* -1 as end offset.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.selection.getEndPointsTextareaIe_ = function(
|
||||
range, selRange, getOnlyStart) {
|
||||
// Create a duplicate of the selected range object to perform our actions
|
||||
// against. Example of selectionRange = "" (assuming that the cursor is
|
||||
// just after the \r\n combination)
|
||||
var selectionRange = selRange.duplicate();
|
||||
|
||||
// Text before the selection start, e.g.,"Hello" (notice how range.text
|
||||
// excludes the \r\n sequence)
|
||||
var beforeSelectionText = range.text;
|
||||
// Text before the selection start, e.g., "Hello" (this will later include
|
||||
// the \r\n sequences also)
|
||||
var untrimmedBeforeSelectionText = beforeSelectionText;
|
||||
// Text within the selection , e.g. "" assuming that the cursor is just after
|
||||
// the \r\n combination.
|
||||
var selectionText = selectionRange.text;
|
||||
// Text within the selection, e.g., "" (this will later include the \r\n
|
||||
// sequences also)
|
||||
var untrimmedSelectionText = selectionText;
|
||||
|
||||
// Boolean indicating whether we are done dealing with the text before the
|
||||
// selection's beginning.
|
||||
var isRangeEndTrimmed = false;
|
||||
// Go over the range until it becomes a 0-lengthed range or until the range
|
||||
// text starts changing when we move the end back by one character.
|
||||
// If after moving the end back by one character, the text remains the same,
|
||||
// then we need to add a "\r\n" at the end to get the actual text.
|
||||
while (!isRangeEndTrimmed) {
|
||||
if (range.compareEndPoints('StartToEnd', range) == 0) {
|
||||
isRangeEndTrimmed = true;
|
||||
} else {
|
||||
range.moveEnd('character', -1);
|
||||
if (range.text == beforeSelectionText) {
|
||||
// If the start position of the cursor was after a \r\n string,
|
||||
// we would skip over it in one go with the moveEnd call, but
|
||||
// range.text will still show "Hello" (because of the IE range.text
|
||||
// bug) - this implies that we should add a \r\n to our
|
||||
// untrimmedBeforeSelectionText string.
|
||||
untrimmedBeforeSelectionText += '\r\n';
|
||||
} else {
|
||||
isRangeEndTrimmed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getOnlyStart) {
|
||||
// We return -1 as end, since the caller is only interested in the start
|
||||
// value.
|
||||
return [untrimmedBeforeSelectionText.length, -1];
|
||||
}
|
||||
// Boolean indicating whether we are done dealing with the text inside the
|
||||
// selection.
|
||||
var isSelectionRangeEndTrimmed = false;
|
||||
// Go over the selected range until it becomes a 0-lengthed range or until
|
||||
// the range text starts changing when we move the end back by one character.
|
||||
// If after moving the end back by one character, the text remains the same,
|
||||
// then we need to add a "\r\n" at the end to get the actual text.
|
||||
while (!isSelectionRangeEndTrimmed) {
|
||||
if (selectionRange.compareEndPoints('StartToEnd', selectionRange) == 0) {
|
||||
isSelectionRangeEndTrimmed = true;
|
||||
} else {
|
||||
selectionRange.moveEnd('character', -1);
|
||||
if (selectionRange.text == selectionText) {
|
||||
// If the selection was not empty, and the end point of the selection
|
||||
// was just after a \r\n, we would have skipped it in one go with the
|
||||
// moveEnd call, and this implies that we should add a \r\n to the
|
||||
// untrimmedSelectionText string.
|
||||
untrimmedSelectionText += '\r\n';
|
||||
} else {
|
||||
isSelectionRangeEndTrimmed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [
|
||||
untrimmedBeforeSelectionText.length,
|
||||
untrimmedBeforeSelectionText.length + untrimmedSelectionText.length];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the start and end points of the selection inside a textarea or a
|
||||
* text input.
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @return {Array.<number>} An array with the start and end positions where the
|
||||
* selection starts and ends or [0,0] if it was unable to find the
|
||||
* positions or no selection exists. Note that we can't reliably tell the
|
||||
* difference between an element that has no selection and one where
|
||||
* it starts and ends at 0.
|
||||
*/
|
||||
goog.dom.selection.getEndPoints = function(textfield) {
|
||||
return goog.dom.selection.getEndPoints_(textfield, false);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the start and end points of the selection inside a textarea or a
|
||||
* text input.
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @param {boolean} getOnlyStart Value indicating if only start
|
||||
* cursor position is to be returned. In IE, obtaining the end position
|
||||
* involves extra work, hence we have this parameter. In FF, there is not
|
||||
* much extra effort involved.
|
||||
* @return {Array.<number>} An array with the start and end positions where the
|
||||
* selection starts and ends or [0,0] if it was unable to find the
|
||||
* positions or no selection exists. Note that we can't reliably tell the
|
||||
* difference between an element that has no selection and one where
|
||||
* it starts and ends at 0. If getOnlyStart was true, we return
|
||||
* -1 as end offset.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.selection.getEndPoints_ = function(textfield, getOnlyStart) {
|
||||
var startPos = 0;
|
||||
var endPos = 0;
|
||||
if (goog.dom.selection.useSelectionProperties_(textfield)) {
|
||||
startPos = textfield.selectionStart;
|
||||
endPos = getOnlyStart ? -1 : textfield.selectionEnd;
|
||||
} else if (goog.userAgent.IE) {
|
||||
var tmp = goog.dom.selection.getRangeIe_(textfield);
|
||||
var range = tmp[0];
|
||||
var selectionRange = tmp[1];
|
||||
|
||||
if (range.inRange(selectionRange)) {
|
||||
range.setEndPoint('EndToStart', selectionRange);
|
||||
if (textfield.type == 'textarea') {
|
||||
return goog.dom.selection.getEndPointsTextareaIe_(
|
||||
range, selectionRange, getOnlyStart);
|
||||
}
|
||||
startPos = range.text.length;
|
||||
if (!getOnlyStart) {
|
||||
endPos = range.text.length + selectionRange.text.length;
|
||||
} else {
|
||||
endPos = -1; // caller did not ask for end position
|
||||
}
|
||||
}
|
||||
}
|
||||
return [startPos, endPos];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the place where the selection should end inside a text area or a text
|
||||
* input
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @param {number} pos The position to end the selection at.
|
||||
*/
|
||||
goog.dom.selection.setEnd = function(textfield, pos) {
|
||||
if (goog.dom.selection.useSelectionProperties_(textfield)) {
|
||||
textfield.selectionEnd = pos;
|
||||
} else if (goog.userAgent.IE) {
|
||||
var tmp = goog.dom.selection.getRangeIe_(textfield);
|
||||
var range = tmp[0];
|
||||
var selectionRange = tmp[1];
|
||||
|
||||
if (range.inRange(selectionRange)) {
|
||||
// Both the current position and the start cursor position need
|
||||
// to be canonicalized to take care of possible \r\n miscounts.
|
||||
pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos);
|
||||
var startCursorPos = goog.dom.selection.canonicalizePositionIe_(
|
||||
textfield, goog.dom.selection.getStart(textfield));
|
||||
|
||||
selectionRange.collapse(true);
|
||||
selectionRange.moveEnd('character', pos - startCursorPos);
|
||||
selectionRange.select();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the place where the selection ends inside a textarea or a text input
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @return {number} The position where the selection ends or 0 if it was
|
||||
* unable to find the position or no selection exists.
|
||||
*/
|
||||
goog.dom.selection.getEnd = function(textfield) {
|
||||
return goog.dom.selection.getEndPoints_(textfield, false)[1];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the cursor position within a textfield.
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @param {number} pos The position within the text field.
|
||||
*/
|
||||
goog.dom.selection.setCursorPosition = function(textfield, pos) {
|
||||
if (goog.dom.selection.useSelectionProperties_(textfield)) {
|
||||
// Mozilla directly supports this
|
||||
textfield.selectionStart = pos;
|
||||
textfield.selectionEnd = pos;
|
||||
|
||||
} else if (goog.userAgent.IE) {
|
||||
pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos);
|
||||
|
||||
// IE has textranges. A textfield's textrange encompasses the
|
||||
// entire textfield's text by default
|
||||
var sel = textfield.createTextRange();
|
||||
|
||||
sel.collapse(true);
|
||||
sel.move('character', pos);
|
||||
sel.select();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the selected text inside a textarea or a text input
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @param {string} text The text to change the selection to.
|
||||
*/
|
||||
goog.dom.selection.setText = function(textfield, text) {
|
||||
if (goog.dom.selection.useSelectionProperties_(textfield)) {
|
||||
var value = textfield.value;
|
||||
var oldSelectionStart = textfield.selectionStart;
|
||||
var before = value.substr(0, oldSelectionStart);
|
||||
var after = value.substr(textfield.selectionEnd);
|
||||
textfield.value = before + text + after;
|
||||
textfield.selectionStart = oldSelectionStart;
|
||||
textfield.selectionEnd = oldSelectionStart + text.length;
|
||||
} else if (goog.userAgent.IE) {
|
||||
var tmp = goog.dom.selection.getRangeIe_(textfield);
|
||||
var range = tmp[0];
|
||||
var selectionRange = tmp[1];
|
||||
|
||||
if (!range.inRange(selectionRange)) {
|
||||
return;
|
||||
}
|
||||
// When we set the selection text the selection range is collapsed to the
|
||||
// end. We therefore duplicate the current selection so we know where it
|
||||
// started. Once we've set the selection text we move the start of the
|
||||
// selection range to the old start
|
||||
var range2 = selectionRange.duplicate();
|
||||
selectionRange.text = text;
|
||||
selectionRange.setEndPoint('StartToStart', range2);
|
||||
selectionRange.select();
|
||||
} else {
|
||||
throw Error('Cannot set the selection end');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the selected text inside a textarea or a text input
|
||||
* @param {Element} textfield A textarea or text input.
|
||||
* @return {string} The selected text.
|
||||
*/
|
||||
goog.dom.selection.getText = function(textfield) {
|
||||
if (goog.dom.selection.useSelectionProperties_(textfield)) {
|
||||
var s = textfield.value;
|
||||
return s.substring(textfield.selectionStart, textfield.selectionEnd);
|
||||
}
|
||||
|
||||
if (goog.userAgent.IE) {
|
||||
var tmp = goog.dom.selection.getRangeIe_(textfield);
|
||||
var range = tmp[0];
|
||||
var selectionRange = tmp[1];
|
||||
|
||||
if (!range.inRange(selectionRange)) {
|
||||
return '';
|
||||
} else if (textfield.type == 'textarea') {
|
||||
return goog.dom.selection.getSelectionRangeText_(selectionRange);
|
||||
}
|
||||
return selectionRange.text;
|
||||
}
|
||||
|
||||
throw Error('Cannot get the selection text');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the selected text within a textarea in IE.
|
||||
* IE treats newline characters as \r\n characters, and we need to check for
|
||||
* these characters at the edge of our selection, to ensure that we return the
|
||||
* right string.
|
||||
* @param {TextRange} selRange Selected range object.
|
||||
* @return {string} Selected text in the textarea.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.selection.getSelectionRangeText_ = function(selRange) {
|
||||
// Create a duplicate of the selected range object to perform our actions
|
||||
// against. Suppose the text in the textarea is "Hello\r\nWorld" and the
|
||||
// selection encompasses the "o\r\n" bit, initial selectionRange will be "o"
|
||||
// (assuming that the cursor is just after the \r\n combination)
|
||||
var selectionRange = selRange.duplicate();
|
||||
|
||||
// Text within the selection , e.g. "o" assuming that the cursor is just after
|
||||
// the \r\n combination.
|
||||
var selectionText = selectionRange.text;
|
||||
// Text within the selection, e.g., "o" (this will later include the \r\n
|
||||
// sequences also)
|
||||
var untrimmedSelectionText = selectionText;
|
||||
|
||||
// Boolean indicating whether we are done dealing with the text inside the
|
||||
// selection.
|
||||
var isSelectionRangeEndTrimmed = false;
|
||||
// Go over the selected range until it becomes a 0-lengthed range or until
|
||||
// the range text starts changing when we move the end back by one character.
|
||||
// If after moving the end back by one character, the text remains the same,
|
||||
// then we need to add a "\r\n" at the end to get the actual text.
|
||||
while (!isSelectionRangeEndTrimmed) {
|
||||
if (selectionRange.compareEndPoints('StartToEnd', selectionRange) == 0) {
|
||||
isSelectionRangeEndTrimmed = true;
|
||||
} else {
|
||||
selectionRange.moveEnd('character', -1);
|
||||
if (selectionRange.text == selectionText) {
|
||||
// If the selection was not empty, and the end point of the selection
|
||||
// was just after a \r\n, we would have skipped it in one go with the
|
||||
// moveEnd call, and this implies that we should add a \r\n to the
|
||||
// untrimmedSelectionText string.
|
||||
untrimmedSelectionText += '\r\n';
|
||||
} else {
|
||||
isSelectionRangeEndTrimmed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return untrimmedSelectionText;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for returning the range for an object as well as the
|
||||
* selection range
|
||||
* @private
|
||||
* @param {Element} el The element to get the range for.
|
||||
* @return {Array.<TextRange>} Range of object and selection range in two
|
||||
* element array.
|
||||
*/
|
||||
goog.dom.selection.getRangeIe_ = function(el) {
|
||||
var doc = el.ownerDocument || el.document;
|
||||
|
||||
var selectionRange = doc.selection.createRange();
|
||||
// el.createTextRange() doesn't work on textareas
|
||||
var range;
|
||||
|
||||
if (el.type == 'textarea') {
|
||||
range = doc.body.createTextRange();
|
||||
range.moveToElementText(el);
|
||||
} else {
|
||||
range = el.createTextRange();
|
||||
}
|
||||
|
||||
return [range, selectionRange];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for canonicalizing a position inside a textfield in IE.
|
||||
* Deals with the issue that \r\n counts as 2 characters, but
|
||||
* move('character', n) passes over both characters in one move.
|
||||
* @private
|
||||
* @param {Element} textfield The text element.
|
||||
* @param {number} pos The position desired in that element.
|
||||
* @return {number} The canonicalized position that will work properly with
|
||||
* move('character', pos).
|
||||
*/
|
||||
goog.dom.selection.canonicalizePositionIe_ = function(textfield, pos) {
|
||||
if (textfield.type == 'textarea') {
|
||||
// We do this only for textarea because it is the only one which can
|
||||
// have a \r\n (input cannot have this).
|
||||
var value = textfield.value.substring(0, pos);
|
||||
pos = goog.string.canonicalizeNewlines(value).length;
|
||||
}
|
||||
return pos;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to determine whether it's okay to use
|
||||
* selectionStart/selectionEnd.
|
||||
*
|
||||
* @param {Element} el The element to check for.
|
||||
* @return {boolean} Whether it's okay to use the selectionStart and
|
||||
* selectionEnd properties on {@code el}.
|
||||
* @private
|
||||
*/
|
||||
goog.dom.selection.useSelectionProperties_ = function(el) {
|
||||
try {
|
||||
return typeof el.selectionStart == 'number';
|
||||
} catch (e) {
|
||||
// Firefox throws an exception if you try to access selectionStart
|
||||
// on an element with display: none.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user