Categories
HTML5 Specs

Cross-browser implementation of the progress element

A useful coincidence: just after I wrote my concerns about the progress element, the WebKit nightly contains the first implementation of this element.

I created an application to test the element. It works as I expected, and is somewhat accessible, though Mac’s VoiceOver would only voice the progress when the element first receives focus. Note, support for the element is only in Webkit nightly on the Mac.

I created a cross-browser version of the application that should work in most modern browsers—modern meaning IE8, not IE5.5, IE6, or even IE7. I had a heck of a time with the application.

The first challenge was the fact that IE8 doesn’t allow dynamic styling of the progress element, even if you use an HTML5 shim. What was more surprising was that Webkit on the PC and Chrome had problems with the progress element, period. Both kept giving me errors about a progress element within a div element, and neither would allow any form of dynamic access.

If you try to emulate the progress element’s effect, using the actual progress element in browsers that don’t currently support the element, setting the background-color for the element wipes out the progress effect with the Webkit nightly. Other than setting width and height, you can’t style the element. Or at least, I’m not sure how to style the element using general CSS properties.

I had to create a separate div element for those browsers that don’t implement progress. To make it work, I tested for progress element support, and if the browser does not support the element, turn off its display and turn on the display of the div element workaround. I had to test on the element’s form property to see if progress was supported. If you access the element, and it isn’t null, and the form property is defined, then the progress element is supported. You can’t test using nodeName, because all browsers return PROGRESS. Unfortunately, there is no elegant way to test for type of DOM object, such as HTMLProgressElement. There’s a hack I found at Sam Ruby’s weblog but that doesn’t work for IE, and again, Chrome and Webkit on the PC had problems with any programmatic access of the element.

You can’t provide a text description of the percentage by using the element’s innerHTML property. I didn’t try creating a new text node and attaching it to the progress element, but I don’t expect this approach to work, either.

You also can’t set a minimum value. The test case the WebKit developers attached for the new element uses the dir attribute to “reverse” the display.

update

I checked the HTML5 spec definition for progress again and found:

Content model:
    Phrasing content, but there must be no progress element descendants.

The HTML editing and WYSIWYG tools and validators are just going to love this. Anyway, supposedly this does mean that the element can take text. This must mean, then, that the Webkit implementation is incorrect.

second update

I created a variation of the application that embeds the fallback approach within the progress element itself. This seems to work fine. It cuts down a couple of lines of code, and at least looks a little more graceful (though it’s not valid). Note that I had to turn off the display of the elements by default, as Webkit nightly sets the background on the progress element to be transparent by default.

Last Update

The WebKit installation is most likely correct in its handling of the text for the progress element. According to the specification:

Authors are encouraged to also include the current value and the maximum value inline as text inside the element, so that the progress is made available to users of legacy user agents.

Though not a directive to the user agents, we have to assume from this statement that UAs are not supposed to display the text if the progress element is supported. However, the direction is unclear, one has to make an assumption that this is what’s happening in the browser.

This also means that if a person wants to include a text description of the progress, as I do in my original approach—something that happens frequently— you can’t. Instead, you’ll have to overlay the progress element with a div element and add the text to it.

You also have to use getAttribute and setAttribute to get and set the element’s value attribute. Accessing the attribute directly only works when the element is supported.

Frankly, I will never use the progress or meter elements. They are inferior, less accessible, more cumbersome options compared to what we have today. That the elements were poorly thought out is obvious when one tries to actually implement them.