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

Legal caret positions – invisible text nodes #75

Closed
Reinmar opened this issue Aug 22, 2015 · 11 comments
Closed

Legal caret positions – invisible text nodes #75

Reinmar opened this issue Aug 22, 2015 · 11 comments

Comments

@Reinmar
Copy link

Reinmar commented Aug 22, 2015

The following HTML contains many text nodes (div.firstChild would be a text node with nodeValue='\n '):

<div contenteditable=events>
    <p></p>
</div>

There's a rule saying that caret can be placed:

Before or after any character in any text node.

That would mean that caret can be placed in that first text node, despite the fact that it would be invisible (unless CSS defines differently – e.g. white-spaces:pre case).

There's a rule already saying that:

The caret cannot be placed inside invisible elements.

Since text nodes are not elements, this rule doesn't apply in this case. So I propose adding another rule (or extending the existing once):

The caret cannot be placed inside invisible text nodes.

We would also need to define what "invisible text nodes" are (compare: #68).


One additional note: If I understood #74 (comment) correctly, this would mean that the caret cannot be placed anywhere between <b> elements in this case:

<p><b>foo</b>     <b>bar</b></p>

That's because the rules say that the caret can only be placed after/before inline elements which are not followed/preceded by text nodes. If we also say that it cannot be placed in that text node between <b>s, then this position will be illegal. This could be clarified by defining #74 as follows:

  • Before or after any character in any visible text node.
  • After inline elements which are not followed by visible text nodes.
  • Before inline elements which are not preceded by visible text nodes and that do not have a previousElementSibling.
  • <p><b>x</b>^ </p> – OK (matches 2nd rule only)
  • <p><b>x</b>^y</p> – OK (matches 1st rule only)
  • <p><b>x</b>^<b>y</b> – OK (matches 2nd rule only)
  • <p> ^<b>x</b> – OK (matches 3rd rule only)
  • <p>x^<b>x</b> – OK (matches 1st rule only)

(BTW. Making these rules exclusive is a challenge :D I'm hope I'm right about the above.)


There's actually one additional node type which complicates this – comments. We could use previousElementSibling in the second rule, but it may still not be enough. If we need to worry about comments, perhaps it would be easier to say that this algorithm should totally ignore them.

@johanneswilm
Copy link
Contributor

There was a long discussion about invisible nodes. First I defined them as display:none. Then someone came along and said the fomulation should be more vague ("invisible") so it could cover other nodes as well. Now the recent most request is to define invisible as equal to display:none and handle all other cases of "invisibility" in JS.

@johanneswilm
Copy link
Contributor

One additional note: If I understood #74 (comment) correctly, this would mean that the caret cannot be placed anywhere between elements in this case:
<p><b>foo</b> <b>bar</b></p>

Are those spaces between the two elements? I that case I would argue that it should be possible to place it there, even though the browser may join all those spaces together to be just a single space. We actually had a discussion about that earlier. The "invisible nodes" should never touch text nodes, unless they are in a display:none element.

@Reinmar
Copy link
Author

Reinmar commented Aug 22, 2015

There was a long discussion about invisible nodes. First I defined them as display:none. Then someone came along and said the fomulation should be more vague ("invisible") so it could cover other nodes as well. Now the recent most request is to define invisible as equal to display:none and handle all other cases of "invisibility" in JS.

I know – I saw the discussion. If it's OK to say that text nodes are elements, then the definition of invisible elements would be incomplete (as it'd say nothing about text nodes). Therefore, I think that it could be better to cover text nodes and elements separately. I think that browser people would need to make a decision which way is better. Based on that I could try to polish the legal caret positions section. E.g. I also noticed that it may be unclear how <br> elements are understood (there's that special case with <br> at the end of block or before a block).

@Reinmar
Copy link
Author

Reinmar commented Aug 22, 2015

One additional note: If I understood #74 (comment) correctly, this would mean that the caret cannot be placed anywhere between elements in this case:
<p><b>foo</b> <b>bar</b></p>

Are those spaces between the two <b> elements? I that case I would argue that it should be possible to place it there, even though the browser may join all those spaces together to be just a single space. We actually had a discussion about that earlier. The "invisible nodes" should never touch text nodes, unless they are in a display:none element.

Hm... I've just realised that these spaces would actually be visible (as one). I need to rethink my initial comment. E.g. which space would be visible in this case <p><b>x </b> <b> x</b></p>? I don't know how spaces aggregation work in details, so this is too complex for me at the moment. I'll try to find out how it works and maybe then I'll be able to propose something reasonable.

And to clarify – I consider this a valid position. In general – I would like to be able to place caret outside inline elements or inside them regardless of their surrounding or contents.

PS. CKEditor normalizes all white spaces when loading data, so such situations with white-spaces are unlikely to happen in it. Perhaps we could refer to or define similar normalization in the spec to simplify the rules.

@johanneswilm
Copy link
Contributor

PS. CKEditor actually normalizes all white spaces when loading data, so such situations with white-spaces are unlikely to happen in it. Perhaps we could refer to or define similar normalization in the spec to simplify the rules.

I think this is stuff the editor has to do. There can be many preferences for how to store spaces in texts and there is no good reason for us to mess with it at this stage. The caret should simply be placeable (programatically) anywhere in text nodes. Rule 1 states that already. So those text nodes do not fall under the definition of invisible.

If you don't feel that the commit addresses your concerns, please reopen this issue.

@Reinmar
Copy link
Author

Reinmar commented Aug 22, 2015

That's a good point. If an RTE keeps the DOM super clean, then caret won't be able to be placed in those weird locations as e.g.:

<div>
    ^<p>x</p></div>

So for me that's totally OK. The more places are legal, the more happy I am :).

@johanneswilm
Copy link
Contributor

Well, the point is just that this is where the the user CAN place the caret programatically (using JS). It doesn't say anything about where the UA SHOULD move the caret next.

@johanneswilm
Copy link
Contributor

We used to have a basic definition of caret movement, which included something about the caret having to move at least 1px or else repeat the same procedure...

But all that is kind of beyond the scope of this spec now and will have to be handled in a future spec.

@johanneswilm
Copy link
Contributor

<div>
    ^<p>x</p></div>

Is that a text node with lots of empty spaces before a block (

) node?

No, I don't think that should just happen. If this is because HTML has been loaded into the DOM in some way, then that import process should be changed.

@Reinmar
Copy link
Author

Reinmar commented Aug 22, 2015

Is that a text node with lots of empty spaces before a block (<p>) node?

Yes.

No, I don't think that should just happen. If this is because HTML has been loaded into the DOM in some way, then that import process should be changed.

It wouldn't happen in CKEditor as it normalizes white-spaces. But the spec currently says that it's a legal position so if some other editor won't normalizes white-spaces and someone will try to place the caret there by using JS, then (according to the spec) the browser should render such caret. If the browser people are OK with this, then we're fine.

BTW. According to the spec there's a difference between:

<div><p>x</p></div>

and

<div>
            <p>x</p></div>

In the first case there's no legal caret position before <p> while in the second there is. But again – just pointing out. It's fine for me as it would not affect an RTE which keeps the DOM clean.

@johanneswilm
Copy link
Contributor

Yes, I think we should stick to this. Otherwise we overcomplicate things and there may be situations we are not thinking of right now where editors actually may want such behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants