Anne van Kesteren

More on contenteditable

Today I spend some more time on figuring out how contentEditable works in Internet Explorer. The plan is basically to specify the behavior of the attribute in IEs implementation and than make something sane out of it for WHATWG. Together with Jorgen on instant messenger I had quite some fun figuring out what IE actually does. At first sight you might not notice a real difference between the following documents:

<!DOCTYPE html>
<div contenteditable>
 test
</div>
<!DOCTYPE html>
<div contenteditable>
 <div>
  test
 </div>
</div>

However, the first document will generate p elements on pressing enter and the second will generate div elements on pressing enter. We got the feeling IE implemented this as in switch(element) as it didn't really make much sense. There seems to be some logic though. If there is no block level container IE will generate p elements. Inline elements will be duplicated. There are exceptions of course, like the a element. Attributes applied to the p element (if one was already there) or to the div element are also duplicated. The id attribute is not duplicated fortunately. (It is in Firefox, designMode.)

(Everything fails on pasting in Internet Explorer. The DOM becomes ill-formed. It's like overlapping elements. Ian wrote about it in the past. I'm really sure how to redefine this in a sane way, but I guess I figure something out eventually. Or perhaps the smart people on the WHATWG mailing list will when I publish some results there.)

When you have the following document there is also some strange behavior going on. It might actually make some sense for the end user, but it isn't really predictable how it's working.

<!DOCTYPE html>
<div contentEditable>
 <h1>
  test
 </h1>
</div>

What happens here when you hit enter depends on the cursor position. It also depends on the whitespace inside the element. <h1>test</h1> gives different results. When there is whitespace and your cursor is positioned right after the second 't' you can press enter once and create a new h1 element. However, if you hit enter again you will return to IEs default behavior of creating paragraphs. (See the consistency? Nice!)

As I'm writing this our knowledge on the subject is still evolving. Say x is a random character, w is whitespace and n represents &nbsp;. Now when you have the string xxxw inside a h1 element. Pressing enter before the whitespace will generate a new element of the same kind (h1), pressing enter after the whitespace will make IE generate a p element. However, when the string is xxxn it doesn't matter if you press enter before or after the enitity. IE will always generate a p element. That also explains the above paragraph a bit better as IE internally represents most whitespace characters as &nbsp; when it considers them significant. (When you create a space, et cetera.)

So you probably stopped reading now, but I have something interesting for the end. (Actually, we just discovered this a minute ago.) As I'm playing with Internet Explorer a lot these days and mostly contentEditable I had to read on having layout and several MSDN documents. Jorgen and I can confirm what was already suspected in that document:

We think they speak of a little window, an own rendering viewport. An element which has layout could be represented internally by an object with its own methods and properties.

Example document used:

<!DOCTYPE html>
<div contentEditable>
 <h1 style="height:1%">test
 </h1>
</div>

It is already widely known the h1 element will have layout. However, when you know press enter inside the h1 element it will generate p elements. That is because the h1 element is not really important anymore. The h1 element has become the viewport and all content inside it will be treated as it were in some generic element. Sick. Pretty cool discovery though.

If the WASP is going to cooperate with Microsoft, I would love them to point this out and ask Microsoft to discuss this on the WHATWG mailing list. Of course, it is doubtful if Microsoft would make any profit from interoperability, but they will get a better image.

Comments

  1. Anne, one of the very first things I’m going to ask Microsoft to do is clarify the whole "layout" thing. I was a voice in the wilderness at first and I’m delighted that Ingo’s document is getting some attention. I believe that all CSS designers and DOM scripters should read this document.

    Incidentally, an element immediately acquires "layout" when you set the contentEditable property. Even if you set it to false.

    Posted by Dean Edwards at

  2. But... is it really important to know what code contentEditable generates? Can’t you just output the browsers whatever HTML want (IE its own stuff, Mozilla composer(/mail)-based output, etc)? If it is going to be published again on tag soup HTML web sites, it doesn’t matter what the output is. And if it needs to become well-formed, shouldn’t that just be solved server-side with a Tidy-like technology?

    It would of course be nice to have IE’s behavior documented, but I’d be horrified if other browsers would have to actually mimic IE’s behavior in this regard...

    Especially given the results I have seen so far that will both be extremely difficult and the output will hardly be useful for parsing anyway.

    ~Grauw

    Posted by Laurens Holst at

  3. Laurens I dissagree. A webbrowser should not produce HTML that is impossible. How would you "tidy" a document with SPAN element filled with P's?

    Secondly, the paste behaviour has so, many, bugs! It is not rare you'll end up with cyclic structure instead of a tree after pasting.

    Documenting the IE behaviour is important to learn from mistakes the IE team has made.

    Posted by Jorgen Horstink at

  4. Well, some parts that do make sense we want to see in other browsers as well. For example the generation of p elements. Ill-formed DOM is of course out of the question, but knowing what Internet Explorer does is important for deciding what other browser should do. (This has actually been the case for the past couple of years.)

    Posted by Anne at

  5. Dean, I believe an element does not get layout when you don't set the contentEditable at all, even when it is inside an editable region (as shown above, see the difference between the div and the other div element that has height:1%). So although those elements implicitly have contenteditable=true they don't necessarily have layout.

    Posted by Anne at

  6. li {background:silver;  }
    .layout{_height:0; background: pink;}
    
    <body contenteditable=true>
    <ol>
     <li>alpha</li>
     <li>beta</li>
     <li>gamma</li>
    </ol>
    <ol>
     <li>delta</li>
     <li class="layout">epsilon</li>
     <li>zeta</li>
    </ol>
    ...
    

    Contenteditable allows to drag (and resize, and edit) any layout element. body itself has layout by default (the following may burn your PC)

    1. drag epsilon to the beginning of beta. - the second list gets no re-draw/re-count event.
    2. Now click at gamma so the cursor is at End-Of-Line, 2x DEL, BACKSP. - we now have one ordered list
    3. click at EOL of alpha, RETURN - some new li entries

    To me, contenteditable is a debacle, but provides insight into current rendering bugs.

    Remember the list white-space-bug or some tree-pixel-gap float scenarios, make body contenteditable, and interact with the mess. Or stay with this example above and add ol {float:left;}, but be prepared to face the evil.

    One will note that the idea of making layout elements responsible for drawing and bound their content is a fundamental misconception, and the day they reject the layout concept as a whole will be a bright day.

    Rumors are that we are able to publish a revision of the article the next days. I don't know exactly if we'll cover this contenteditable stuff, though.

    Posted by Ingo Chao at

  7. As I wrote on my site, IE only generates P elements on children of elements having layout.

    This is looks like direct evidence for elements having layout using their own viewport.

    Posted by Jorgen Horstink at

  8. Anne, I mean that when you set contentEditable=false using JavaScript the element acquires layout.

    Posted by Dean Edwards at

  9. I discovered something while experimenting with contentEditable the other night:

    <!DOCTYPE html>
    <title>contentEditable</title>
    <style>div p { width: 200px; height: 500px; background: #f1f1f1; position: absolute;} </style>
    <div contenteditable>
    <p>
      This is editable
    </p>
    </div>
    

    If you apply position: absolute to the P-element, the left and bottom gliders won't work.

    Posted by Henrik Lied at