mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-07 21:54:29 +00:00
415 lines
16 KiB
HTML
415 lines
16 KiB
HTML
|
<!doctype html>
|
||
|
<html>
|
||
|
<head>
|
||
|
<title>Testing Selection Events</title>
|
||
|
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||
|
</head>
|
||
|
|
||
|
<body>
|
||
|
<div id="normal">
|
||
|
<span id="inner">A bunch of text in a span inside of a div which should be selected</span>
|
||
|
</div>
|
||
|
|
||
|
<div id="ce" contenteditable>
|
||
|
This is a random block of text
|
||
|
</div>
|
||
|
|
||
|
<input type="text" id="input" value="XXXXXXXXXXXXXXXXXXX" width="200"> <br>
|
||
|
|
||
|
<textarea id="textarea" width="200">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</textarea>
|
||
|
|
||
|
<script>
|
||
|
// Call the testing methods from the parent window
|
||
|
var is = parent.is;
|
||
|
var ok = parent.ok;
|
||
|
|
||
|
// spin() spins the event loop for two cycles, giving time for
|
||
|
// selectionchange events to be fired, and handled by our listeners.
|
||
|
function spin() {
|
||
|
return new Promise(function(a) {
|
||
|
parent.SimpleTest.executeSoon(function() {
|
||
|
parent.SimpleTest.executeSoon(a)
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// The main test
|
||
|
parent.add_task(function *() {
|
||
|
yield spin();
|
||
|
|
||
|
var selectstart = 0;
|
||
|
var selectionchange = 0;
|
||
|
var inputSelectionchange = 0;
|
||
|
var textareaSelectionchange = 0;
|
||
|
|
||
|
var cancel = false;
|
||
|
var selectstartTarget = null;
|
||
|
|
||
|
document.addEventListener('selectstart', function(aEvent) {
|
||
|
console.log("originaltarget", aEvent.originalTarget, "new", selectstartTarget);
|
||
|
is(aEvent.originalTarget, selectstartTarget,
|
||
|
"The original target of selectstart");
|
||
|
selectstartTarget = null;
|
||
|
|
||
|
console.log(selectstart);
|
||
|
selectstart++;
|
||
|
|
||
|
if (cancel) {
|
||
|
aEvent.preventDefault();
|
||
|
}
|
||
|
});
|
||
|
document.addEventListener('selectionchange', function(aEvent) {
|
||
|
is(aEvent.originalTarget, document,
|
||
|
"The original target of selectionchange should be the document");
|
||
|
console.log(selectionchange);
|
||
|
selectionchange++;
|
||
|
});
|
||
|
|
||
|
function elt(aId) { return document.getElementById(aId); }
|
||
|
function reset() {
|
||
|
selectstart = 0;
|
||
|
selectionchange = 0;
|
||
|
inputSelectionchange = 0;
|
||
|
textareaSelectionchange = 0;
|
||
|
cancel = false;
|
||
|
}
|
||
|
|
||
|
elt("input").addEventListener('selectionchange', function(aEvent) {
|
||
|
is (aEvent.originalTarget, elt("input"),
|
||
|
"The original target of selectionchange should be the input");
|
||
|
console.log(inputSelectionchange);
|
||
|
inputSelectionchange++;
|
||
|
});
|
||
|
elt("textarea").addEventListener('selectionchange', function(aEvent) {
|
||
|
is (aEvent.originalTarget, elt("textarea"),
|
||
|
"The original target of selectionchange should be the textarea");
|
||
|
console.log(textareaSelectionchange);
|
||
|
textareaSelectionchange++;
|
||
|
});
|
||
|
function* mouseAction(aElement, aOffset, aType,
|
||
|
aSelStart, aSelChng, aISelChng, aTSelChng,
|
||
|
aYOffset)
|
||
|
{
|
||
|
if (aType == "click") { // You can simulate a click event by sending undefined
|
||
|
aType = undefined;
|
||
|
}
|
||
|
if (!aYOffset) {
|
||
|
aYOffset = 10;
|
||
|
}
|
||
|
synthesizeMouse(aElement, aOffset, aYOffset, { type: aType });
|
||
|
yield spin();
|
||
|
|
||
|
is(selectstart, aSelStart,
|
||
|
"SelStart Mouse Action (" + aOffset + " - " + aType + ")");
|
||
|
is(selectionchange, aSelChng,
|
||
|
"SelChng Mouse Action (" + aOffset + " - " + aType + ")");
|
||
|
is(inputSelectionchange, aISelChng || 0,
|
||
|
"ISelChng Mouse Action (" + aOffset + " - " + aType + ")");
|
||
|
is(textareaSelectionchange, aTSelChng || 0,
|
||
|
"TSelChng Mouse Action (" + aOffset + " - " + aType + ")");
|
||
|
reset();
|
||
|
}
|
||
|
|
||
|
function* keyAction(aKey, aShift, aAccel,
|
||
|
aSelStart, aSelChng, aISelChng, aTSelChng)
|
||
|
{
|
||
|
synthesizeKey(aKey, { shiftKey: aShift, accelKey: aAccel });
|
||
|
yield spin();
|
||
|
is(selectstart, aSelStart,
|
||
|
"SelStart Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
|
||
|
is(selectionchange, aSelChng,
|
||
|
"SelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
|
||
|
is(inputSelectionchange, aISelChng || 0,
|
||
|
"ISelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
|
||
|
is(textareaSelectionchange, aTSelChng || 0,
|
||
|
"TSelChng Key Action (" + aKey + " - " + aShift + " - " + aAccel + ")");
|
||
|
reset();
|
||
|
}
|
||
|
|
||
|
var selection = document.getSelection();
|
||
|
function isCollapsed() {
|
||
|
is(selection.isCollapsed, true, "Selection is collapsed");
|
||
|
}
|
||
|
function isNotCollapsed() {
|
||
|
is(selection.isCollapsed, false, "Selection is not collapsed");
|
||
|
}
|
||
|
|
||
|
// Focus the contenteditable text
|
||
|
yield* mouseAction(elt("ce"), 100, "click", 0, 1);
|
||
|
isCollapsed();
|
||
|
|
||
|
// Move the selection to the right, this should only fire selectstart once
|
||
|
selectstartTarget = elt("ce").firstChild;
|
||
|
yield* keyAction("VK_RIGHT", true, false, 1, 1);
|
||
|
isNotCollapsed();
|
||
|
yield* keyAction("VK_RIGHT", true, false, 0, 1);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// Move it back so that the selection is empty again
|
||
|
yield* keyAction("VK_LEFT", true, false, 0, 1);
|
||
|
isNotCollapsed();
|
||
|
yield* keyAction("VK_LEFT", true, false, 0, 1);
|
||
|
isCollapsed();
|
||
|
|
||
|
// Going from empty to non-empty should fire selectstart again
|
||
|
selectstartTarget = elt("ce").firstChild;
|
||
|
yield* keyAction("VK_LEFT", true, false, 1, 1);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
function* mouseMoves(aElement, aTarget) {
|
||
|
// Select a region
|
||
|
yield* mouseAction(aElement, 50, "mousedown", 0, 1);
|
||
|
isCollapsed();
|
||
|
|
||
|
selectstartTarget = aTarget;
|
||
|
yield* mouseAction(aElement, 100, "mousemove", 1, 1);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// Moving it more shouldn't trigger a start (move back to empty)
|
||
|
yield* mouseAction(aElement, 75, "mousemove", 0, 1);
|
||
|
isNotCollapsed();
|
||
|
yield* mouseAction(aElement, 50, "mousemove", 0, 1);
|
||
|
isCollapsed();
|
||
|
|
||
|
// Wiggling the mouse a little such that it doesn't select any
|
||
|
// characters shouldn't trigger a selection
|
||
|
yield* mouseAction(aElement, 50, "mousemove", 0, 0, 0, 0, 11);
|
||
|
isCollapsed();
|
||
|
|
||
|
// Moving the mouse again from an empty selection should trigger a
|
||
|
// selectstart
|
||
|
selectstartTarget = aTarget;
|
||
|
yield* mouseAction(aElement, 25, "mousemove", 1, 1);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// Releasing the mouse shouldn't do anything
|
||
|
yield* mouseAction(aElement, 25, "mouseup", 0, 0);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// And neither should moving your mouse around when the mouse
|
||
|
// button isn't pressed
|
||
|
yield* mouseAction(aElement, 50, "mousemove", 0, 0);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// Clicking in an random location should move the selection, but not perform a
|
||
|
// selectstart
|
||
|
yield* mouseAction(aElement, 50, "click", 0, 1);
|
||
|
isCollapsed();
|
||
|
|
||
|
// Clicking there again should do nothing
|
||
|
yield* mouseAction(aElement, 50, "click", 0, 0);
|
||
|
isCollapsed();
|
||
|
|
||
|
// Selecting a region, and canceling the selectstart should mean that the
|
||
|
// selection remains collapsed
|
||
|
yield* mouseAction(aElement, 75, "mousedown", 0, 1);
|
||
|
isCollapsed();
|
||
|
cancel = true;
|
||
|
selectstartTarget = aTarget;
|
||
|
yield* mouseAction(aElement, 100, "mousemove", 1, 1);
|
||
|
isCollapsed();
|
||
|
yield* mouseAction(aElement, 100, "mouseup", 0, 0);
|
||
|
isCollapsed();
|
||
|
}
|
||
|
|
||
|
// Should work both on normal
|
||
|
yield* mouseMoves(elt("inner"), elt("inner").firstChild);
|
||
|
// and contenteditable fields
|
||
|
yield* mouseMoves(elt("ce"), elt("ce").firstChild);
|
||
|
// and fields with elements in them
|
||
|
yield* mouseMoves(elt("normal"), elt("inner").firstChild);
|
||
|
|
||
|
yield* mouseAction(elt("inner"), 50, "click", 0, 1);
|
||
|
isCollapsed();
|
||
|
|
||
|
reset();
|
||
|
// Select all should fire both selectstart and change
|
||
|
selectstartTarget = document.body;
|
||
|
yield* keyAction("A", false, true, 1, 1);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// Clear the selection
|
||
|
yield* mouseAction(elt("inner"), 50, "click", 0, 1);
|
||
|
isCollapsed();
|
||
|
|
||
|
// Even if we already have a selection
|
||
|
yield* mouseAction(elt("inner"), 75, "mousedown", 0, 1);
|
||
|
isCollapsed();
|
||
|
selectstartTarget = elt("inner").firstChild;
|
||
|
yield* mouseAction(elt("inner"), 100, "mousemove", 1, 1);
|
||
|
isNotCollapsed();
|
||
|
yield* mouseAction(elt("inner"), 100, "mouseup", 0, 0);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
selectstartTarget = document.body;
|
||
|
yield* keyAction("A", false, true, 1, 1);
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// Clear the selection
|
||
|
yield* mouseAction(elt("inner"), 50, "click", 0, 1);
|
||
|
isCollapsed();
|
||
|
|
||
|
// Make sure that a synthesized selection change doesn't fire selectstart
|
||
|
var s = document.getSelection();
|
||
|
s.removeAllRanges();
|
||
|
yield spin();
|
||
|
is(selectstart, 0, "Synthesized range removals shouldn't fire selectstart");
|
||
|
is(selectionchange, 1, "Synthesized range removals should change selectionchange");
|
||
|
reset();
|
||
|
isCollapsed();
|
||
|
|
||
|
var range = document.createRange();
|
||
|
range.selectNode(elt("inner"));
|
||
|
s.addRange(range);
|
||
|
yield spin();
|
||
|
is(selectstart, 0, "Synthesized range additions shouldn't fire selectstart");
|
||
|
is(selectionchange, 1, "Synthesized range additions should change selectionchange");
|
||
|
reset();
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// Change the range, without replacing
|
||
|
range.selectNode(elt("ce"));
|
||
|
yield spin();
|
||
|
is(selectstart, 0, "Synthesized range mutations shouldn't fire selectstart");
|
||
|
is(selectionchange, 1, "Synthesized range mutations should change selectionchange");
|
||
|
reset();
|
||
|
isNotCollapsed();
|
||
|
|
||
|
// Remove the range
|
||
|
s.removeAllRanges();
|
||
|
yield spin();
|
||
|
is(selectstart, 0, "Synthesized range removal");
|
||
|
is(selectionchange, 1, "Synthesized range removal");
|
||
|
reset();
|
||
|
isCollapsed();
|
||
|
|
||
|
|
||
|
/*
|
||
|
Selection events mouse move on input type=text
|
||
|
*/
|
||
|
|
||
|
// Select a region
|
||
|
|
||
|
yield* mouseAction(elt("input"), 50, "mousedown", 0, 1, 1, 0);
|
||
|
|
||
|
selectstartTarget = elt("input");
|
||
|
yield* mouseAction(elt("input"), 100, "mousemove", 1, 0, 1, 0);
|
||
|
|
||
|
// Moving it more shouldn't trigger a start (move back to empty)
|
||
|
yield* mouseAction(elt("input"), 75, "mousemove", 0, 0, 1, 0);
|
||
|
yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 1, 0);
|
||
|
|
||
|
// Wiggling the mouse a little such that it doesn't select any
|
||
|
// characters shouldn't trigger a selection
|
||
|
yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 0, 0, 11);
|
||
|
|
||
|
// Moving the mouse again from an empty selection should trigger a
|
||
|
// selectstart
|
||
|
selectstartTarget = elt("input");
|
||
|
yield* mouseAction(elt("input"), 25, "mousemove", 1, 0, 1, 0);
|
||
|
|
||
|
// Releasing the mouse shouldn't do anything
|
||
|
yield* mouseAction(elt("input"), 25, "mouseup", 0, 0, 0, 0);
|
||
|
|
||
|
// And neither should moving your mouse around when the mouse
|
||
|
// button isn't pressed
|
||
|
yield* mouseAction(elt("input"), 50, "mousemove", 0, 0, 0, 0);
|
||
|
|
||
|
// Clicking in an random location should move the selection, but
|
||
|
// not perform a selectstart
|
||
|
yield* mouseAction(elt("input"), 50, "click", 0, 0, 1, 0);
|
||
|
|
||
|
// Clicking there again should do nothing
|
||
|
yield* mouseAction(elt("input"), 50, "click", 0, 0, 0, 0);
|
||
|
|
||
|
// Selecting a region, and canceling the selectstart should mean that the
|
||
|
// selection remains collapsed
|
||
|
yield* mouseAction(elt("input"), 75, "mousedown", 0, 0, 1, 0);
|
||
|
cancel = true;
|
||
|
selectstartTarget = elt("input");
|
||
|
yield* mouseAction(elt("input"), 100, "mousemove", 1, 0, 1, 0);
|
||
|
yield* mouseAction(elt("input"), 100, "mouseup", 0, 0, 0, 0);
|
||
|
|
||
|
|
||
|
// Select a region
|
||
|
// XXX For some reason we fire 2 selectchange events on the body
|
||
|
// when switching from the input to the text area.
|
||
|
yield* mouseAction(elt("textarea"), 50, "mousedown", 0, 2, 0, 1);
|
||
|
|
||
|
selectstartTarget = elt("textarea");
|
||
|
yield* mouseAction(elt("textarea"), 100, "mousemove", 1, 0, 0, 1);
|
||
|
|
||
|
// Moving it more shouldn't trigger a start (move back to empty)
|
||
|
yield* mouseAction(elt("textarea"), 75, "mousemove", 0, 0, 0, 1);
|
||
|
yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 1);
|
||
|
|
||
|
// Wiggling the mouse a little such that it doesn't select any
|
||
|
// characters shouldn't trigger a selection
|
||
|
yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 0, 11);
|
||
|
|
||
|
// Moving the mouse again from an empty selection should trigger a
|
||
|
// selectstart
|
||
|
selectstartTarget = elt("textarea");
|
||
|
yield* mouseAction(elt("textarea"), 25, "mousemove", 1, 0, 0, 1);
|
||
|
|
||
|
// Releasing the mouse shouldn't do anything
|
||
|
yield* mouseAction(elt("textarea"), 25, "mouseup", 0, 0, 0, 0);
|
||
|
|
||
|
// And neither should moving your mouse around when the mouse
|
||
|
// button isn't pressed
|
||
|
yield* mouseAction(elt("textarea"), 50, "mousemove", 0, 0, 0, 0);
|
||
|
|
||
|
// Clicking in an random location should move the selection, but not perform a
|
||
|
// selectstart
|
||
|
yield* mouseAction(elt("textarea"), 50, "click", 0, 0, 0, 1);
|
||
|
|
||
|
// Clicking there again should do nothing
|
||
|
yield* mouseAction(elt("textarea"), 50, "click", 0, 0, 0, 0);
|
||
|
|
||
|
// Selecting a region, and canceling the selectstart should mean that the
|
||
|
// selection remains collapsed
|
||
|
yield* mouseAction(elt("textarea"), 75, "mousedown", 0, 0, 0, 1);
|
||
|
cancel = true;
|
||
|
selectstartTarget = elt("textarea");
|
||
|
yield* mouseAction(elt("textarea"), 100, "mousemove", 1, 0, 0, 1);
|
||
|
yield* mouseAction(elt("textarea"), 100, "mouseup", 0, 0, 0, 0);
|
||
|
|
||
|
// Marking the input and textarea as display: none and then as visible again
|
||
|
// shouldn't trigger any changes, although the nodes will be re-framed
|
||
|
elt("input").setAttribute("style", "display: none;");
|
||
|
yield spin();
|
||
|
is(selectstart, 0, "idn - ss 1");
|
||
|
is(selectionchange, 0, "idn - sc 1");
|
||
|
is(inputSelectionchange, 0, "idn - isc 1");
|
||
|
is(textareaSelectionchange, 0, "idn - tsc 1");
|
||
|
reset();
|
||
|
|
||
|
elt("input").setAttribute("style", "");
|
||
|
yield spin();
|
||
|
is(selectstart, 0, "idn - ss 2");
|
||
|
is(selectionchange, 0, "idn - sc 2");
|
||
|
is(inputSelectionchange, 0, "idn - isc 2");
|
||
|
is(textareaSelectionchange, 0, "idn - tsc 2");
|
||
|
reset();
|
||
|
|
||
|
elt("textarea").setAttribute("style", "display: none;");
|
||
|
yield spin();
|
||
|
is(selectstart, 0, "tdn - ss 1");
|
||
|
is(selectionchange, 0, "tdn - sc 1");
|
||
|
is(inputSelectionchange, 0, "tdn - isc 1");
|
||
|
is(textareaSelectionchange, 0, "tdn - tsc 1");
|
||
|
reset();
|
||
|
|
||
|
elt("textarea").setAttribute("style", "");
|
||
|
yield spin();
|
||
|
is(selectstart, 0, "tdn - ss 2");
|
||
|
is(selectionchange, 0, "tdn - sc 2");
|
||
|
is(inputSelectionchange, 0, "tdn - isc 2");
|
||
|
is(textareaSelectionchange, 0, "tdn - tsc 2");
|
||
|
reset();
|
||
|
});
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|