Skip to content

Commit

Permalink
Trigger selectionchange event on document when selection changes
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-oles committed Jan 29, 2024
1 parent 2f8a730 commit c3b9331
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
14 changes: 13 additions & 1 deletion lib/jsdom/living/selection/Selection-impl.js
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit c3b9331

Please sign in to comment.