Solving a browser bug with invalid HTML

Recently, I’ve been involved in building Solar Stormwatch, a citizen science project which asks people to look for by watching videos of data recorded by the wide-field cameras on the STEREO spacecraft. We ask people a series of questions about each video and record their answers. The answers they submit then determine subsequent questions that they’ll be asked. Answers are tracked in the underlying API by assigning each answer a numerical ID, so the markup for an answer looks something like this (using HTML buttons for each answer):
<button value="2">Ahead</button>

If the site user wants to pick the answer ‘Ahead’ to a question, they click this button. With jQuery, I get the value of the button (2) using var answer_id = $(this).val(). Users confirm their answer by pressing a ‘Next’ button to move onto the next question:

<button id="next" value="">Next</button>

I decided to use the ‘Next’ button to store the currently selected answer: $('#next').val(answer_id). I can then look at the value of the ‘Next’ button to decide which question to ask next when they submit an answer. All fairly straightforward HTML and JavaScript, which works in any standards-compliant web browser.

However, after launching the site we started to get strange bug reports on the Solar Stormwatch forum. Buttons were displaying numbers instead of words as their labels. Questions were repeating rather than moving onto the next question for a given answer. It turns out there is a bug in IE6 and IE7, which was being picked up by our users — IE6 and IE7 do not support the value attribute on buttons.

In IE6 and IE7, calling $(this).val() returns the text of a button — ‘Ahead’ in the example given above. Similarly, setting .val() for a button sets the button text, not its value. My first reaction was to change my jQuery code to use .attr('value') to access the value attribute instead. This runs into exactly the same underlying browser bug — .attr('value') gets and sets the button text in IE6 and 7.

To solve this, and get the questions working in IE, I ended up changing the value attribute on buttons to data-value. This is invalid in HTML 4, though it will be valid in HTML 5.

<button data-value="2">Ahead</button>

This works, however, because the default behaviour of HTML parsers in all the major browsers is the same when they encounter an attribute they don’t understand. They simply add it to the DOM as a property of the current node ie. you get something like button.data-value=2. So, wherever I had used .val() in my jQuery code, I now use .attr('data-value') to get and set the value of buttons.

I’m not hugely happy with this solution. It’s invalid HTML and relies on default error-handling behaviour in HTML parsers. It does work cross-browser, and it is robust in that HTML parsers aren’t likely to change the way they handle unrecognised attributes. I wish Internet Explorer supported the standards-compliant, valid solution though.