- From: Robin Berjon <robin@w3.org>
- Date: Tue, 24 Jun 2014 12:34:51 +0200
- To: Johannes Wilm <johannes@fiduswriter.com>
- CC: Xavier Morel <xmo@openerp.com>, "Web Applications Working Group WG (public-webapps@w3.org)" <public-webapps@w3.org>, public-editing-tf@w3.org
On 23/06/2014 20:33 , Johannes Wilm wrote: > I filed bugs on this on both Firefox and Chrome in spring 2013. It was > briefly fixed in Chrome, but the fix was then retracted and we never > heard any more of it. It was also reported in Firefox by someone else in > 2011. [1] > > I also had some contact with Webkit people working in this area who > unfortunately didn't find the behavior to be problematic. > > This is probably the main reason why at least I am wondering if editing > maybe just is an area that won't be of enough interest to browser makers > to ever fix and that it may therefore just make more sense to just ask > them to remove it and do everything in Javascript. But now it seeems > this is about to change, which would be really really good. From discussions I've had in the past on this topic, it's not so much that browser-folks don't want to fix this. The problem is more that 1) this is hard, so fixing can often only happen if someone really owns the problem rather than contributing the odd fix, and such a person isn't always available; 2) the current state of contentEditable is such a mess, notably with libraries doing per-UA workarounds, that fixes that make the behaviour globally saner actually break deployed code. This has conspired to make the situation rot. Hopefully we can fix this with the new tack taken here, notably by using contentEditable=cursor as a "sanity hook" which doesn't have to be backwards compatible with the existing madness. You point to several bugs, but I think the one most worth reading is: https://code.google.com/p/chromium/issues/detail?id=238000 This has a wealth of issues and information, as well as a number of good ideas. Piotr's point about the behaviour of deletion when a selection crosses an even number of editing boundaries is particularly useful. The way we've been thinking about this so far is that with cE=cursor, the browser would perform no DOM modification on your behalf but rather you'd have to handle events in order to carry out the modifications yourself. This increases the amount of work that script has to do but in this case it would likely enable you to produce the precise handling you require. Having said that, considering this specific problem makes me realise that the deletion event model that I had in mind does not work. The way I'd initially considered it was that you'd receive a Deletion event that would abstract away from the deleting backwards/forwards differences across platforms as well as reach of the deletion (character, word, line, etc.). This works well for the following examples (in all of which | represents a cursor and [] a selection): <editable>If a clock gets hungry|, it goes back four seconds.</editable> Here (at least on my computer) the following key combinations would yield deletion events with the indicated ranges: backspace "y" delete "," alt-backspace "hungry" ctrl-K "If a clock gets hungry, it goes back four seconds." So far so good, and this extends well to the selection case: <editable>If a clock gets [hungry], it goes back four seconds.</editable> backspace "hungry" delete "hungry" alt-backspace "hungry" ctrl-K "If a clock gets hungry, it goes back four seconds." That's all nice and well, but what should the range be in the following cases: A: <editable>blah <non-editable>foo</non-editable>| blah</editable> B: <editable>blah [<non-editable>foo</non-editable>] blah</editable> C: <editable>bl[ah <non-editable>foo</non-editable> bl]ah</editable> D: <editable>blah <non-editable>f[oo</non-editable> bl]ah</editable> E: <editable>blah <non-editable>|foo</non-editable> blah</editable> Or in this: F: <ul contenteditable=cursor> <li>blah</li> <li>|blah</li> </ul> F2: <ul contenteditable=cursor> <li>blah</li> <li>|</li> </ul> or just for kicks, one could make the argument that this is different: G: <ul contenteditable=cursor> <li contenteditable=cursor>blah</li> <li contenteditable=cursor>|blah</li> </ul> ? I think that we can start to solve this in the following manner: • When a deletion event would produce a range crossing an odd number of editing boundaries (either because there's a selection doing so in the sum of its ranges or for instance given backspace in case A above) then its range is empty and corresponds to a collapsed range a the cursor position (this is defined even for selections). • Conversely, when it would cross an even number of editing boundaries, then the range covers them. • Deletion events capture information expressing the direction of the deletion ("previous", "next", or possibly "both" in the delete-line case). This makes it possible for script to know how to hand the empty-range case. • Additionally, the deletion event can expose convenient information about the editing boundaries being crossed, their number, their hosts. This means that, assuming backspace, the cases above can be handled as follows: A: empty range, the script can decide whether to select or delete the non-editable content (direction "previous"). B: a range containing non-editable. Presumably deleted. C: same as B with some extra content on both sides. Presumably deleted. D: empty range, the script can decide what makes most sense. (Stabbing the user in the face sounds good.) E: empty range, the script decides which is best. For F, F2, G, and an awful lot of other cases (dt/dd, td, etc.) I think we should take the minimalist approach: just produce a deletion event indicating its direction but with an empty range. Scripts can decide if they wish to merge elements, delete empty ones, outdent, etc. This is getting complicated enough (and I haven't mentioned other cases such as br, script, hr, td, img, video...) that I wonder if the Deletion event shouldn't have its own spec. Other question: when there's a selection and an input event takes place, should it be preceded by a deletion event? I think we need to because the alternative is to have the input event handler have to perform its own logic equivalent to deletion, which would be painful. But it comes with its own interesting challenges. Thoughts? > Use cases for this: > > 1. We use it for footnotes which we float of to the right of the text in > a <span class="footnote" contneteditable=false><span><span > contenteditable="true">[FOOTNOTE TEXT]</span></span></span>. If one has > access to CSS regions, one can even float them to be under the text on > each page. The other <span class="footnote"> is used to draw the > footnote number in the main text. If one hits backspace behind it, the > entire footnote should disappear. as it is now, instead the "back wall" > of the footnote is removed which means that the rest of the paragraph > is being added to the footnote. A question for you: how would you like selection to work in this case, notably for copy/pasting? As a user, I would tend to expect that if I select from before the <sup>1</sup> to after it and copy, I would get a buffer containing the <sup>1</sup> but *not* the footnote content (otherwise you get the famed "PDF effect" with lots of junk in your buffer). It also looks visually weird if you have the footnote to the side of the page being selected. But with the logical document order you use, it would get selected. Do you make use of selection-preventing tricks? These likely have their own amusing interactions with deletion: if you make the footnote non-selectable but wish to drop it when a selection encompassing it is deleted, you're facing a fun new challenge. -- Robin Berjon - http://berjon.com/ - @robinberjon
Received on Tuesday, 24 June 2014 10:35:05 UTC