Closed Bug 286560 Opened 19 years ago Closed 3 years ago

Fix comments for focusNode in nsISelection.idl

Categories

(Core :: DOM: Core & HTML, defect, P5)

x86
Windows XP
defect

Tracking

()

RESOLVED INVALID

People

(Reporter: danswer, Unassigned)

Details

Attachments

(2 files)

User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1

focusNode is returning the incorrect node information when I go into a
text/textarea node.  It seems to return the last known focus node (more or less,
see details for alt+tab behaviour with DIVs) EVEN though it no longer has focus.
 I ensure this by putting in a window.setTimeout (in addition to explicitly
setting the selection in the text element (again, after a window.setTimeout))

Csaba Gabor from Vienna


Reproduce with:

<html><head><title>Focus test</title>
<script type='text/javascript'>
function elem(id) {return document.getElementById(id);}
function safeify(str) { return
str.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\n/g,"<br>"); }
function findSel() {
    var sel = window.getSelection();
    var node = sel.focusNode;
    var res = ""; var obj; var idx;
    if (node && node.nodeName) res = node.nodeName;
    else {    // print out details for unknown nodes
        for (idx in node) {
            objType = typeof(node[idx]);
            if (objType=="string") res += idx + ": &quot;" + safeify(node[idx])
+ "&quot;<br>\n";
            else if (objType=="number") res += idx + ": " + node[idx] + "<br>\n";
            else if (objType=="function") res += idx + ": function<br>\n";
            else if (node[idx]==null) res += idx + ": null<br>\n";
            else if (objType=="object" && typeof(node[idx].nodeName)=="string")
                res += idx + ": [" + node[idx].nodeName + "]<br>\n";
            else res += idx + ": " + objType + "<br>\n";
        }
    }
    var priorRes = elem('results').innerHTML;
    if (!priorRes || priorRes.substring(0,res.length)!=res)
elem('results').innerHTML = res;
    else elem('results').innerHTML += " *";
}
</script>
</head>
<body onload="document.forms[0].myt.focus()">
<form name=testform action=''>
<input type=text name=myt tabindex=1 value="abc def"
onfocus="window.setTimeout('document.forms[0].myt.setSelectionRange(1,2)',100);window.setTimeout(findSel,500)">
<button type=button name=myb accessKey=b>Dummy <u>B</u>utton</button>
</form><br>
<div id=results>&nbsp;
</div>
</body>
</html>

Reproducible: Always

Steps to Reproduce:
Bring up the included page.  You might want to have an additional tab in Firefox
(to try with ctrl+pagedown).  The div now shows FORM

1.  If you tab into textbox (myt) then window.getSelection().focusNode will
always show FORM

2.  Bring up the page fresh.  Click somewhat below FORM, then click myt => no
change (you get an '*' to indicate that .focuNode has the same nodeName).  Now
click somewhat to the right of the button, then click myt => BODY.  Now click
somewhat below BODY, then click myt => no change (you get an '*').  This means
that clicking below that text is not causing a change.  Now click on the text
BODY, then click myt => #text.  Now click somewhat below #text, then click myt
=> DIV.  This might not be new behaviour, but it is anomalous.

3.  If you Alt+Tab to another app, then back, then .focusNode does not alter

4.  If you click on the Button and then click myt, .focusNode does not change. 
HOWEVER, if you press alt+B to simulate a click on the button and then click
myt, .focusNode changes to "BUTTON".

5.  Finally, click on the text in the div, then click myt => #text.  Now either
press alt+tab twice (to tab to another application and then back) or click the
button then click myt => DIV


Expected Results:  
In no case is there actually focus in the returned elements, so I would argue
that all 5 observed behaviours are incorrect, but some, such as 4 and 5, seem
more incorrect than others.  I've put in a delay to produce a selection in the
textbox, and then an even longer delay to allow that to settle before making the
report to the DIV.  Focus/selection is gone from everywhere else before any
reporting happens.

What I'm expecting is to have .focusNode return the control (myt) that has the
focus (and selection).

Note: I AM able to both determine (myt.selectionStart, myt.selectionEnd) and set
(myt.setSelectionRange) the selection within the text control (about which I'm
very happy).  The motivation here is more along the lines of which element has
focus (corresponding to document.activeElement in IE)...
The focusNode is inconsistent for tabbing into an input blank vs clicking into
the blank. Clicking into the blank appears to always be correct, but tabbing in
usually results in the wrong node (returns the body element as opposed to just
the input element).

Since the selection is tied with the caret, this bug creates a very serious
problem for accessibility tools that rely on the caret to determine where the
user is.

I can confirm this bug report 100%

In my case I was working with nodes in an iframe (DesignMode = "On") -- not a
textarea. The iframe is inside a form but this does not appear relavent.

Specifically, selecting an IMG element fails to provide the correct node. I
always get some node prior to the node actually selected. I would expect even
anchorNode to be the selected image in the case where the image it selected by a
single click.

Interestingly, blind execCommand operations to change text color, for example,
*do* operate on the correct selection -- even though getSelection would still
return the wrong node(s) -- that is, if I simply leave out my code to
rationalise the current selection, stuff works -- but not so with IMG tags for
some reason.
This bug happens with replaced elements, if I understand it correctly?

See:
http://developer.mozilla.org/en/docs/DOM:Selection:anchorNode
"Returns the node in which the selection begins."
http://developer.mozilla.org/en/docs/DOM:Selection:focusNode
"Returns the node in which the selection end."

A selection can never be inside a replaced element (at least not with normal selection), as far as I can tell, so isn't this bug invalid?
(In reply to comment #3)
> This bug happens with replaced elements, if I understand it correctly?
> ...
> A selection can never be inside a replaced element (at least not with normal
> selection), as far as I can tell, so isn't this bug invalid?

There is usually no beginning or end end selection when an object simply receives focus -- in fact there is usually "selection" at all. Is that the poiint you are making here? If it is... then what function DOES return the object with the current focus, regardless of selection?
Well, despite the name, focusNode doesn't really have anything to do with were the focus is. It simply just returns the node in which the selection ends.
I don't know of any function that returns the focused element.
Maybe you could add a focus listener on the window or something?
(In reply to comment #5)
> Well, despite the name, focusNode doesn't really have anything to do with were
> the focus is. It simply just returns the node in which the selection ends.
> I don't know of any function that returns the focused element.
> Maybe you could add a focus listener on the window or something?

Seems to me (and I'm sure many others) that since a) it's called focusNode() and b) all the other browsers except maybe Safari *seem* to interpret that label literally -- that the *bug* here is someone's definition of of what focusNode should do. It should, surely, return the current node with focus. No? I mean -- far out! No? :) (I'm sure someone's gonna mention something about W3C about now -- perhaps that needs an erata entry too huh? :)
You're right it's a misnomer. The developers of this interface were thinking of the focusNode as where the caret is. I think the actual DOM focus would probably always be an ancestor of that node.

Anyway, this is not a W3C interface -- it's not standards-based so there is no important conflict with safari.

I would say the idl comment for focusNode should be fixed to explain the misnomer:
http://lxr.mozilla.org/seamonkey/source/content/base/public/nsISelection.idl#59

This misnomer is really the least of our focus problems which occured from focus not being clearly designed from the beginning.
(In reply to comment #7)
> You're right it's a misnomer. The developers of this interface were thinking of
> the focusNode as where the caret is. I think the actual DOM focus would
> probably always be an ancestor of that node.
I can change the selection by script, and I'm pretty sure the focus doesn't change with it, so focusNode really doesn't necessarely have anything to do with were the focus is, afaics.
So I think this fixes the comments in nsISelection.idl, but focusNode and focusOffset are really awful names, because they suggest something different.

And I think a way to get the current focused node in a web page in Mozilla would be nice (e.g. like IE6 does with document.activeElement). But I guess I need to raise that in the whatwg?
Attachment #214544 - Flags: review?(bzbarsky)
Attachment #214544 - Attachment is patch: true
Attachment #214544 - Attachment mime type: application/octet-stream → text/plain
Attachment #214544 - Flags: superreview+
Attachment #214544 - Flags: review?(bzbarsky)
Attachment #214544 - Flags: review+
Changing summary to reflect the current state of the bug.
Summary: focusNode returns incorrect node (from window.getSelection) → Fix comments for focusNode in nsISelection.idl
Checking in content/base/public/nsISelection.idl;
/cvsroot/mozilla/content/base/public/nsISelection.idl,v  <--  nsISelection.idl
new revision: 1.10; previous revision: 1.9
done

Fixed.
Status: NEW → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
(In reply to comment #9)
> And I think a way to get the current focused node in a web page in Mozilla
> would be nice (e.g. like IE6 does with document.activeElement). But I guess I
> need to raise that in the whatwg?
Ah, there is already something specced here:
http://www.whatwg.org/specs/web-apps/current-work/#documentfocus1
So it only needs to be implemented. ;)

I haven't had internet connectivity for the last week, and I see a lot of activity here.  In particular, I notice that most of the issues I raised in the original report are now resolved (in the sense that there is now consistent behaviour).  That's good.

However, the documentation for focusNode now says something to the effect of:
Returns the node in which the selection ends.

Is this well defined?  A node can have child nodes, after all.

In particular, when I now try my original tests, I am consistently getting FORM as the focusNode when I click in the text input element.  Is there a reason that a reader of the documentation should suspect the FORM element is returned by focusNode instead of the tightest fitting <input ...> element?  Frankly, FORM seems like the worst possible element to pick.
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Attached file testcase
(In reply to comment #13)
> However, the documentation for focusNode now says something to the effect of:
> Returns the node in which the selection ends.
> 
> Is this well defined?  A node can have child nodes, after all.
Yes, it's well defined. In that case the focusNode returns one of the child nodes were the selection ends.

I don't really understand your testcase. An input is a replaced element, which means the selection can't be inside it. The selection you see in an input element is a different selection than that from window.getSelection(), they operate independantly from each other.
Sorry to butt in -- but the original bug report was very clear. There was no mention of replaced objects. Quite simply, the current selection is not returned by focusNode -- but it is in other browsers (99% sure -- haven't tested conclusively lately.) Where is the confusion exactly? We seem to be off on some tangent. 

*** Can we not just have focusNode "return the node at the end of a selection" -- even when the "selection" is a single node? ***

Like, for example, when a single image is selected in design mode -- by cliking on it once -- that image is now the start and end of "the selection" -- but focusNode is not returning the img node at all. To me, the orignal test case makes this clear enough -- well I think so. *shrug* "Selected" does not neccesarily mean "part of multiple items". The position of the caret in a text box, in my opinion, IS a selection too -- naley, the character directly before it. If not that -- then at least it MUST be the textbox node itself. No?

Are you perhaps thinking of "Selection" in terms limited by "clipboard related functions?"

I'll butt out now. :)
> (In reply to comment #13)
> > However, the documentation for focusNode now says something to the effect of:
> > Returns the node in which the selection ends.
> > 
> > Is this well defined?  A node can have child nodes, after all.
> Yes, it's well defined. In that case the focusNode returns one of the child
> nodes were the selection ends.

Thanks for your reply Martijn.  Let me clarify my comment on well defined.
A selection could end in a SPAN/DIV of a P element within the BODY of a document.  If you say "the" node, then it implies that the node is unique, but nothing in the documentation that I've seen indicates this uniqueness.  In other words, nothing I've read says that it is the 'tightest fit' surrounding node that should be returned.  In fact, even your reply says "one of the child nodes [of what?] where the selection ends" which means that as a developer I am not told which one I will be getting.  This is inconsistent.

On the other hand, if you say "a" node, it means any one of many (like "one of the child nodes") the definition is consistent, but not specific enough to let the developer determine which one.  Mozilla could always return BODY (rendering focusNode useless) and say that it is a child node of Document.

> I don't really understand your testcase. An input is a replaced element, which
> means the selection can't be inside it.

My apologies on this.  This report seems to be full of words that read one way and mean something else.  I read your earlier comments about replaced elements, and since I knew that a replaced element is one that has undergone an element.replaceNode operation, it was clear to me that they were tangent comments to my original report.  Little did I realize till your comment 14 that replaced element has another meaning, found at http://www.w3.org/TR/REC-CSS2/conform.html

I haven't seen in the documentation where it says that focusNode operates only on non replaced elements.

> The selection you see in an input
> element is a different selection than that from window.getSelection(), they
> operate independantly from each other.

Yes.  You could have multiple <input type=text ...> elements and each retains the selection that it has, along with the selection in the main document.  However, only one selection is ever shown at a time, no?  (By shown, I am thinking of when you see the selection actually/actively hilighted.  If the element with the selection is not "active" then one does not see the selection).
In other words there is, at most, one active selection.

To my mind that makes the end position of the selection (meaning active selection) well defined, provided there is an active selection.  I see no intrinsic reason that a replaced element should not be returned when the active selection is within a replaced element.

In conclusion, according to the behaviour I am seeing, I would recommend the documentation for focusNode (it should have been named caretNode, no?) read something like:
Returns the tightest fit non replaced node in which the selection ends [that is to say, where the caret is].

However, I hope that it may be possible to explore the issue of allowing a replaced node to be returned when that is where the caret(cursor) / (active) selection is so that we would not have to write "non replaced node" above.  (Of course when there is no visible selection, just the caret, the active selection has length 0).

Finally, because I might be missing something relevant, I'd like to mention a behaviour that I don't understand on your attachment.  If I select the "es" in the top "test" and then press the right arrow three times, the caret winds up in the input field.  However, I am not able to make a selection (using the shift keys in combination with the right/left arrow), nor am I able to enter text.  What am I missing?

Csaba
(In reply to comment #15)
> Sorry to butt in -- but the original bug report was very clear. There was no
> mention of replaced objects. Quite simply, the current selection is not
> returned by focusNode -- but it is in other browsers (99% sure -- haven't
> tested conclusively lately.) Where is the confusion exactly? We seem to be off
> on some tangent. 
No, that's not correct, focusNode returns the node in where the selection ends in Mozilla, 100% of the time, afaics.

> *** Can we not just have focusNode "return the node at the end of a selection"
> -- even when the "selection" is a single node? ***
That is already happening, not?

> Like, for example, when a single image is selected in design mode -- by cliking
> on it once -- that image is now the start and end of "the selection" -- but
> focusNode is not returning the img node at all. To me, the orignal test case
> makes this clear enough -- well I think so. *shrug* 
No, when you select an image, the anchorNode and the focusNode are not the img element, but the element surrounding the img element, since the selection _surrounds_ the image, it's not inside the image.

> The position of the caret in a text box, in my opinion, IS a selection too -- naley, the character directly before
> it. If not that -- then at least it MUST be the textbox node itself. No?
Yes, the position of the caret in a text box is a selection too, but it is a _differrent_ selection, and it has a different api. So window.getSelection().focusNode gets you nowhere in this case. When you click in the textbox, the selection in the document gets cleared, so there is no selection in the main document after that, see:
http://wargers.org/mozilla/getselection.htm
If you want the text selection in an input, see here, at the bottom:
http://developer.mozilla.org/en/docs/XUL_Tutorial:Focus_and_Selection
(In reply to comment #16)
> node that should be returned.  In fact, even your reply says "one of the child
> nodes [of what?] where the selection ends" which means that as a developer I am
> not told which one I will be getting.  This is inconsistent.
Sorry, to be not clear, you get the node back in where the selection ends, and there is only one of that, so it's a unique node.


> > I don't really understand your testcase. An input is a replaced element, which
> > means the selection can't be inside it.

> and since I knew that a replaced element is one that has undergone an
> element.replaceNode operation, it was clear to me that they were tangent
> comments to my original report.  Little did I realize till your comment 14 that
> replaced element has another meaning, found at
> http://www.w3.org/TR/REC-CSS2/conform.html
replaceNode has nothing to do with this. The cs2 link sort of explains it, a replaced element is an element where the content of the element is replaced by something different.

> I haven't seen in the documentation where it says that focusNode operates only
> on non replaced elements.
It doesn't operate only on non replaced elements, I didn't say that.

> Yes.  You could have multiple <input type=text ...> elements and each retains
> the selection that it has, along with the selection in the main document. 
> However, only one selection is ever shown at a time, no?  (By shown, I am
> thinking of when you see the selection actually/actively hilighted.  If the
> element with the selection is not "active" then one does not see the
> selection).
> In other words there is, at most, one active selection.
No, the selection in the main document gets cleared, when you focus a text box, see commet 17. Textbox elements indeed retain the selection that it has.

> To my mind that makes the end position of the selection (meaning active
> selection) well defined, provided there is an active selection.  I see no
> intrinsic reason that a replaced element should not be returned when the active
> selection is within a replaced element.
Yes, _when_ the selection is _within_ a replaced element, then you are correct, but there is now way with normal selection (where the users is dragging a selection with the mouse) to get inside a replaced element.

> In conclusion, according to the behaviour I am seeing, I would recommend the
> documentation for focusNode (it should have been named caretNode, no?) read
> something like:
> Returns the tightest fit non replaced node in which the selection ends [that is
> to say, where the caret is].
No, current documentation (which I changed) is correct. focusNode can be inside a replaced element (but that doesn't happen normally).
 
> Finally, because I might be missing something relevant, I'd like to mention a
> behaviour that I don't understand on your attachment.  If I select the "es" in
> the top "test" and then press the right arrow three times, the caret winds up
> in the input field.  However, I am not able to make a selection (using the
> shift keys in combination with the right/left arrow), nor am I able to enter
> text.  What am I missing?
Are you browsing with caret browsing turned on? I think that's a bug, you could file a new bug on that (if there hasn't been filed a bug on it, already).
> No, when you select an image, the anchorNode and the focusNode are not the img
element, but the element surrounding the img element, since the selection
_surrounds_ the image, it's not inside the image.
Ah! Thank you. That explains something that's been confusing me a long time. 

(Though I'm not convinced it is this way in the other browsers, for what that's worth. But I'll research that myself. Don't waste any time on my now off-topic ignorance. :) 
Assignee: general → nobody
QA Contact: ian → general
https://bugzilla.mozilla.org/show_bug.cgi?id=1472046

Move all DOM bugs that haven't been updated in more than 3 years and has no one currently assigned to P5.

If you have questions, please contact :mdaly.
Priority: -- → P5

https://w3c.github.io/selection-api/ covers this and seems aligned with our implementation.

Status: REOPENED → RESOLVED
Closed: 18 years ago3 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: