Adding mapbox-gl branch
This commit is contained in:
@@ -0,0 +1,722 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.dom.RangeTest');
|
||||
goog.setTestOnly('goog.dom.RangeTest');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.NodeType');
|
||||
goog.require('goog.dom.Range');
|
||||
goog.require('goog.dom.RangeType');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.dom.TextRange');
|
||||
goog.require('goog.dom.browserrange');
|
||||
goog.require('goog.testing.dom');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
var assertRangeEquals = goog.testing.dom.assertRangeEquals;
|
||||
|
||||
function setUp() {
|
||||
// Reset the focus; some tests may invalidate the focus to exercise various
|
||||
// browser bugs.
|
||||
var focusableElement = goog.dom.getElement('focusableElement');
|
||||
focusableElement.focus();
|
||||
focusableElement.blur();
|
||||
}
|
||||
|
||||
function normalizeHtml(str) {
|
||||
return str.toLowerCase().replace(/[\n\r\f"]/g, '')
|
||||
.replace(/<\/li>/g, ''); // " for emacs
|
||||
}
|
||||
|
||||
function testCreate() {
|
||||
assertNotNull('Browser range object can be created for node',
|
||||
goog.dom.Range.createFromNodeContents(goog.dom.getElement('test1')));
|
||||
}
|
||||
|
||||
function testTableRange() {
|
||||
var tr = goog.dom.getElement('cell').parentNode;
|
||||
var range = goog.dom.Range.createFromNodeContents(tr);
|
||||
assertEquals('Selection should have correct text', '12',
|
||||
range.getText());
|
||||
assertEquals('Selection should have correct html fragment',
|
||||
'1</td><td>2', normalizeHtml(range.getHtmlFragment()));
|
||||
|
||||
// TODO(robbyw): On IE the TR is included, on FF it is not.
|
||||
//assertEquals('Selection should have correct valid html',
|
||||
// '<tr id=row><td>1</td><td>2</td></tr>',
|
||||
// normalizeHtml(range.getValidHtml()));
|
||||
|
||||
assertEquals('Selection should have correct pastable html',
|
||||
'<table><tbody><tr><td id=cell>1</td><td>2</td></tr></tbody></table>',
|
||||
normalizeHtml(range.getPastableHtml()));
|
||||
}
|
||||
|
||||
function testUnorderedListRange() {
|
||||
var ul = goog.dom.getElement('ulTest').firstChild;
|
||||
var range = goog.dom.Range.createFromNodeContents(ul);
|
||||
assertEquals('Selection should have correct html fragment',
|
||||
'1<li>2', normalizeHtml(range.getHtmlFragment()));
|
||||
|
||||
// TODO(robbyw): On IE the UL is included, on FF it is not.
|
||||
//assertEquals('Selection should have correct valid html',
|
||||
// '<li>1</li><li>2</li>', normalizeHtml(range.getValidHtml()));
|
||||
|
||||
assertEquals('Selection should have correct pastable html',
|
||||
'<ul><li>1<li>2</ul>',
|
||||
normalizeHtml(range.getPastableHtml()));
|
||||
}
|
||||
|
||||
function testOrderedListRange() {
|
||||
var ol = goog.dom.getElement('olTest').firstChild;
|
||||
var range = goog.dom.Range.createFromNodeContents(ol);
|
||||
assertEquals('Selection should have correct html fragment',
|
||||
'1<li>2', normalizeHtml(range.getHtmlFragment()));
|
||||
|
||||
// TODO(robbyw): On IE the OL is included, on FF it is not.
|
||||
//assertEquals('Selection should have correct valid html',
|
||||
// '<li>1</li><li>2</li>', normalizeHtml(range.getValidHtml()));
|
||||
|
||||
assertEquals('Selection should have correct pastable html',
|
||||
'<ol><li>1<li>2</ol>',
|
||||
normalizeHtml(range.getPastableHtml()));
|
||||
}
|
||||
|
||||
function testCreateFromNodes() {
|
||||
var start = goog.dom.getElement('test1').firstChild;
|
||||
var end = goog.dom.getElement('br');
|
||||
var range = goog.dom.Range.createFromNodes(start, 2, end, 0);
|
||||
assertNotNull('Browser range object can be created for W3C node range',
|
||||
range);
|
||||
|
||||
assertEquals('Start node should be selected at start endpoint', start,
|
||||
range.getStartNode());
|
||||
assertEquals('Selection should start at offset 2', 2,
|
||||
range.getStartOffset());
|
||||
assertEquals('Start node should be selected at anchor endpoint', start,
|
||||
range.getAnchorNode());
|
||||
assertEquals('Selection should be anchored at offset 2', 2,
|
||||
range.getAnchorOffset());
|
||||
|
||||
var div = goog.dom.getElement('test2');
|
||||
assertEquals('DIV node should be selected at end endpoint', div,
|
||||
range.getEndNode());
|
||||
assertEquals('Selection should end at offset 1', 1, range.getEndOffset());
|
||||
assertEquals('DIV node should be selected at focus endpoint', div,
|
||||
range.getFocusNode());
|
||||
assertEquals('Selection should be focused at offset 1', 1,
|
||||
range.getFocusOffset());
|
||||
|
||||
|
||||
assertTrue('Text content should be "xt\\s*abc"',
|
||||
/xt\s*abc/.test(range.getText()));
|
||||
assertFalse('Nodes range is not collapsed', range.isCollapsed());
|
||||
}
|
||||
|
||||
|
||||
function testCreateControlRange() {
|
||||
if (!goog.userAgent.IE) {
|
||||
return;
|
||||
}
|
||||
var cr = document.body.createControlRange();
|
||||
cr.addElement(goog.dom.getElement('logo'));
|
||||
|
||||
var range = goog.dom.Range.createFromBrowserRange(cr);
|
||||
assertNotNull('Control range object can be created from browser range',
|
||||
range);
|
||||
assertEquals('Created range is a control range', goog.dom.RangeType.CONTROL,
|
||||
range.getType());
|
||||
}
|
||||
|
||||
|
||||
function testTextNode() {
|
||||
var range = goog.dom.Range.createFromNodeContents(
|
||||
goog.dom.getElement('test1').firstChild);
|
||||
|
||||
assertEquals('Created range is a text range', goog.dom.RangeType.TEXT,
|
||||
range.getType());
|
||||
assertEquals('Text node should be selected at start endpoint', 'Text',
|
||||
range.getStartNode().nodeValue);
|
||||
assertEquals('Selection should start at offset 0', 0,
|
||||
range.getStartOffset());
|
||||
|
||||
assertEquals('Text node should be selected at end endpoint', 'Text',
|
||||
range.getEndNode().nodeValue);
|
||||
assertEquals('Selection should end at offset 4', 'Text'.length,
|
||||
range.getEndOffset());
|
||||
|
||||
assertEquals('Container should be text node', goog.dom.NodeType.TEXT,
|
||||
range.getContainer().nodeType);
|
||||
|
||||
assertEquals('Text content should be "Text"', 'Text', range.getText());
|
||||
assertFalse('Text range is not collapsed', range.isCollapsed());
|
||||
}
|
||||
|
||||
|
||||
function testDiv() {
|
||||
var range = goog.dom.Range.createFromNodeContents(
|
||||
goog.dom.getElement('test2'));
|
||||
|
||||
assertEquals('Text node "abc" should be selected at start endpoint', 'abc',
|
||||
range.getStartNode().nodeValue);
|
||||
assertEquals('Selection should start at offset 0', 0,
|
||||
range.getStartOffset());
|
||||
|
||||
assertEquals('Text node "def" should be selected at end endpoint', 'def',
|
||||
range.getEndNode().nodeValue);
|
||||
assertEquals('Selection should end at offset 3', 'def'.length,
|
||||
range.getEndOffset());
|
||||
|
||||
assertEquals('Container should be DIV', goog.dom.getElement('test2'),
|
||||
range.getContainer());
|
||||
|
||||
assertTrue('Div text content should be "abc\\s*def"',
|
||||
/abc\s*def/.test(range.getText()));
|
||||
assertFalse('Div range is not collapsed', range.isCollapsed());
|
||||
}
|
||||
|
||||
|
||||
function testEmptyNode() {
|
||||
var range = goog.dom.Range.createFromNodeContents(
|
||||
goog.dom.getElement('empty'));
|
||||
|
||||
assertEquals('DIV be selected at start endpoint',
|
||||
goog.dom.getElement('empty'), range.getStartNode());
|
||||
assertEquals('Selection should start at offset 0', 0,
|
||||
range.getStartOffset());
|
||||
|
||||
assertEquals('DIV should be selected at end endpoint',
|
||||
goog.dom.getElement('empty'), range.getEndNode());
|
||||
assertEquals('Selection should end at offset 0', 0,
|
||||
range.getEndOffset());
|
||||
|
||||
assertEquals('Container should be DIV', goog.dom.getElement('empty'),
|
||||
range.getContainer());
|
||||
|
||||
assertEquals('Empty text content should be ""', '', range.getText());
|
||||
assertTrue('Empty range is collapsed', range.isCollapsed());
|
||||
}
|
||||
|
||||
|
||||
function testCollapse() {
|
||||
var range = goog.dom.Range.createFromNodeContents(
|
||||
goog.dom.getElement('test2'));
|
||||
assertFalse('Div range is not collapsed', range.isCollapsed());
|
||||
range.collapse();
|
||||
assertTrue('Div range is collapsed after call to empty()',
|
||||
range.isCollapsed());
|
||||
|
||||
range = goog.dom.Range.createFromNodeContents(goog.dom.getElement('empty'));
|
||||
assertTrue('Empty range is collapsed', range.isCollapsed());
|
||||
range.collapse();
|
||||
assertTrue('Empty range is still collapsed', range.isCollapsed());
|
||||
}
|
||||
|
||||
// TODO(robbyw): Test iteration over a strange document fragment.
|
||||
|
||||
function testIterator() {
|
||||
goog.testing.dom.assertNodesMatch(goog.dom.Range.createFromNodeContents(
|
||||
goog.dom.getElement('test2')), ['abc', '#br', '#br', 'def']);
|
||||
}
|
||||
|
||||
function testReversedNodes() {
|
||||
var node = goog.dom.getElement('test1').firstChild;
|
||||
var range = goog.dom.Range.createFromNodes(node, 4, node, 0);
|
||||
assertTrue('Range is reversed', range.isReversed());
|
||||
node = goog.dom.getElement('test3');
|
||||
range = goog.dom.Range.createFromNodes(node, 0, node, 1);
|
||||
assertFalse('Range is not reversed', range.isReversed());
|
||||
}
|
||||
|
||||
function testReversedContents() {
|
||||
var range = goog.dom.Range.createFromNodeContents(
|
||||
goog.dom.getElement('test1'), true);
|
||||
assertTrue('Range is reversed', range.isReversed());
|
||||
assertEquals('Range should select "Text"', 'Text',
|
||||
range.getText());
|
||||
assertEquals('Range start offset should be 0', 0, range.getStartOffset());
|
||||
assertEquals('Range end offset should be 4', 4, range.getEndOffset());
|
||||
assertEquals('Range anchor offset should be 4', 4, range.getAnchorOffset());
|
||||
assertEquals('Range focus offset should be 0', 0, range.getFocusOffset());
|
||||
|
||||
var range2 = range.clone();
|
||||
|
||||
range.collapse(true);
|
||||
assertTrue('Range is collapsed', range.isCollapsed());
|
||||
assertFalse('Collapsed range is not reversed', range.isReversed());
|
||||
assertEquals('Post collapse start offset should be 4', 4,
|
||||
range.getStartOffset());
|
||||
|
||||
range2.collapse(false);
|
||||
assertTrue('Range 2 is collapsed', range2.isCollapsed());
|
||||
assertFalse('Collapsed range 2 is not reversed', range2.isReversed());
|
||||
assertEquals('Post collapse start offset 2 should be 0', 0,
|
||||
range2.getStartOffset());
|
||||
}
|
||||
|
||||
function testRemoveContents() {
|
||||
var outer = goog.dom.getElement('removeTest');
|
||||
var range = goog.dom.Range.createFromNodeContents(outer.firstChild);
|
||||
|
||||
range.removeContents();
|
||||
|
||||
assertEquals('Removed range content should be ""', '', range.getText());
|
||||
assertTrue('Removed range should be collapsed', range.isCollapsed());
|
||||
assertEquals('Outer div should have 1 child now', 1,
|
||||
outer.childNodes.length);
|
||||
assertEquals('Inner div should be empty', 0,
|
||||
outer.firstChild.childNodes.length);
|
||||
}
|
||||
|
||||
function testRemovePartialContents() {
|
||||
var outer = goog.dom.getElement('removePartialTest');
|
||||
var originalText = goog.dom.getTextContent(outer);
|
||||
|
||||
try {
|
||||
var range = goog.dom.Range.createFromNodes(outer.firstChild, 2,
|
||||
outer.firstChild, 4);
|
||||
removeHelper(1, range, outer, 1, '0145');
|
||||
|
||||
range = goog.dom.Range.createFromNodes(outer.firstChild, 0,
|
||||
outer.firstChild, 1);
|
||||
removeHelper(2, range, outer, 1, '145');
|
||||
|
||||
range = goog.dom.Range.createFromNodes(outer.firstChild, 2,
|
||||
outer.firstChild, 3);
|
||||
removeHelper(3, range, outer, 1, '14');
|
||||
|
||||
var br = goog.dom.createDom('BR');
|
||||
outer.appendChild(br);
|
||||
range = goog.dom.Range.createFromNodes(outer.firstChild, 1,
|
||||
outer, 1);
|
||||
removeHelper(4, range, outer, 2, '1<br>');
|
||||
|
||||
outer.innerHTML = '<br>123';
|
||||
range = goog.dom.Range.createFromNodes(outer, 0, outer.lastChild, 2);
|
||||
removeHelper(5, range, outer, 1, '3');
|
||||
|
||||
outer.innerHTML = '123<br>456';
|
||||
range = goog.dom.Range.createFromNodes(outer.firstChild, 1, outer.lastChild,
|
||||
2);
|
||||
removeHelper(6, range, outer, 2, '16');
|
||||
|
||||
outer.innerHTML = '123<br>456';
|
||||
range = goog.dom.Range.createFromNodes(outer.firstChild, 0, outer.lastChild,
|
||||
2);
|
||||
removeHelper(7, range, outer, 1, '6');
|
||||
|
||||
outer.innerHTML = '<div></div>';
|
||||
range = goog.dom.Range.createFromNodeContents(outer.firstChild);
|
||||
removeHelper(8, range, outer, 1, '<div></div>');
|
||||
} finally {
|
||||
// Restore the original text state for repeated runs.
|
||||
goog.dom.setTextContent(outer, originalText);
|
||||
}
|
||||
|
||||
// TODO(robbyw): Fix the following edge cases:
|
||||
// * Selecting contents of a node containing multiply empty divs
|
||||
// * Selecting via createFromNodes(x, 0, x, x.childNodes.length)
|
||||
// * Consistent handling of nodeContents(<div><div></div></div>).remove
|
||||
}
|
||||
|
||||
function removeHelper(testNumber, range, outer, expectedChildCount,
|
||||
expectedContent) {
|
||||
range.removeContents();
|
||||
assertTrue(testNumber + ': Removed range should now be collapsed',
|
||||
range.isCollapsed());
|
||||
assertEquals(testNumber + ': Removed range content should be ""', '',
|
||||
range.getText());
|
||||
assertEquals(testNumber + ': Outer div should contain correct text',
|
||||
expectedContent, outer.innerHTML.toLowerCase());
|
||||
assertEquals(testNumber + ': Outer div should have ' + expectedChildCount +
|
||||
' children now', expectedChildCount, outer.childNodes.length);
|
||||
assertNotNull(testNumber + ': Empty node should still exist',
|
||||
goog.dom.getElement('empty'));
|
||||
}
|
||||
|
||||
function testSurroundContents() {
|
||||
var outer = goog.dom.getElement('surroundTest');
|
||||
outer.innerHTML = '---Text that<br>will be surrounded---';
|
||||
var range = goog.dom.Range.createFromNodes(outer.firstChild, 3,
|
||||
outer.lastChild, outer.lastChild.nodeValue.length - 3);
|
||||
|
||||
var div = goog.dom.createDom(goog.dom.TagName.DIV, {'style': 'color: red'});
|
||||
var output = range.surroundContents(div);
|
||||
|
||||
assertEquals('Outer element should contain new element', outer,
|
||||
output.parentNode);
|
||||
assertFalse('New element should have no id', !!output.id);
|
||||
assertEquals('New element should be red', 'red', output.style.color);
|
||||
assertEquals('Outer element should have three children', 3,
|
||||
outer.childNodes.length);
|
||||
assertEquals('New element should have three children', 3,
|
||||
output.childNodes.length);
|
||||
|
||||
// TODO(robbyw): Ensure the range stays in a reasonable state.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given two offsets into the 'foobar' node, make sure that inserting
|
||||
* nodes at those offsets doesn't change a selection of 'oba'.
|
||||
* @bug 1480638
|
||||
*/
|
||||
function assertSurroundDoesntChangeSelectionWithOffsets(
|
||||
offset1, offset2, expectedHtml) {
|
||||
var div = goog.dom.getElement('bug1480638');
|
||||
div.innerHTML = 'foobar';
|
||||
var rangeToSelect = goog.dom.Range.createFromNodes(
|
||||
div.firstChild, 2, div.firstChild, 5);
|
||||
rangeToSelect.select();
|
||||
|
||||
var rangeToSurround = goog.dom.Range.createFromNodes(
|
||||
div.firstChild, offset1, div.firstChild, offset2);
|
||||
rangeToSurround.surroundWithNodes(goog.dom.createDom('span'),
|
||||
goog.dom.createDom('span'));
|
||||
|
||||
// Make sure that the selection didn't change.
|
||||
assertHTMLEquals('Selection must not change when contents are surrounded.',
|
||||
expectedHtml, goog.dom.Range.createFromWindow().getHtmlFragment());
|
||||
}
|
||||
|
||||
function testSurroundWithNodesDoesntChangeSelection1() {
|
||||
assertSurroundDoesntChangeSelectionWithOffsets(3, 4,
|
||||
'o<span></span>b<span></span>a');
|
||||
}
|
||||
|
||||
function testSurroundWithNodesDoesntChangeSelection2() {
|
||||
assertSurroundDoesntChangeSelectionWithOffsets(3, 6,
|
||||
'o<span></span>ba');
|
||||
}
|
||||
|
||||
function testSurroundWithNodesDoesntChangeSelection3() {
|
||||
assertSurroundDoesntChangeSelectionWithOffsets(1, 3,
|
||||
'o<span></span>ba');
|
||||
}
|
||||
|
||||
function testSurroundWithNodesDoesntChangeSelection4() {
|
||||
assertSurroundDoesntChangeSelectionWithOffsets(1, 6,
|
||||
'oba');
|
||||
}
|
||||
|
||||
function testInsertNode() {
|
||||
var outer = goog.dom.getElement('insertTest');
|
||||
outer.innerHTML = 'ACD';
|
||||
|
||||
var range = goog.dom.Range.createFromNodes(outer.firstChild, 1,
|
||||
outer.firstChild, 2);
|
||||
range.insertNode(goog.dom.createTextNode('B'), true);
|
||||
assertEquals('Element should have correct innerHTML', 'ABCD',
|
||||
outer.innerHTML);
|
||||
|
||||
outer.innerHTML = '12';
|
||||
range = goog.dom.Range.createFromNodes(outer.firstChild, 0,
|
||||
outer.firstChild, 1);
|
||||
var br = range.insertNode(goog.dom.createDom(goog.dom.TagName.BR), false);
|
||||
assertEquals('New element should have correct innerHTML', '1<br>2',
|
||||
outer.innerHTML.toLowerCase());
|
||||
assertEquals('BR should be in outer', outer, br.parentNode);
|
||||
}
|
||||
|
||||
function testReplaceContentsWithNode() {
|
||||
var outer = goog.dom.getElement('insertTest');
|
||||
outer.innerHTML = 'AXC';
|
||||
|
||||
var range = goog.dom.Range.createFromNodes(outer.firstChild, 1,
|
||||
outer.firstChild, 2);
|
||||
range.replaceContentsWithNode(goog.dom.createTextNode('B'));
|
||||
assertEquals('Element should have correct innerHTML', 'ABC',
|
||||
outer.innerHTML);
|
||||
|
||||
outer.innerHTML = 'ABC';
|
||||
range = goog.dom.Range.createFromNodes(outer.firstChild, 3,
|
||||
outer.firstChild, 3);
|
||||
range.replaceContentsWithNode(goog.dom.createTextNode('D'));
|
||||
assertEquals(
|
||||
'Element should have correct innerHTML after collapsed replace',
|
||||
'ABCD', outer.innerHTML);
|
||||
|
||||
outer.innerHTML = 'AX<b>X</b>XC';
|
||||
range = goog.dom.Range.createFromNodes(outer.firstChild, 1,
|
||||
outer.lastChild, 1);
|
||||
range.replaceContentsWithNode(goog.dom.createTextNode('B'));
|
||||
goog.testing.dom.assertHtmlContentsMatch('ABC', outer);
|
||||
}
|
||||
|
||||
function testSurroundWithNodes() {
|
||||
var outer = goog.dom.getElement('insertTest');
|
||||
outer.innerHTML = 'ACE';
|
||||
var range = goog.dom.Range.createFromNodes(outer.firstChild, 1,
|
||||
outer.firstChild, 2);
|
||||
|
||||
range.surroundWithNodes(goog.dom.createTextNode('B'),
|
||||
goog.dom.createTextNode('D'));
|
||||
|
||||
assertEquals('New element should have correct innerHTML', 'ABCDE',
|
||||
outer.innerHTML);
|
||||
}
|
||||
|
||||
function testIsRangeInDocument() {
|
||||
var outer = goog.dom.getElement('insertTest');
|
||||
outer.innerHTML = '<br>ABC';
|
||||
var range = goog.dom.Range.createCaret(outer.lastChild, 1);
|
||||
|
||||
assertEquals('Should get correct start element', 'ABC',
|
||||
range.getStartNode().nodeValue);
|
||||
assertTrue('Should be considered in document', range.isRangeInDocument());
|
||||
|
||||
outer.innerHTML = 'DEF';
|
||||
|
||||
assertFalse('Should be marked as out of document',
|
||||
range.isRangeInDocument());
|
||||
}
|
||||
|
||||
function testRemovedNode() {
|
||||
var node = goog.dom.getElement('removeNodeTest');
|
||||
var range = goog.dom.browserrange.createRangeFromNodeContents(node);
|
||||
range.select();
|
||||
goog.dom.removeNode(node);
|
||||
|
||||
var newRange = goog.dom.Range.createFromWindow(window);
|
||||
|
||||
// In Chrome 14 and below (<= Webkit 535.1), newRange will be null.
|
||||
// In Chrome 16 and above (>= Webkit 535.7), newRange will be collapsed
|
||||
// like on other browsers.
|
||||
// We didn't bother testing in between.
|
||||
if (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('535.7')) {
|
||||
assertNull('Webkit supports rangeCount == 0', newRange);
|
||||
} else {
|
||||
assertTrue('The other browsers will just have an empty range.',
|
||||
newRange.isCollapsed());
|
||||
}
|
||||
}
|
||||
|
||||
function testReversedRange() {
|
||||
goog.dom.Range.createFromNodes(goog.dom.getElement('test2'), 0,
|
||||
goog.dom.getElement('test1'), 0).select();
|
||||
|
||||
var range = goog.dom.Range.createFromWindow(window);
|
||||
assertTrue('Range should be reversed',
|
||||
goog.userAgent.IE || range.isReversed());
|
||||
}
|
||||
|
||||
function testUnreversedRange() {
|
||||
goog.dom.Range.createFromNodes(goog.dom.getElement('test1'), 0,
|
||||
goog.dom.getElement('test2'), 0).select();
|
||||
|
||||
var range = goog.dom.Range.createFromWindow(window);
|
||||
assertFalse('Range should not be reversed', range.isReversed());
|
||||
}
|
||||
|
||||
function testReversedThenUnreversedRange() {
|
||||
// This tests a workaround for a webkit bug where webkit caches selections
|
||||
// incorrectly.
|
||||
goog.dom.Range.createFromNodes(goog.dom.getElement('test2'), 0,
|
||||
goog.dom.getElement('test1'), 0).select();
|
||||
goog.dom.Range.createFromNodes(goog.dom.getElement('test1'), 0,
|
||||
goog.dom.getElement('test2'), 0).select();
|
||||
|
||||
var range = goog.dom.Range.createFromWindow(window);
|
||||
assertFalse('Range should not be reversed', range.isReversed());
|
||||
}
|
||||
|
||||
function testHasAndClearSelection() {
|
||||
goog.dom.Range.createFromNodeContents(
|
||||
goog.dom.getElement('test1')).select();
|
||||
|
||||
assertTrue('Selection should exist', goog.dom.Range.hasSelection());
|
||||
|
||||
goog.dom.Range.clearSelection();
|
||||
|
||||
assertFalse('Selection should not exist', goog.dom.Range.hasSelection());
|
||||
}
|
||||
|
||||
function assertForward(string, startNode, startOffset, endNode, endOffset) {
|
||||
var root = goog.dom.getElement('test2');
|
||||
var originalInnerHtml = root.innerHTML;
|
||||
|
||||
assertFalse(string, goog.dom.Range.isReversed(startNode, startOffset,
|
||||
endNode, endOffset));
|
||||
assertTrue(string, goog.dom.Range.isReversed(endNode, endOffset,
|
||||
startNode, startOffset));
|
||||
assertEquals('Contents should be unaffected after: ' + string,
|
||||
root.innerHTML, originalInnerHtml);
|
||||
}
|
||||
|
||||
function testIsReversed() {
|
||||
var root = goog.dom.getElement('test2');
|
||||
var text1 = root.firstChild; // Text content: 'abc'.
|
||||
var br = root.childNodes[1];
|
||||
var text2 = root.lastChild; // Text content: 'def'.
|
||||
|
||||
assertFalse('Same element position gives false', goog.dom.Range.isReversed(
|
||||
root, 0, root, 0));
|
||||
assertFalse('Same text position gives false', goog.dom.Range.isReversed(
|
||||
text1, 0, text2, 0));
|
||||
assertForward('Element offsets should compare against each other',
|
||||
root, 0, root, 2);
|
||||
assertForward('Text node offsets should compare against each other',
|
||||
text1, 0, text2, 2);
|
||||
assertForward('Text nodes should compare correctly',
|
||||
text1, 0, text2, 0);
|
||||
assertForward('Text nodes should compare to later elements',
|
||||
text1, 0, br, 0);
|
||||
assertForward('Text nodes should compare to earlier elements',
|
||||
br, 0, text2, 0);
|
||||
assertForward('Parent is before element child', root, 0, br, 0);
|
||||
assertForward('Parent is before text child', root, 0, text1, 0);
|
||||
assertFalse('Equivalent position gives false', goog.dom.Range.isReversed(
|
||||
root, 0, text1, 0));
|
||||
assertFalse('Equivalent position gives false', goog.dom.Range.isReversed(
|
||||
root, 1, br, 0));
|
||||
assertForward('End of element is after children', text1, 0, root, 3);
|
||||
assertForward('End of element is after children', br, 0, root, 3);
|
||||
assertForward('End of element is after children', text2, 0, root, 3);
|
||||
assertForward('End of element is after end of last child',
|
||||
text2, 3, root, 3);
|
||||
}
|
||||
|
||||
function testSelectAroundSpaces() {
|
||||
// set the selection
|
||||
var textNode = goog.dom.getElement('textWithSpaces').firstChild;
|
||||
goog.dom.TextRange.createFromNodes(
|
||||
textNode, 5, textNode, 12).select();
|
||||
|
||||
// get the selection and check that it matches what we set it to
|
||||
var range = goog.dom.Range.createFromWindow();
|
||||
assertEquals(' world ', range.getText());
|
||||
assertEquals(5, range.getStartOffset());
|
||||
assertEquals(12, range.getEndOffset());
|
||||
assertEquals(textNode, range.getContainer());
|
||||
|
||||
// Check the contents again, because there used to be a bug where
|
||||
// it changed after calling getContainer().
|
||||
assertEquals(' world ', range.getText());
|
||||
}
|
||||
|
||||
function testSelectInsideSpaces() {
|
||||
// set the selection
|
||||
var textNode = goog.dom.getElement('textWithSpaces').firstChild;
|
||||
goog.dom.TextRange.createFromNodes(
|
||||
textNode, 6, textNode, 11).select();
|
||||
|
||||
// get the selection and check that it matches what we set it to
|
||||
var range = goog.dom.Range.createFromWindow();
|
||||
assertEquals('world', range.getText());
|
||||
assertEquals(6, range.getStartOffset());
|
||||
assertEquals(11, range.getEndOffset());
|
||||
assertEquals(textNode, range.getContainer());
|
||||
|
||||
// Check the contents again, because there used to be a bug where
|
||||
// it changed after calling getContainer().
|
||||
assertEquals('world', range.getText());
|
||||
}
|
||||
|
||||
function testRangeBeforeBreak() {
|
||||
var container = goog.dom.getElement('rangeAroundBreaks');
|
||||
var text = container.firstChild;
|
||||
var offset = text.length;
|
||||
assertEquals(4, offset);
|
||||
|
||||
var br = container.childNodes[1];
|
||||
var caret = goog.dom.Range.createCaret(text, offset);
|
||||
caret.select();
|
||||
assertEquals(offset, caret.getStartOffset());
|
||||
|
||||
var range = goog.dom.Range.createFromWindow();
|
||||
assertFalse('Should not contain whole <br>',
|
||||
range.containsNode(br, false));
|
||||
if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
|
||||
assertTrue('Range over <br> is adjacent to the immediate range before it',
|
||||
range.containsNode(br, true));
|
||||
} else {
|
||||
assertFalse('Should not contain partial <br>',
|
||||
range.containsNode(br, true));
|
||||
}
|
||||
|
||||
assertEquals(offset, range.getStartOffset());
|
||||
assertEquals(text, range.getStartNode());
|
||||
}
|
||||
|
||||
function testRangeAfterBreak() {
|
||||
var container = goog.dom.getElement('rangeAroundBreaks');
|
||||
var br = container.childNodes[1];
|
||||
var caret = goog.dom.Range.createCaret(container.lastChild, 0);
|
||||
caret.select();
|
||||
assertEquals(0, caret.getStartOffset());
|
||||
|
||||
var range = goog.dom.Range.createFromWindow();
|
||||
assertFalse('Should not contain whole <br>',
|
||||
range.containsNode(br, false));
|
||||
var isSafari3 =
|
||||
goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('528');
|
||||
|
||||
if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) ||
|
||||
isSafari3) {
|
||||
assertTrue('Range over <br> is adjacent to the immediate range after it',
|
||||
range.containsNode(br, true));
|
||||
} else {
|
||||
assertFalse('Should not contain partial <br>',
|
||||
range.containsNode(br, true));
|
||||
}
|
||||
|
||||
if (isSafari3) {
|
||||
assertEquals(2, range.getStartOffset());
|
||||
assertEquals(container, range.getStartNode());
|
||||
} else {
|
||||
assertEquals(0, range.getStartOffset());
|
||||
assertEquals(container.lastChild, range.getStartNode());
|
||||
}
|
||||
}
|
||||
|
||||
function testRangeAtBreakAtStart() {
|
||||
var container = goog.dom.getElement('breaksAroundNode');
|
||||
var br = container.firstChild;
|
||||
var caret = goog.dom.Range.createCaret(container.firstChild, 0);
|
||||
caret.select();
|
||||
assertEquals(0, caret.getStartOffset());
|
||||
|
||||
var range = goog.dom.Range.createFromWindow();
|
||||
assertTrue('Range over <br> is adjacent to the immediate range before it',
|
||||
range.containsNode(br, true));
|
||||
assertFalse('Should not contain whole <br>',
|
||||
range.containsNode(br, false));
|
||||
|
||||
assertRangeEquals(container, 0, container, 0, range);
|
||||
}
|
||||
|
||||
function testFocusedElementDisappears() {
|
||||
// This reproduces a failure case specific to Gecko, where an element is
|
||||
// created, contentEditable is set, is focused, and removed. After that
|
||||
// happens, calling selection.collapse fails.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=773137
|
||||
var disappearingElement = goog.dom.createDom('div');
|
||||
document.body.appendChild(disappearingElement);
|
||||
disappearingElement.contentEditable = true;
|
||||
disappearingElement.focus();
|
||||
document.body.removeChild(disappearingElement);
|
||||
var container = goog.dom.getElement('empty');
|
||||
var caret = goog.dom.Range.createCaret(container, 0);
|
||||
// This should not throw.
|
||||
caret.select();
|
||||
assertEquals(0, caret.getStartOffset());
|
||||
}
|
||||
|
||||
function assertNodeEquals(expected, actual) {
|
||||
assertEquals(
|
||||
'Expected: ' + goog.testing.dom.exposeNode(expected) +
|
||||
'\nActual: ' + goog.testing.dom.exposeNode(actual),
|
||||
expected, actual);
|
||||
}
|
||||
Reference in New Issue
Block a user