123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752 |
- // 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(goog.dom.TagName.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');
- goog.dom.setTextContent(div, '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(goog.dom.TagName.SPAN),
- goog.dom.createDom(goog.dom.TagName.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');
- goog.dom.setTextContent(outer, '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);
- goog.dom.setTextContent(outer, '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');
- goog.dom.setTextContent(outer, '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);
- goog.dom.setTextContent(outer, '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');
- goog.dom.setTextContent(outer, '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());
- goog.dom.setTextContent(outer, '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() {
- if (goog.userAgent.EDGE_OR_IE) return; // IE doesn't make this distinction.
- 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', 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(goog.dom.TagName.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);
- }
|