Problem
I need to detect selected text based on mouse events. I also need to detect when current selection disappears. My next code works fine for situation when you selecting something and deselecting this by clicking outside of selection. But this code doesn't works when you want to deselect by clicking on selected text.
Please test next code to see what i mean.
Environment
How to reproduce
let mousePressed = false;
document.addEventListener('mousedown', () => {
mousePressed = true;
});
document.addEventListener('mouseup', () => {
if (mousePressed) {
const selection = window.getSelection();
const isCollapsed = selection.isCollapsed;
console.log(`Collapsed: ${isCollapsed}`);
mousePressed = false;
}
});
false
, true
.true
. Actual selection will disappear.false
. But actual selection will disappear.What happened
Notice difference between № 4 and № 6. Both of them leads to same result: selection will disappear. But with one difference: № 4 will correctly point on that selection is collapsed, but № 6 will treat disappeared selection as not collapsed. It is means that window.getSelection()
will provide disappeared selection, even if there are no actual visible selection.
It is happened in both browsers: Google Chrome and Mozilla Firefox.
How to test wrong order of events
Perform all these steps with a little bit different code:
let mousePressed = false;
document.addEventListener('mousedown', () => {
mousePressed = true;
});
document.addEventListener('mouseup', () => {
if (mousePressed) {
window.setTimeout(() => {
const selection = window.getSelection();
const isCollapsed = selection.isCollapsed;
console.log(`Collapsed: ${isCollapsed}`);
}, 1000);
mousePressed = false;
}
});
It is same, but now window.getSelection()
will be called with delay. And now № 6 yields expected result: true
.
Why it is happened
I do not know. I think there is something with events order for different situations. With situation № 4 order yields expected result. With situation № 6 probably order of events is different, and that order yields not expected result.
What I'm asking for
There is something wrong with my code? Or it is a bug that should be reported on Chromium and Bugzilla? Or it is actually expected behavior?
I mean, i need to achieve same result (Collapsed: true
) for both № 4 and № 6.
The problem was solved using this pattern:
let mousePressed = false;
document.addEventListener('mousedown', () => {
mousePressed = true;
});
document.addEventListener('mouseup', () => {
if (mousePressed) {
window.setTimeout(() => {
const selection = window.getSelection();
const isCollapsed = selection.isCollapsed;
console.log(`Collapsed: ${isCollapsed}`);
}, 0);
mousePressed = false;
}
});
i.e., timer with 0 ms delay.
Now both № 4 and № 6 are handled correctly.
But i'm still not sure if it is right way to handle such situations. Maybe there is something wrong with code, maybe there is bug in both browsers.