Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger selectionchange event on document when selection changes (small change - 2 files) #3676

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 13 additions & 1 deletion lib/jsdom/living/selection/Selection-impl.js
Expand Up @@ -11,6 +11,7 @@ const { setBoundaryPointStart, setBoundaryPointEnd } = require("../range/Range-i

const Range = require("../generated/Range");
const { implForWrapper } = require("../generated/utils");
const { fireAnEvent } = require("../helpers/events");

// https://w3c.github.io/selection-api/#dfn-direction
const SELECTION_DIRECTION = {
Expand Down Expand Up @@ -329,11 +330,22 @@ class SelectionImpl {
}

_associateRange(newRange) {
const didSelectionChange = this._range !== newRange &&
(
// Change from/to null selection
newRange === null ||
this._range === null ||
// Change of selection range
compareBoundaryPointsPosition(newRange._start, this._range._start) !== 0 ||
compareBoundaryPointsPosition(newRange._end, this._range._end) !== 0
);
this._range = newRange;
this._direction = newRange === null ? SELECTION_DIRECTION.DIRECTIONLESS : SELECTION_DIRECTION.FORWARDS;

// TODO: Emit "selectionchange" event. At this time, there is currently no test in WPT covering this.
// https://w3c.github.io/selection-api/#selectionchange-event
if (didSelectionChange) {
fireAnEvent("selectionchange", implForWrapper(this._globalObject._document));
}
}
}

Expand Down
@@ -0,0 +1,91 @@
<!DOCTYPE HTML>
<title>selectionchange event on document</title>
<link rel="author" title="Piotr Oleś" href="mailto:piotrek.oles@gmail.com">
<link rel="help" href="https://w3c.github.io/selection-api/#selectionchange-event">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<div id="example">test <span>nested</span></div>

<script>
"use strict";

test(t => {
let events = 0;
document.addEventListener("selectionchange", () => {
events++;
});
const target = document.getElementById("example");
const selection = document.getSelection();
selection.setBaseAndExtent(target, 0, target, 1);
assert_equals(events, 1, "Should be 1 event");
selection.setBaseAndExtent(target, 0, target, 1);
assert_equals(events, 1, "Should be 1 event because we called setBaseAndExtent with the same arguments");
selection.setBaseAndExtent(target, 0, target, 2);
assert_equals(events, 2, "Should be 2 events");
t.add_cleanup(() => selection.removeAllRanges());
}, `triggers selectionchange event on setBaseAndExtent`);

test(t => {
let events = 0;
document.addEventListener("selectionchange", () => {
events++;
});
const target = document.getElementById("example");
const selection = document.getSelection();
selection.selectAllChildren(target);
assert_equals(events, 1, "Should be 1 event");
selection.selectAllChildren(target);
assert_equals(events, 1, "Should be 1 event because we called selectAllChildren with the same arguments");
t.add_cleanup(() => selection.removeAllRanges());
}, `triggers selectionchange event on selectAllChildren`);

test(t => {
let events = 0;
document.addEventListener("selectionchange", () => {
events++;
});
const target = document.getElementById("example");
const selection = document.getSelection();
selection.selectAllChildren(target);
assert_equals(events, 1, "Should be 1 event");
selection.removeAllRanges();
assert_equals(events, 2, "Should be 2 events");
selection.removeAllRanges();
assert_equals(events, 2, "Should be 2 events because we called removeAllRanges with the same arguments");
t.add_cleanup(() => selection.removeAllRanges());
}, `triggers selectionchange event on removeAllRanges`);

test(t => {
let events = 0;
document.addEventListener("selectionchange", () => {
events++;
});
const target = document.getElementById("example");
const selection = document.getSelection();
selection.setBaseAndExtent(target, 0, target, 1);
assert_equals(events, 1, "Should be 1 event");
selection.collapseToStart();
assert_equals(events, 2, "Should be 2 events");
selection.collapseToStart();
assert_equals(events, 2, "Should be 2 events because we called collapseToStart with the same arguments");
t.add_cleanup(() => selection.removeAllRanges());
}, `triggers selectionchange event on collapseToStart`);

test(t => {
let events = 0;
document.addEventListener("selectionchange", () => {
events++;
});
const target = document.getElementById("example");
const selection = document.getSelection();
selection.setBaseAndExtent(target, 0, target, 1);
assert_equals(events, 1, "Should be 1 event");
selection.collapseToEnd();
assert_equals(events, 2, "Should be 2 events");
selection.collapseToEnd();
assert_equals(events, 2, "Should be 2 events because we called collapseToEnd with the same arguments");
t.add_cleanup(() => selection.removeAllRanges());
}, `triggers selectionchange event on collapseToEnd`);
</script>