Closed
Bug 1060579
Opened 11 years ago
Closed 11 years ago
nsISelectionPrivate doesn't fire selection listener event when manipulating contenteditable from JS
Categories
(Core :: DOM: Selection, defect)
Tracking
()
RESOLVED
WONTFIX
People
(Reporter: janjongboom, Assigned: janjongboom)
Details
We have a selection listener in forms.js (https://github.com/mozilla/gecko-dev/blob/master/dom/inputmethod/forms.js#L287). This works fine on contenteditable elements when moving the cursor around. However... There is no event fired when manipulating the innerHTML of the contenteditable from content process where the cursor position actually changes. E.g.:
<div id="text" contenteditable>Some text</div>
Then set the cursor to end of the div w/ JavaScript:
var t = document.querySelector('#text');
t.focus();
var range = document.createRange();
range.selectNodeContents(t);
range.collapse(false);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
This works fine, I get notifySelectionChanged. Now we clear out the contenteditable via:
setTimeout(function() {
var t = document.getElementById('text');
t.innerHTML = '';
}, 20);
And now I don't get any event :-(
Assignee | ||
Comment 1•11 years ago
|
||
Ehsan, you were one of the last ones to touch the interface, you know which component this should be under?
Flags: needinfo?(ehsan.akhgari)
Comment 2•11 years ago
|
||
Why do you expect to get a selection change event in the test case in comment 0? The selection is not changed when you set the innerHTML to an empty string...
Flags: needinfo?(ehsan.akhgari) → needinfo?(janjongboom)
Assignee | ||
Comment 3•11 years ago
|
||
(In reply to :Ehsan Akhgari (not reading bugmail, needinfo? me!) from comment #2)
> Why do you expect to get a selection change event in the test case in
> comment 0? The selection is not changed when you set the innerHTML to an
> empty string...
It is, the cursor was at position [9, 9], and after the innerHTML change it is at [0, 0].
Flags: needinfo?(janjongboom) → needinfo?(ehsan.akhgari)
Comment 5•11 years ago
|
||
(In reply to Jan Jongboom [:janjongboom] (Telenor) from comment #3)
> (In reply to :Ehsan Akhgari (not reading bugmail, needinfo? me!) from
> comment #2)
> > Why do you expect to get a selection change event in the test case in
> > comment 0? The selection is not changed when you set the innerHTML to an
> > empty string...
>
> It is, the cursor was at position [9, 9], and after the innerHTML change it
> is at [0, 0].
When I said the selection is not modified, I meant its ranges are not changed. It is entirely possible for a selection's ranges to be changed under its nose when the content within those ranges mutates, which is what you are seeing here. We have never dispatched any kind of selection change notification for that case AFAIK.
Component: Editor → Selection
Flags: needinfo?(ehsan.akhgari)
Comment 6•11 years ago
|
||
So, I think what we can do here is to extend nsRange::SetInSelection to take a mozilla::dom::Selection* pointer, store that within the range so that the range knows what selection it is associated with, and then inside the nsRange mutation observers, notify the selection object of a change to the range if it is in a selection.
This worries me a little bit since that this changes the semantics of the selection listeners, by dispatching events on them where we would not before. I think that is fine though. Olli, what do you think?
Flags: needinfo?(bugs)
Comment 7•11 years ago
|
||
Or, we could expose these notifications through a new API if that is better...
Comment 8•11 years ago
|
||
I think comment 6 should be fine, especially if we notify selection listeners using script runners.
Flags: needinfo?(bugs)
Comment 9•11 years ago
|
||
(In reply to :Ehsan Akhgari (not reading bugmail, needinfo? me!) from comment #6)
> So, I think what we can do here is to extend nsRange::SetInSelection to take
> a mozilla::dom::Selection* pointer, store that within the range so that the
> range knows what selection it is associated with, and then inside the
> nsRange mutation observers, notify the selection object of a change to the
> range if it is in a selection.
I fear that this would be complex, brittle and slow.
Comment 10•11 years ago
|
||
If the use case is to observe DOM mutations under a single node -
why not use a MutationObserver?
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
Flags: needinfo?(janjongboom)
Assignee | ||
Comment 11•11 years ago
|
||
(In reply to Mats Palmgren (:mats) from comment #10)
> If the use case is to observe DOM mutations under a single node -
> why not use a MutationObserver?
> https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
Because I think that would be the wrong way to fix this. We can create exceptions and handlers for everything like we had in the past, but it's going to break or have weird edge cases or something will break. That's why we abandoned our home grown solution for nsISelectionPrivate instead in bug 1026997. If we can't rely on this API to give us correct events whenever the cursor position changes I believe it's a bug.
Flags: needinfo?(janjongboom) → needinfo?(mats)
Comment 12•11 years ago
|
||
(In reply to Mats Palmgren (:mats) from comment #9)
> (In reply to :Ehsan Akhgari (not reading bugmail, needinfo? me!) from
> comment #6)
> > So, I think what we can do here is to extend nsRange::SetInSelection to take
> > a mozilla::dom::Selection* pointer, store that within the range so that the
> > range knows what selection it is associated with, and then inside the
> > nsRange mutation observers, notify the selection object of a change to the
> > range if it is in a selection.
>
> I fear that this would be complex, brittle and slow.
Can you please clarify?
Comment 13•11 years ago
|
||
The nsRange mutation handlers[1] are already complex and brittle and
I'm worried that adding code to handle additional cases will make
them substantially worse. Note that currently we can ignore pretty
much all mutations that doesn't involve the start/end nodes of the
Range. That won't be the case if we need to detect mutations that
"modifies the selection" (as I understand that concept).
Say we have a Range in the Selection from a:0 to c:0 in:
<a>...<b>...<c>
then we currently ignore any mutations under <b> for example since it
doesn't affect the Range itself although the selection as the user
percieves it will likely change. Detecting and notifying such changes
will make the code slower (and I supect it means *all* code will be
slower, since the UA likely has a Selection listener already so we
*will* notify all such mutations if they occur inside the selection).
IIUC, the use case in this bug only needs to observe mutations under
a single node and there is a simple solution for that already:
var observer = new MutationObserver(function(mutations) {
// update your selection dependent stuff here
});
});
observer.observe(document.querySelector('#text'),
{ childList: true,
subtree: true,
characterData: true });
I don't think complicated changes to nsRange are motivated if the
above serves the use case here - and if it doesn't, then let's
discuss what exactly is needed and how we can solve that.
[1]
http://hg.mozilla.org/mozilla-central/annotate/f27ff178807d/content/base/src/nsRange.cpp#l388
Flags: needinfo?(mats)
Comment 14•11 years ago
|
||
To clarify the markup I meant a,b,c to be subtrees, something like this:
<a>...</a>...<b>...</b>...<c>...</c>
Comment 15•11 years ago
|
||
(In reply to Mats Palmgren (:mats) from comment #13)
> I don't think complicated changes to nsRange are motivated if the
> above serves the use case here - and if it doesn't, then let's
> discuss what exactly is needed and how we can solve that.
Needinfoing Jan.
Flags: needinfo?(janjongboom)
Assignee | ||
Comment 16•11 years ago
|
||
pinging :yxl as well. You think this is acceptable solution?
Flags: needinfo?(xyuan)
Comment 17•11 years ago
|
||
I tend to use a content mutation observer instead of changing the selection listener.
It doesn't change the semantics of the selection listeners and isn't the nsIEditorObserver[1] we already have able to act as content mutation observer:
https://github.com/mozilla/gecko-dev/blob/45f4500903123d7142ca43fcedf81e1388fececf/dom/inputmethod/forms.js#L332
Flags: needinfo?(xyuan)
Assignee | ||
Comment 19•11 years ago
|
||
Alright, so closing this as WONTFIX and moving the proposed fix into bug 1059163
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → WONTFIX
Assignee | ||
Updated•11 years ago
|
Flags: needinfo?(janjongboom)
You need to log in
before you can comment on or make changes to this bug.
Description
•