This document is no longer maintained. See HTML and HTML Editing APIs instead.

Web Applications 1.0 — contentEditable and disabled

This version:
...
Latest version:
...
Editor:
Anne van Kesteren, Opera Software

It is expected that this specification will eventually be merged with Web Applications 1.0.

The contentEditable attribute

Currently contentEditable is markup language specific.

The contentEditable must apply to all HTML elements or elements in the http://www.w3.org/1999/xhtml namespace with the exception of the html element, the table element and its descendants and the head elements and its descendants. It is expected that a future revision of this draft includes support for editable tables. If an element has a contentEditable attribute set to exactly the literal value true, or if its nearest ancestor with the contentEditable attribute set has its attribute set to exactly the literal value true, then the UA must treat the element as editable (as described below).

If an HTML element has a contentEditable attribute set but the value of the attribute is not empty or exactly the literal value true, or if its nearest ancestor with the contentEditable attribute set is not editable, or if it has no ancestor with the contentEditable attribute set, then the element must not be treated as editable.

Authors must only use the values true and false with the contentEditable attribute.

If an element is editable and its parent element is not, then the element is an editing host. Editable elements can be nested, meaning the user can edit through them (see below). User agents must make editing hosts focusable (which typically means it enters the tab order). An editing host can contain non-editable sections, these are handled as described below. An editing host can contain non-editable sections that contain further editing hosts. These nested editing hosts must not be handled any differently to top-level editing hosts.

UAs must make it possible to select, copy and resize (if applicable) non-editable sections within an editing host. Non-editable sections within an editing host can contain an editing host.

Processing model

Because implementors have no clue.

This section should define what current cursor position means, where you can place your cursor, what a line is. See some notes in the source code.

In Internet Explorer there is different handling for elements inside an editable host that have certain attributes or CSS properties set that might cause hasLayout to become true. We are ignoring those specifics here as they make no sense whatsoever.

Basic actions

These actions only apply when the editable area is focused.

Automatic generation of a elements when certain text is inserted

A execCommand should be mapped to this in order to turn it off.

This section should describe that when someone enters http://example.org the browser should turn it into <a href="http://example.org">http://example.org</a>. Same for example@example.org (here a mailto: has to be added as well).

Creating a line-break (shift+enter)

This should have a execCommand equivalent.

User agents should allow users to enter line-breaks in editing hosts. The exact interface for this is implementation dependent. When the user requests a line break, the user agent must insert a br element node at the current cursor position. This also applies to pre elements.

Inside an attribute value (when modifying an input element for example) requesting a line-break must result in the insertion of U+000D immediately followed by U+000A (&#13;&#10;).

Here is an example of inserting a br element node. The current cursor position is denoted with |. Before:

...
 <div contenteditable="true">
  <p>Foo|Bar</p>
 </div>
...

After:

...
 <div contenteditable="true">
  <p>Foo<br>|Bar</p>
 </div>
...

And here is what the output may look like when editing an input element:

...
 <input value="Foo&#13;&#10;Bar" contenteditable="true">
...

Creating a block-break (enter)

This should have a execCommand equivalent.

One of the problems with block-break is that its exact semantics depend on the markup language being used and the nodeName of the editing host. For example, in HTML you want to disable the ability to insert p element nodes inside a h1 element node. For generic XML languages this is almost impossible with using a schema language of some sort.

CSS display types are not an option as they don't have enough different values to distinquish between the kinds of content models you have.

Because Internet Explorer treats each element that is made an editing host as a div element with some specifics that are relevant to the element contenteditable="true" was applied upon this specification only defines what should happen for elements that are being edited inside a div element that has contenteditable set to true.

User agents should allow users to enter block-breaks in editing hosts. The exact interface for this is implementation dependent. The result of a user requesting a block-break depends on the context.

Paragraph algorithm

The algorithm must be applied by UAs in when:

The algorithm is as follows:

Parts might be merged

  1. Two p element nodes must be created. If the request was made from a p element node line the attributes either set through markup or DOM excluding the id attribute must be set on the newly created p element nodes.
  2. For all non whitespace text nodes that share a common or no ancestor before the current cursor position the UA must check the zero or more ancestors and recreate those excluding a element nodes including their attributes set through either markup or DOM excluding attributes of type ID and append them in order they were found to the first p element node that was created in step 1. When there are no non whitespace text nodes before the current cursor position the p element node must contain one U+00A0 character.
  3. All non whitespace text nodes that share a common or no ancestor from step 2 must be recreated and appended to the common parent element inside the newly created p element node or must be appended directly to the newly created p element when no common parent element exists.
  4. If before the none whitespace text nodes that share a common ancestor more non whitespace text nodes exist step 2 must be repeated.
  5. For all non whitespace text nodes that share a common or no ancestor after the current cursor position the UA must check the zero or more ancestors and recreate those excluding a element nodes including their attributes set through either markup or DOM excluding attributes of type ID and append them in order they were found to the second p element node that was created in step 1. When there are no non whitespace text nodes after the current cursor position the p element node must contain one U+00A0 character.
  6. All non whitespace text nodes that share a common or no ancestor from step 5 must be recreated and appended to the common parent element inside the newly created p element node or must be appended directly to the newly created p element when no common parent element exists.
  7. If before the none whitespace text nodes that share a common ancestor more non whitespace text nodes exist step 5 must be repeated.
  8. The whole line should be replaced with the two newly created p element nodes.
...
 <div contenteditable="true">
  Foo|Bar
 </div>
...

Would result in:

...
 <div contenteditable="true">
  <p>Foo</p>
  <p>|Bar</p>
 </div>
...
Block level element algorithm

This algorithm must apply when the paragraph algorithm does not. I hope this is true...

div

When requesting a block-break where the parent node or nearest ancestor node if the parent node is an inline level element of the current cursor position is a div element two div elements must be created and for each the attributes either set through markup or DOM excluding the id attribute on the div element must be set on the newly created div element nodes. Now the paragraph algorithm from step 2 on must be applied to these newly created div element nodes. (And thus replacing p with div.)

h1, h2, h3, h4, h5 and h6 (from now on: hx)

When requesting a block-break where the parent node or nearest ancestor node if the parent node is an inline level element of the current cursor position which must not be at the end of the line or one character before the end when the last character is U+00A0 is a hx element two hx elements must be created and for each the attributes either set through markup or DOM excluding the id attribute on the hx element node must be set on the newly created hx element nodes. Now the paragraph algorithm from step 2 on must be applied to these newly created hx element nodes. (And thus replacing p with hx.)

When requesting a block-break where nearest ancestor node name is hx and the current cursor position is at the end of the line or one character before the end when the last character is U+00A0 a p element node must be created and appended directly after the hx element node containing the character U+00A0.

li

This does so not deal with nested lists. Any suggestions on that are highly appreciated.

When requesting a block-break inside an li element node that has children two li element nodes must be created and for each the attributes either set through markup or DOM excluding the id attribute on the li element node must be set on the newly created li element nodes. Now the paragraph algorithm from step 2 on must be applied to these newly created li element nodes. (And thus replacing p with li.)

When requesting a block-break inside li element node that has no children the node must be removed and a p element node must be created and appended directly after the parent node of the li element node containing the character U+00A0.

Internet Explorer does weird things for nested lists. There is a difference between ul - li - ul - li and ul - li - div - ul - li for example that is hard to debug.

Attribute values

Inside an attribute value block-break must be treated equivalent to line-break.

Denoting importance (ctrl+b)

User agents should allow users to denote importance in editing hosts. The exact interface for this is implementation dependent.

When text is selected the each series of one or more text nodes sharing a common ancestor must be placed inside a strong element node. When no text is selected the action acts like a boolean. When denoting importance is turned off it must be turned on and the other way around.

Denoting emphasis (ctrl+i)

Must be implemented equivalent to denoting importance with the exception that this is about the em element node.

Underlining text (deprecated, ctrl+u)

Must be implemented equivalent to denoting importance with the exception that this is about the u element node.

Treatment of elements

The img element

img elements inside an editable region can be selected, resized (with respect to their containing block) and copied. The first time you resize the img element its height and width attribute must be set. If you later resize the img again the height and width attribute must remain unchanged and the style attribute must be used instead to set the height and width properties from CSS. If the height and width attributes were already set they must not be changed by the UA.

The input and button elements

It is non conforming that the size attribute is set as the attribute is deprecated, but that is what Internet Explorer does. Actually, setting the style attribute...

input and button elements inside an editable region can be selected, resized (with respect to their containing block) and copied. The height and width of the elements must be set using the style attribute using the height and width properties from CSS. Resizing an input element must result in the size attribute to be set.

The UA must provide a way for entering default values for input elements with a type attribute value of text, password, button, submit, reset. The value entered must result in the value attribute to be set. UA must also provide a way to set the checked boolean attribute on input elements with a type attribute value of radio or checkbox. For type is radio UAs must only provide this interface when a name attribute is set.

execCommand method

interface ExecCommand {
  boolean execCommand(in DOMString commandIdentifier [, in boolean userInterface , [ in DOMString value ]] );
}

The commandIdentifier argument is case-insensitive.

This part needs careful checking.

The userInterface argument specifies if a user interface should be activated for the particular commendIdentifier using the value true. When no user interface is available it does not matter whether the value is true or false. When the value of the argument is true the third optional argument, value, must be ignored. The default value is false, except when commandIdentifier equals createLink.

The value of the value argument depends on commandIdentifier and is relevant when no user interface is available or when userInterface is set to false.

Unless specified otherwise userInterface and value may be passed as arguments, but must be ignored by UAs. When value is required and nothing is said about userInterface, userInterface must be either true or false.

Possible values for the commandIdentifier are outlined below with a description on how they can be used and must be implemented. Deprecated values may be implemented.

backColor (deprecated)

value must be a <color> value as defined in CSS 2.1. # may be omitted for three-digit and six-digit RGB notation.

When text is selected each series of one or more text nodes sharing a common ancestor must be placed inside a font element node. This element has a style attribute set using the background-color property from CSS to denote the color. The color must match value with the exception that three-digit and six-digit RGB color values with must be prefixed with # when it was omitted.

When no text is selected the command acts like a boolean. See denoting importance on how it must be treated.

bold

Must be implemented equivalent to denoting importance.

createLink

When userInterface and value are not set and no editing host has focus a widget must be shown to the user and the link entered by the user must be inserted directly before the first text node inside document.body as <a href="link">link</a>. If there is no text node, but an element and that element is not an editing host the link must be inserted at the start of the element. If it is an editing host the link must be created before the it.

When userInterface and value are not set and a editing host has focus the same applies with the exception that the link is inserted at cursor position.

When userInterface and value are not set and text is selected a widget must be shown to the user and the link entered by the user must be applied on the selected text. If the selected text spans over multiple block level elements each block level element will get an a element inside to wrap the selected text with as value for the href attributed the entered link.

When userInterface is set and value is not the situation does not change. Regardless of the value of userInterface.

When userInterface is set to true and value is set, the situation does not change.

When userInterface is set to false and value is set the command works as described above, with the exception that no widget is supplied and the value of value is used as link.

delete

Is this useful? Should there be a section under basic actions as this maps to delete.

The selected text must be removed from the DOM. When no text is selected the characters after the current cursor position must be removed one by one for each time the action is called.

fontName (deprecated)

value must match a valid value for the font-family property from CSS 2.1.

When text is selected it must be wrapped inside a font element with a face attribute set which takes the value argument as value.

When no text is selected the command acts like a boolean. See denoting importance on how it should be treated.

fontSize (deprecated)

It seems conflicting with the DOM interface that you can pass an integer as value, but Internet Explorer supports it.

value must be set and takes a floating point as value. The floating point may be passed as string or as integer and denotes the size.

value must be computed to an integer. When value is higher than 7 size is 7 and when it is lower than 1 size is 1.

When text is selected it must be wrapped inside a font element with a size attribute set which takes size as value.

When no text is selected the command acts like a boolean. See denoting importance on how it should be treated.

Internet Explorer also supports 0,2 (becomes 2) and 3,2 (becomes 7) as string arguments for value. Do we want to specify that or do we want to say browsers are free to do some error recovery when value does not match a floating point or a floating point denoted as string? (That seems to go against the idea of WHATWG.)

foreColor (deprecated)

Treated identically to backColor with the exception that here a color attribute is applied on the font element and not a style attribute. The color attribute takes the same value as the background-color property did defined in backColor.

formatBlock

value must be set and takes one of the following values: normal, heading 1, heading 2, heading 3, heading 4, heading 5, heading 6 or a block level element nodeName prefixed with < and suffixed with >. (A block level start tag without attributes or whitespace.)

indent (deprecated, for now)

Broken for lists in Internet Explorer. You get trees like ul - ul - ul - li.

The element currently edited inside an editing host will get indented. For most element this happens by wrapping blockquote element with a dir attribute set to ltr and a style attribute set to MARGIN-RIGHT: 0px. Exceptions to this rule are the li element...

insertButton

When value is passed as argument UAs must use it as the id attribute value to be specified on the inserted button element.

When text is selected the text must be replaced with the button element. When no text is selected and an editing host has focus the button element must be inserted on cursor position.

When inserting multiple button elements without changing the value of value the document may become invalid as all will have the same id attribute value.

insertFieldset

Must be implemented equivalent to insertButton with the exception that a fieldset element must be inserted.

insertHorizontalRule

Must be implemented equivalent to insertButton with the exception that a hr element must be inserted.

insertIframe

Must be implemented equivalent to insertButton with the exception that an iframe element must be inserted.

insertImage

When userInterface is omitted or is set to false and value is omitted an img element without attributes set must be inserted.

When userInterface is set to true, value must be ignored. The user should be given a user interface where he can set values for the following attributes: src, alt, hspace (deprecated), vspace (deprecated), border (deprecated) and align (deprecated).

When userInterface is set to false and value is set value specifies the value of the src attribute of the img element.

When text is selected it is replaced by the img element with zero or more attributes set (as described above). When no text is selected and an editing host is focused the img element must be inserted on the current cursor position.

insertInputButton

Must be implemented equivalent to insertButton with the exception that a input element with the type attribute set to button must be inserted.

insertInputButton

Must be implemented equivalent to insertButton with the exception that a input element with the type attribute set to button must be inserted.

insertInputCheckbox

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to checkbox.

insertInputFileUpload

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to file.

insertInputHidden

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to hidden.

insertInputImage

There is no way to set an alt attribute value. Would be nice if we define a user interface for this so that the userInterface argument does matter for insertInputImage.

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to image.

insertInputPassword

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to password.

insertInputRadio

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to radio.

insertInputReset

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to reset.

insertInputSubmit

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to submit.

insertInputText

Must be implemented equivalent to insertInputButton with the exception that the type attribute must be set to text.

insertOrderedList

The element inside the editing host that currently has focus becomes an ol element with a li element as child that will have the same value as the element that had focus. When the element already is an ol element it will become a p element.

This seems to be more complicated as described above in Internet Explorer. We need a serious amount of testcases to document this more properly.

insertParagraph

Must be implemented equivalent to insertButton with the exception that a p element must be inserted.

insertSelectDropdown

Must be implemented equivalent to insertButton with the exception that a select element must be inserted.

We should probably define a way to create option elements in a simple way as well.

insertSelectListbox

Must be implemented equivalent to insertButton with the exception that a select element must be inserted with the boolean multiple attribute set.

insertTextarea

Must be implemented equivalent to insertButton with the exception that a textarea element must be inserted.

insertUnorderedList

Must be implemented equivalent to insertOrderedList with the exception that a ul element must be inserted.

italic

Must be implemented equivalent to denoting emphasis.

justifyCenter (deprecated)

When editing a p element inside an editing host the p element must get a align attribute set with the exact value center. When not editing a p element inside an editing host a div element must get inserted with the align attribute set to the exact value center.

justifyFull (deprecated)

Must be implemented equivalent justifyCenter with the exception that align must be set to the exact value justify.

justifyLeft (deprecated)

Must be implemented equivalent justifyCenter with the exception that align must be set to the exact value left.

justifyNone (deprecated)

Must be implemented equivalent justifyCenter with the exception that the align attribute must be removed.

justifyRight (deprecated)

Must be implemented equivalent justifyCenter with the exception that align must be set to the exact value right.

outdent (deprecated, for now)

Must do the opposite of indent.

overWrite

This is basically insert and it does not make sense to have an editing command for it.

...

print

This is basically ctrl+p and it does not make sense to have an editing command for it. (Or window.print().)

...

redo

This is basically ctrl+y and it does not make sense to have an editing command for it.

...

refresh

This action resets the DOM to it original content when the document was first loaded. Browsers should store that state so it does not require a reload of the page.

removeFormat

This should be more clearly defined.

Removes all stylistic information from the current selection or ancestor nodes of the current cursor position.

saveAs

Allows users to save the actual source code of the page. DOM modifications are thus not part of it. The optional value argument specifies the suggested file name for the document. UAs may modify the suggested file name. (They may remove the string .html for example.)

...

selectAll

This is basically ctrl+a and it does not make sense to have an editing command for it.

strikeThrough (deprecated)

Must be implemented equivalent to denoting importance with the exception that there is no default keyboard equivalent specified and the element must be strike.

subscript

Must be implemented equivalent to denoting importance with the exception that there is no default keyboard equivalent specified and the element must be sub.

superscript

Must be implemented equivalent to denoting importance with the exception that there is no default keyboard equivalent specified and the element must be sup.

underline

Must be implemented equivalent to underlining text.

undo

This is basically ctrl+z and it does not make sense to have an editing command for it.

...

unlink

...

unselect

Deselects the current selection.

execCommand arguments mapping defined

This section is informative

The execCommand takes two optional arguments (userInterface and value). The following table specifies if they apply. In addition it is specified what value the value argument can take if applicable.

commandIdentifieruserInterfacevalue
backColor-<color> value
bold--
createLinkSpecifies whether or not a user interface must be shownSpecifies link when userInterface is false
delete--
fontName-Specifies value font-family property of CSS 2.1 could take
fontSize-Specifies size
foreColor-<color> value
formatBlock-Specifies block level element
indent--
insertButton-Specifies id attribute value
insertFieldset-Specifies id attribute value
insertHorizontalRule-Specifies id attribute value
insertIFrame-Specifies id attribute value
insertImageSpecifies whether or not a user interface must be shownSpecifies src when userInterface is false
insertInputButton-Specifies id attribute value
insertInputCheckbox-Specifies id attribute value
insertInputFileUpload-Specifies id attribute value
insertInputHidden-Specifies id attribute value
insertInputImage-Specifies id attribute value
insertInputPassword-Specifies id attribute value
insertInputRadio-Specifies id attribute value
insertInputReset-Specifies id attribute value
insertInputSubmit-Specifies id attribute value
insertInputText-Specifies id attribute value
insertMarquee-Specifies id attribute value
insertOrderedList-Specifies id attribute value
insertParagraph-Specifies id attribute value
insertSelectDropdown-Specifies id attribute value
insertSelectListbox-Specifies id attribute value
insertTextArea-Specifies id attribute value
insertUnorderedList-Specifies id attribute value
italic--
justifyCenter--
justifyFull--
justifyLeft--
justifyNone--
justifyRight--
outdent--
overWrite--
print--
redo--
refresh--
removeFormat--
saveAs--
selectAll--
strikeThrough--
subscript--
superscript--
underline--
undo--
unlink--
unselect--

How contentEditable maps to the designMode DOM attribute

designMode is a DOM attribute of the document interface that takes a DOMString as value. It can have the following case-insensitive values: on, off and inherit where off and inherit must be implemented equivalent.

document.designMode = "on" must be implemented equivalent to document.body.contentEditable = "true" with the exception that scripting inside the document is no longer supported and it can not be overwritten by elements setting the contentEditable attribute to false.

The disabled attribute

disabled is needed as equivalent for disabled on form controls. Unless developers say it is not.

This should basically be a global attribute (same for the disabled DOM attribute) with special semantics when applied to certain elements.

Acknowledgements