I put together a new release of the Validator.nu HTML Parser. This is a highly recommended update for everyone who is using a previous version the parser in an application.
- Fixed an issue where under rare circumstances attribute values were leaking into element content.
- Fixed a bug where
isindex
processing added attributes to all elements that were supposed to have no attributes.
- Implemented spec changes. (Too numerous to enumerate, but, as a highlight, framesets parse much better now.)
- Moved to WebKit-style foster parenting.
- Changed the API for tree builder subclasses again due to new constraints. If you have previously written your own tree builder subclass, you need to change it.
- Fixed the bundled XML serializer.
- Made it possible to generate a C++ version that does not leak memory from the Java source.
- Removed the C++ translator from the release. (Get it from SVN.)
Posted in Processing Model, Syntax | Comments Off on Validator.nu HTML Parser 1.2.0
HTML 5 introduces new elements like <section>, <article> and <footer> for structuring the content in your webpages. They can be employed in many situations where <div> is used today and should help you make more readable, maintainable, HTML source. But if you just go through your document and blindly replace all the <div>s with <section>s you are doing it wrong.
This is not just semantic nit-picking, there is a practical reason to use these elements correctly.
In HTML 5, there is an algorithm for constructing an outline view of documents. This can be used, for example by AT, to help a user navigate through a document. And <section> and friends are an important part of this algorithm. Each time you nest a <section>, you increase the outline depth by 1 (in case you are wondering what the advantages of this model are compared to the traditional <h1>-<h6> model, consider a web based feedreader that wants to integrate the document structure of the syndicated content with that of the surrounding site. In HTML 4 this means parsing all the content and renumbering all the headings. In HTML5 the headings end up at the right depth for free). So a document like the following:
<body>
<h1>This is the main header</h1>
<section>
<h1>This is a subheader</h1>
<section>
<h1>This is a subsubheader</h1>
</section>
</section>
<section>
<h1>This is a second subheader</h1>
</section>
</body>
has an outline like:
This is the main header
+--This is a subheader
+--This is a subsubheader
+--This is a second subheader
If you just blindly convert all the <div>s on your pages to <sections> it's pretty unlikely your page will have the outline you expected. And, apart from being a semantic faux-pas, this will confuse the hell out of people who rely on headings for navigation.
Hopefully, in time, we will get tools that make this kind of mistake obvious and CSS support for selecting headings based on depth. Until then remember <section> is not just a semantic <div>
Posted in Elements, Tutorials | 24 Comments »
We have previously talked about how to get Internet Explorer to play ball when using the new HTML5 elements, but today I'm going to talk about Firefox 2.
Firefox 2 (or any other Gecko-based browser with a Gecko version pre 1.9b5) has a parsing bug where it will close an unknown element when it sees the start tag of a "block" element like p
, h1
, div
, and so forth. So if you have:
<body>
<header>
<h1>Test</h1>
</header>
<article>
<p>...</p>
...
</article>
<nav>
<ul>...</ul>
</nav>
<footer>
<p>...</p>
</footer>
</body>
...then in Firefox 2 it will be parsed as if it were:
<body>
<header>
</header><h1>Test</h1>
<article>
</article><p>...</p>
...
<nav>
</nav><ul>...</ul>
<footer>
</footer><p>...</p>
</body>
So if you style the new elements with CSS it will probably look completely broken in Firefox 2.
If you care about Firefox 2 then there are some ways to fix this:
- Go back to using
div
elements
- Use content type negotiation between
text/html
and application/xhtml+xml
- Fix up the DOM with scripting
(1) is probably wise if your content structure changes between pages or over time. (2) also works but means that users will be exposed to the Yellow Screen of Death should a markup error slip through your system. Otherwise (3) can be worth to consider.
Fixing up Firefox 2's DOM is actually pretty simple if you have a consistent structure. Using the same markup as above it could look something like this:
<body>
<header>
<h1>Test</h1>
</header>
<article>
<p>...</p>
...
</article>
<nav>
<ul>...</ul>
</nav>
<footer>
<p>...</p>
</footer>
<!--[if !IE]>--><script>
// dom fixup for gecko pre 1.9b5
var n = document.getElementsByTagName('header')[0];
if (n.childNodes.length <= 1) { // the element was closed early
var tags = ['ARTICLE', 'NAV', 'FOOTER', 'SCRIPT'];
for (var i = 0; i < tags.length; ++i) {
while (n.nextSibling && n.nextSibling.nodeName != tags[i]) {
n.appendChild(n.nextSibling);
}
n = n.nextSibling;
}
}
</script><!--<![endif]-->
</body>
You might think that this script would work for IE, too, when not using the createElement hack, but apparently IE throws an exception when trying to append a child to an unknown element. So you still have to use the createElement hack for IE.
If you want to move the script to head
and run it on load and you don't have anything after the footer then you would replace 'SCRIPT'
in the tags
array with undefined
to make it work.
(If you want to do content type negotiation and want to just serve XHTML to Gecko-based browsers with this bug then you should look for the substrings "Gecko/" and "rv:1.x" where x is less than 9, or "rv:1.9pre" or "rv:1.9a" or "rv:1.9bx" where x is less than 5.)
Posted in Browsers, DOM, Elements | 17 Comments »
Welcome back to "This Week in HTML 5," where I'll try to summarize the major activity in the ongoing standards process in the WHATWG and W3C HTML Working Group. The pace of HTML 5 changes has reached a fever pitch, so I'm going to split out these episodes into daily (!) rather than weekly summaries until things calm down.
The big news for February 13, 2009 is r2814/r2815, which adds a .value
property on file upload controls:
On getting, [the .value
property] must return the string "C:\fakepath\"
followed by the filename of the first file in the list of selected files, if any, or the empty string if the list is empty. On setting, it must throw an INVALID_ACCESS_ERR
exception.
According to bug 6529, Opera already implements something close to this, and is willing to modify their implementation to match the spec text.
The other big news of the day is r2804/r2805, which defines what happens when a focused element becomes hidden.
For example, this might happen because the element is removed from its Document
, or has a hidden
attribute added. It would also happen to an input
element when the element gets disabled.
But let's back up a step. What does it mean for an element to be "focused" in the first place? The spec has a whole section on the concept of focus. The short answer is that focus is just what you think it is: it's the element that responds when you type. As you tab around a form, the focus moves between form fields, where you can type information; as you tab around a page, the focus moves between links, which you can follow; if you tab long enough, focus moves out of the page and back to the location bar, and so forth.
The not-so-short answer that everything in the previous paragraph is platform-specific and, depending on your browser, highly customizable. The HTML 5 spec respects these platform differences, and defers the definition of what elements should be focusable to the browser, which ultimately respects the conventions of the underlying operating system.
The long answer is that virtually anything can be focusable, because HTML 5 standardizes a crucial accessibility feature that most modern browsers now implement, namely that any element can have a tabindex
attribute.
It may not sound like it, but this is a really, really important feature for building accessible web applications. HTML 4 restricted the tabindex
attribute to links and form fields. For reasons unknown, Internet Explorer ignored that and respected a tabindex
attribute on any element. Starting with Firefox 2, Mozilla co-opted this implementation and wrote up a rough "standard" about using the tabindex
attribute on anything. Once it was implemented in the browser, IBM contracted with major screenreader vendors to support Firefox's (and IE's) behavior. This provided the foundation for pure-Javascript widgets to become keyboard-accessible (also implemented by IBM). Not just theoretically, but actually, in real shipping browsers and real shipping screenreaders. Under the covers, Dojo's complex widgets are marked up with semantically meaningless <div>
s and <span>
s, yet they are still focusable and keyboard-navigable. The controls are in the tab order, so you can focus with the keyboard, then you can use the keyboard to further manipulate them, change their state, and so forth.
In HTML 4, there was no way to put custom controls into the tab order without breaking markup validity (unless you futzed around with custom DTDs or scripting hacks), because the tabindex
attribute could only be used on links and form fields. HTML 5 "paves the cowpaths" and standardizes this definition and behavior of tabindex
-on-anything. This is a huge step forward for web accessibility. The concept of focus is central to accessibility, and HTML 5 gives it the attention it deserves. (There's more to making controls accessible than just keyboard navigability, but if you don't have keyboard navigability, nothing else really matters. If you're creating your own custom Javscript widgets, you must read the (non-vendor-specific) DHTML Style Guide for implementing keyboard accessibility in custom controls.)
Now then, why is r2804 important? Well, if the element that has focus suddenly can't have focus anymore -- because it was programmatically hidden or disabled, or it was removed from the DOM altogether -- then it is vitally important to specify where the focus goes. So the HTML 5 specification lays it all out:
When an element that is focused stops being a focusable element, or stops being focused without another element being explicitly focused in its stead, the user agent should run the focusing steps for the body element, if there is one; if there is not, then the user agent should run the unfocusing steps for the affected element only.
[Background reading: Re: Lose Focus When Hidden? (SVG ISSUE-2031)]
Other interesting changes of the day:
- r2807 simplifies the definition of
window.onerror
.
- r2810 makes the presence of a
<noframes>
element a non-ignoreable error for validators. (It was previously a "downplayed error.")
- r2811 defines that "
this
" in the Javascript global scope, should return a WindowProxy
object instead of a Window
object. I confess I have no idea what that means or why it's important. Perhaps a commenter could enlighten me?
- r2812 updates the way browsers should determine character encoding (using known aliases of common encodings).
- r2817 adds "transparent" to the list of colors that need to be parsed in an IE-compatible way.
- r2818 notes that putting a document in
designMode
does not actually prevent it from executing scripts.
Tune in... well, sometime soon-ish for another exciting episode of "This Week Day In HTML 5."
Tags: accessibility, thisweekinhtml5
Posted in Weekly Review | 1 Comment »
Welcome back to my semi-regular column, "The Road to HTML 5," where I'll try to explain some of the new elements, attributes, and other features in the upcoming HTML 5 specification.
The feature of the day is contentEditable
, by which I mean client-side in-browser "rich text" editing. All major browsers support this now, including Firefox 3, Safari 3, Opera 9, Google Chrome, and Internet Explorer (since 5.5). Of course, the devil is in the details.
In this article:
What is contentEditable
?
There are really two attributes involved, designMode
and contentEditable
. The designMode
attribute governs the entire document (i.e. it makes the entire document editable, like a dedicated HTML editor). The contentEditable
attribute governs just the element on which it appears, and that element's children -- like a rich text editor control within a page. In fact, that was the original use case: enabling web developers to build rich text editors. There are now a variety of such editors available under various licenses.
Both of these attributes, designMode
and contentEditable
, were originally designed and implemented by Microsoft in Windows Internet Explorer (5.5, to be exact). There was some superficial documentation on how to use them (so developers could develop rich text editors), but little thought of interoperability. So, no details on all the nitty gritty details of exactly what markup is generated when you press ENTER right here, or what the DOM looks like as you backspace your way through a start tag. Much of this sort of information was later reverse-engineered, and cross-browser support for basic operations is actually quite good. (Browsers still vary widely on the details.) The designMode
and contentEditable
attributes, and the APIs that drive rich text editors, are implemented in all major browsers, including Firefox, Opera, Safari, Google Chrome, and of course Internet Explorer.
How does it work?
Mark Finkle wrote a nice high-level summary of designMode
, and later added a post about contentEditable
once it appeared in the Firefox 3 alphas. (That was back in 2007.) Quoting Mark:
Mozilla has a rich text editing system (called Midas) and an API similar to Internet Explorer's. Mozilla, like Internet Explorer, supports the ability to make an entire document editable by setting the designMode property of the document object. Once in design mode, the document can be manipulated using various DHTML commands.
... Firefox 3 is expanding its rich WYSIWYG editing capabilities by adding support for the contentEditable attribute. Setting contentEditable to "true" allows you to make parts of a document editable. ...
The API for interacting with the document is:
- document.execCommand
- Executes the given command.
- document.queryCommandEnabled
- Determines whether the given command can be executed on the document in its current state.
- document.queryCommandIndeterm
- Determines whether the current selection is in an indetermined state.
- document.queryCommandState
- Determines whether the given command has been executed on the current selection.
- document.queryCommandValue
- Determines the current value of the document, range, or current selection for the given command.
Once you have an editable document (designMode
) or element (contentEditable
), you use this set of API calls to issue "commands" on the editable region, and to query the current state of the region. Commands are things like "bold," "italic," "underline," "create a link," "change foreground color," and so on -- all the commands you would expect from a rich text editor. Here's a test page with 36 commands.
In other words, "supporting the contentEditable
attribute" is really just the tip of the iceberg. The real compatibility story is written in the commands which are passed to the document.execCommand()
function. So which browsers support which commands?
As you can see from Peter's chart, basic stuff like bold, italic, creating links, and changing colors is well-supported across browsers. After that, the compatibility story gets hairy.
A brief and extremely biased timeline of standardization
Reverse-engineering and standardizing contentEditable
and its associated APIs was one of the original goals of the WHAT working group, as part of (what at the time was called) "Web Applications 1.0" and is now known as "HTML 5."
- July 2000. Microsoft releases Internet Explorer 5.5, with support for
designMode
and contentEditable
. Other than some sparse documentation on MSDN, no further details were given.
- November 2004. Ian Hickson: [whatwg] Re: several messages. "One set of the ideas that was brought up in this forum was the ability to extend <textarea> to support syntax highlighting, or WYSIWYG editing of BB code markup, or just the ability to do rich text editing of any kind. Having considered all the suggestions, the only thing I could really see as being realistic would be to do something similar to (and ideally compatible with) IE's 'contentEditable' and 'designMode' attributes."
- April 2005. Olav Junker Kjær: "I have been thinking about HTML editing, which I think is a critical feature."
- July 2005. Anne van Kesteren: begins to reverse-engineer Microsoft's
contentEditable
implementation.
- July 2005. Anne van Kesteren: [whatwg] [html5] contenteditable specification. The first message points to annevankesteren.nl/projects/whatwg/spec, while (somewhat surprisingly) still exists. An unfinished but fascinating piece of reverse engineering. (Most of this is now merged into the HTML 5 spec, in the Command APIs section.)
- July 2005. Anne van Kesteren: [whatwg] [html5] contenteditable specification (again)
- July 2005. Matthew Raymond: [whatwg] [WF2] Readonly and default pseudoclass matching. Discussion of how
contentEditable
interacts with proposed (and now standardized) pseudo-classes like :read-only
.
- August 2005. dolphinling: [whatwg] What exactly is contentEditable for?. Other than the obvious answer, "rich text editing," the discussion focused on how modified content is/could be/should be submitted to the server, and whether it could be implemented without scripting.
- September 2005. Ian Hickson: [whatwg] Status update. "Web Apps 1, a.k.a. 'HTML5'. Still very much work in progress. ... The main things that need fleshing out are: (1) contentEditable: at least to a state comparable to WinIE, although we might want to add some of the new features being requested on this list like declarative association with a form."
- September 2005. Matthew Raymond: [whatwg] Re: Simple template-based editing. Discussion of a (never-implemented)
<htmlarea>
element.
- June 2006. Lachlan Hunt: [whatwg] Spellchecking proposal #2. Discussion of how
contentEditable
interacts with the spellcheck
attribute. See also: Ian Hickson's feedback, with examples.
- July 2006. Anne van Kesteren: [whatwg] contenteditable="" needs fixing. (This later led to these test cases.)
- January 2007. Simon Pieters: [whatwg] contenteditable, <em> and <strong>
- January 2007. Anne van Kesteren: [whatwg] contenteditable="" values and isContentEditable
- February 2007. Ian Hickson: "I have added it to the now-written designMode section."
- April 2007. David Hyatt: "The use case of being able to drop images into a contenteditable region and have them show up as <img /> elements at the appropriate place and then get automatically uploaded somewhere is a really compelling one." See also: Ian Hickson's feedback, 19 months later.
- November 2008. Ian Hickson: "contentEditable is being made more consistent, but there's still no non-scripted solution, since nobody can agree on what elements to allow."
- December 2008. Ian Hickson: [whatwg] <input placeholder="">. Discussion of whether the
placeholder
attribute should also apply to contentEditable
regions and designMode
documents in an <iframe>
.
Conclusion
The original use case for contentEditable
-- building rich text editors -- is alive and well on the web. Cross-browser compatibility can be charitably described as "evolving," but we are long past the point where "only IE can do that fancy rich-text stuff." Standardization through the WHATWG has shaken out numerous interoperability bugs and led to thoughtful consideration of a wide variety of edge cases. Most of these benefits had to be realized through reverse engineering, rather than cooperation, but the work has been done and the web is better for it.
Further reading
Posted in Tutorials | 17 Comments »