With regards to Drew’s recent post Internet Explorer’s mishandlings of BUTTONs, I thought I would post a solution I came up with whilst serving at Yahoo! for the new Ask/Answer flow.
What’s the problem?
For those of you who’ve not read Drew’s above–linked post (you should, it explains the problem concisely), the issue can be broken down thusly:
BUTTONelements are good to use for “Web 2.0” styling like rounded corners, because they allow elements to be nested inside them (in our case, emptySPANs or similar);- Internet Explorer mis-handles the
BUTTONs by sending the entire contents (equivalent toinnerHTML) along to the server, rather than the definedvalue; - This means you need to fork your server side code to deal with the possibility of the content not being what you expect.
What’s the problem with Drew’s method?
Nothing major, except that it all depends on the way he “(throws) the
”. If he’s just using off–left, screen readers will still be able to see the content, which in his example is “SPAN off-screen with CSSABC123
”: whilst this is only present for the example given, could theoretically be anything. Either way it’s unlikely to be relevant to a screen–reader (or a search crawler, when it comes down to it).
As I stated, it’s very minor nit–picking. But what is the Internet for if not to nit–pick (or to call people Nazis)?
So what’s my solution?
Despite Drew being entirely correct when he said that a solution that relies on JavaScript isn’t a solution
, I’m going to do one anyway. Key features include:
- Graceful degradation: in all browsers without Javascript enabled regular
input type="submit"elements are used; - Allows for extra styling: spurious (and quite horrible) extra
spanelements are inserted, allowing for bonus styling hooks; and - Accessibility is enhanced: since Internet Explorer famously has fail with regards to CSS pseudo-class selectors, and given these are essential for keyboard users (to simulate mouseover etc.), we add in some event handling to enhance the buttons for IE mouse/keyboard users.
Note that no CSS is provided: this is left as an exercise for the reader. Also note that it’s written for a site using the YUI library, which is the front–end framework of choice where this code was originally written.
Also bear in mind this this comes with a really really big caveat.
<form action="" method="post">
<-- other FORM fields before (remembering our LABELs and FIELDSETs!!)-->
<div>
<input type="submit" class="cta" name="my-submit" value="Save Application">
</div>
</form>
<!-- we need the YUI basics -->
<script type="text/javascript"
src="http://yui.yahooapis.com/2.5.2/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript">
// namespaced to "EUropean User Interface"
YAHOO.namespace('EU.UI');
// CTA stands for "call to action", a standard Yahoo! term for a rounded corner button
YAHOO.EU.UI.cta = function() {
function fixSubmit(e) {
// this function is only fired for browsers which don't understand
// button type="submit", so we're okay to proceed without browser
// checking
// clobber default behaviour
YAHOO.util.Event.preventDefault(e);
var form = this.form;
// IE will submit all buttons at once, so kill/disable the ones we didn't click
var els = form.getElementsByTagName('button');
if (els.length > 0) {
for (var i=0, l=els.length; i<l; i++) {
// check if it's the same element--name isn't reliable as
// there could be multiple forms with the same named element
if (els[i] !== this) {
// note this will cause a "flash" of greyed out buttons
els[i].disabled = true;
}
}
}
// now that all buttons except the one that was clicked are disabled,
// send the form along with just the button clicked
form.submit();
}
return {
init : function() {
var els = YAHOO.util.Dom.getElementsByClassName('cta', 'input');
// these could be anything--just use them as styling hooks
var startContent = '<span><span><span><span>';
var endContent = '<\/span><\/span><\/span><\/span>';
if (els.length > 0) {
for (var i=0, l=els.length; i<l; i++) {
var el = els[i];
if (el.type.toLowerCase() === 'submit') {
// do transform
var newCta = document.createElement('div');
// add additional classes ('secondary', 'right' etc.)
newCta.className = el.className;
var button = document.createElement('button');
button.name = el.name;
button.value = el.value;
button.innerHTML = startContent + el.value + endContent;
newCta.appendChild(button);
el.parentNode.replaceChild(newCta, el);
// fix the submit
try {
button.type = 'submit';
}
// IE errors out on the above, so we now know we're dealing with IE
catch (err) {
YAHOO.util.Event.on(button, 'click', fixSubmit);
}
// fix :focus and :active pseudo-class for all IE for keyboard navigation
if (YAHOO.env.ua.ie > 0) {
YAHOO.util.Event.on(button, 'focus', function(e) {
YAHOO.util.Dom.addClass(this, 'hover');
});
YAHOO.util.Event.on(button, 'blur', function(e) {
YAHOO.util.Dom.removeClass(this, 'hover');
});
YAHOO.util.Event.on(button, 'click', function(e) {
YAHOO.util.Dom.addClass(this, 'active');
});
}
}
}
}
}
}
}();
// above () returns the function immediately, causing the inner functions to be "private"
// fire public init method on DOMReady event
YAHOO.util.Event.onDOMReady(YAHOO.EU.UI.cta.init);
</script>
“You use(d) Javascript for presentation you bad bad man”
Yes I do. Well, I did (I only did this type of thing once). Glad you’ve been paying attention. I believe I’m okay doing this for a few reasons (so listen closely):
- The HTML remains un–polluted. I believe this to be of prime important, as HTML is the only part of the web standards “trinity” (HTML, CSS, and Javascript) that is always delivered to all user agents;
- The Javascript used does not detract from the accessibility in any way; and
- Sometimes the presentation is important enough for your audience or goal that you need to do things like this. Call it an over–optimisation in the name of: accessibility over separation–of–concerns purity, and brand/design requirements.
You may, as is your wont, disagree. That’s okay, but before I get flamed (which I can’t, given that I still don’t have comments enabled), I want it to be known that this script was produced under the above caveats. As usual, YMMV. Just don’t go doing this type of thing often.
Comments are not enabled for this post.