blob: d0465b9bbe81e5dd95a3eeb70c09ffc97ac0e976 [file] [log] [blame]
// Copyright 2008 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.TextRangeTest');
goog.setTestOnly('goog.dom.TextRangeTest');
goog.require('goog.dom');
goog.require('goog.dom.ControlRange');
goog.require('goog.dom.Range');
goog.require('goog.dom.TextRange');
goog.require('goog.math.Coordinate');
goog.require('goog.style');
goog.require('goog.testing.ExpectedFailures');
goog.require('goog.testing.jsunit');
goog.require('goog.userAgent');
var logo;
var logo2;
var logo3;
var logo3Rtl;
var table;
var table2;
var table2div;
var test3;
var test3Rtl;
var expectedFailures;
function setUpPage() {
logo = goog.dom.getElement('logo');
logo2 = goog.dom.getElement('logo2');
logo3 = goog.dom.getElement('logo3');
logo3Rtl = goog.dom.getElement('logo3Rtl');
table = goog.dom.getElement('table');
table2 = goog.dom.getElement('table2');
table2div = goog.dom.getElement('table2div');
test3 = goog.dom.getElement('test3');
test3Rtl = goog.dom.getElement('test3Rtl');
expectedFailures = new goog.testing.ExpectedFailures();
}
function tearDown() {
expectedFailures.handleTearDown();
}
function testCreateFromNodeContents() {
assertNotNull('Text range object can be created for element node',
goog.dom.TextRange.createFromNodeContents(logo));
assertNotNull('Text range object can be created for text node',
goog.dom.TextRange.createFromNodeContents(logo2.previousSibling));
}
function testMoveToNodes() {
var range = goog.dom.TextRange.createFromNodeContents(table2);
range.moveToNodes(table2div, 0, table2div, 1, false);
assertEquals('Range should start in table2div',
table2div,
range.getStartNode());
assertEquals('Range should end in table2div',
table2div,
range.getEndNode());
assertEquals('Range start offset should be 0',
0,
range.getStartOffset());
assertEquals('Range end offset should be 0',
1,
range.getEndOffset());
assertFalse('Range should not be reversed',
range.isReversed());
range.moveToNodes(table2div, 0, table2div, 1, true);
assertTrue('Range should be reversed',
range.isReversed());
assertEquals('Range text should be "foo"',
'foo',
range.getText());
}
function testContainsTextRange() {
var range = goog.dom.TextRange.createFromNodeContents(table2);
var range2 = goog.dom.TextRange.createFromNodeContents(table2div);
assertTrue('TextRange contains other TextRange',
range.containsRange(range2));
assertFalse('TextRange does not contain other TextRange',
range2.containsRange(range));
range = goog.dom.Range.createFromNodes(
table2div.firstChild, 1, table2div.lastChild, 1);
range2 = goog.dom.TextRange.createFromNodes(
table2div.firstChild, 0, table2div.lastChild, 0);
assertTrue('TextRange partially contains other TextRange',
range2.containsRange(range, true));
assertFalse('TextRange does not fully contain other TextRange',
range2.containsRange(range, false));
}
function testContainsControlRange() {
if (goog.userAgent.IE) {
var range = goog.dom.ControlRange.createFromElements(table2);
var range2 = goog.dom.TextRange.createFromNodeContents(table2div);
assertFalse('TextRange does not contain ControlRange',
range2.containsRange(range));
range = goog.dom.ControlRange.createFromElements(logo2);
assertTrue('TextRange contains ControlRange',
range2.containsRange(range));
range = goog.dom.TextRange.createFromNodeContents(table2);
range2 = goog.dom.ControlRange.createFromElements(logo, logo2);
assertTrue('TextRange partially contains ControlRange',
range2.containsRange(range, true));
assertFalse('TextRange does not fully contain ControlRange',
range2.containsRange(range, false));
}
}
function testGetStartPosition() {
expectedFailures.expectFailureFor(goog.userAgent.GECKO &&
!goog.userAgent.isVersionOrHigher('2'));
// The start node is in the top left.
var range = goog.dom.TextRange.createFromNodeContents(test3);
var topLeft = goog.style.getPageOffset(test3.firstChild);
if (goog.userAgent.IE) {
// On IE the selection is as tall as its tallest element.
var logoPosition = goog.style.getPageOffset(logo3);
topLeft.y = logoPosition.y;
if (!goog.userAgent.isVersionOrHigher('8')) {
topLeft.x += 2;
topLeft.y += 2;
}
}
try {
var result = assertNotThrows(goog.bind(range.getStartPosition, range));
assertObjectEquals(topLeft, result);
} catch (e) {
expectedFailures.handleException(e);
}
}
function testGetStartPositionNotInDocument() {
expectedFailures.expectFailureFor(goog.userAgent.GECKO &&
!goog.userAgent.isVersionOrHigher('2'));
expectedFailures.expectFailureFor(goog.userAgent.IE &&
!goog.userAgent.isVersionOrHigher('8'));
var range = goog.dom.TextRange.createFromNodeContents(test3);
goog.dom.removeNode(test3);
try {
var result = assertNotThrows(goog.bind(range.getStartPosition, range));
assertNull(result);
} catch (e) {
expectedFailures.handleException(e);
} finally {
goog.dom.appendChild(document.body, test3);
}
}
function testGetStartPositionReversed() {
expectedFailures.expectFailureFor(goog.userAgent.GECKO &&
!goog.userAgent.isVersionOrHigher('2'));
// Simulate the user selecting backwards from right-to-left.
// The start node is now in the bottom right.
var firstNode = test3.firstChild.firstChild;
var lastNode = test3.lastChild.lastChild;
var range = goog.dom.TextRange.createFromNodes(
lastNode, lastNode.nodeValue.length, firstNode, 0);
var pageOffset = goog.style.getPageOffset(test3.lastChild);
var bottomRight = new goog.math.Coordinate(
pageOffset.x + test3.lastChild.offsetWidth,
pageOffset.y + test3.lastChild.offsetHeight);
if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) {
bottomRight.x += 2;
bottomRight.y += 2;
}
try {
var result = assertNotThrows(goog.bind(range.getStartPosition, range));
assertObjectRoughlyEquals(bottomRight, result, 1);
} catch (e) {
expectedFailures.handleException(e);
}
}
function testGetStartPositionRightToLeft() {
expectedFailures.expectFailureFor(goog.userAgent.GECKO &&
!goog.userAgent.isVersionOrHigher('2'));
// Even in RTL content the start node is still in the top left.
var range = goog.dom.TextRange.createFromNodeContents(test3Rtl);
var topLeft = goog.style.getPageOffset(test3Rtl.firstChild);
if (goog.userAgent.IE) {
// On IE the selection is as tall as its tallest element.
var logoPosition = goog.style.getPageOffset(logo3Rtl);
topLeft.y = logoPosition.y;
if (!goog.userAgent.isVersionOrHigher('8')) {
topLeft.x += 2;
topLeft.y += 2;
}
}
try {
var result = assertNotThrows(goog.bind(range.getStartPosition, range));
assertObjectRoughlyEquals(topLeft, result, 0.1);
} catch (e) {
expectedFailures.handleException(e);
}
}
function testGetEndPosition() {
expectedFailures.expectFailureFor(goog.userAgent.GECKO &&
!goog.userAgent.isVersionOrHigher('2'));
// The end node is in the bottom right.
var range = goog.dom.TextRange.createFromNodeContents(test3);
var pageOffset = goog.style.getPageOffset(test3.lastChild);
var bottomRight = new goog.math.Coordinate(
pageOffset.x + test3.lastChild.offsetWidth,
pageOffset.y + test3.lastChild.offsetHeight);
if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) {
bottomRight.x += 6;
bottomRight.y += 2;
}
try {
var result = assertNotThrows(goog.bind(range.getEndPosition, range));
assertObjectRoughlyEquals(bottomRight, result, 1);
} catch (e) {
expectedFailures.handleException(e);
}
}
function testGetEndPositionNotInDocument() {
expectedFailures.expectFailureFor(goog.userAgent.GECKO &&
!goog.userAgent.isVersionOrHigher('2'));
expectedFailures.expectFailureFor(goog.userAgent.IE &&
!goog.userAgent.isVersionOrHigher('8'));
var range = goog.dom.TextRange.createFromNodeContents(test3);
goog.dom.removeNode(test3);
try {
var result = assertNotThrows(goog.bind(range.getEndPosition, range));
assertNull(result);
} catch (e) {
expectedFailures.handleException(e);
} finally {
goog.dom.appendChild(document.body, test3);
}
}
function testGetEndPositionReversed() {
expectedFailures.expectFailureFor(goog.userAgent.GECKO &&
!goog.userAgent.isVersionOrHigher('2'));
// Simulate the user selecting backwards from right-to-left.
// The end node is now in the top left.
var firstNode = test3.firstChild.firstChild;
var lastNode = test3.lastChild.lastChild;
var range = goog.dom.TextRange.createFromNodes(
lastNode, lastNode.nodeValue.length, firstNode, 0);
var topLeft = goog.style.getPageOffset(test3.firstChild);
if (goog.userAgent.IE) {
// On IE the selection is as tall as its tallest element.
var logoPosition = goog.style.getPageOffset(logo3);
topLeft.y = logoPosition.y;
if (!goog.userAgent.isVersionOrHigher('8')) {
topLeft.x += 2;
topLeft.y += 2;
}
}
try {
var result = assertNotThrows(goog.bind(range.getEndPosition, range));
assertObjectEquals(topLeft, result);
} catch (e) {
expectedFailures.handleException(e);
}
}
function testGetEndPositionRightToLeft() {
expectedFailures.expectFailureFor(goog.userAgent.GECKO &&
!goog.userAgent.isVersionOrHigher('2'));
expectedFailures.expectFailureFor(goog.userAgent.IE &&
!goog.userAgent.isVersionOrHigher('8'));
// Even in RTL content the end node is still in the bottom right.
var range = goog.dom.TextRange.createFromNodeContents(test3Rtl);
var pageOffset = goog.style.getPageOffset(test3Rtl.lastChild);
var bottomRight = new goog.math.Coordinate(
pageOffset.x + test3Rtl.lastChild.offsetWidth,
pageOffset.y + test3Rtl.lastChild.offsetHeight);
if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) {
bottomRight.x += 2;
bottomRight.y += 2;
}
try {
var result = assertNotThrows(goog.bind(range.getEndPosition, range));
assertObjectRoughlyEquals(bottomRight, result, 1);
} catch (e) {
expectedFailures.handleException(e);
}
}
function testCloneRangeDeep() {
var range = goog.dom.TextRange.createFromNodeContents(logo);
assertFalse(range.isCollapsed());
var cloned = range.clone();
cloned.collapse();
assertTrue(cloned.isCollapsed());
assertFalse(range.isCollapsed());
}