Friday, 27 February 2009

Is the NoScript tag the tag of the devil?

I came to the realisation today that the noscript tag is the sporn of the devil. It encourages developers to think of JavaScript in black and white, it's either on or off, the users support it or they don't. Unfortunately this simplistic approach can leave your users frustrated and thinking your site is broken. Consider this over heard conversation...


Project manager:
"Why doesn't the site work on my Blackberry?"
Developer:
"We don't support the Blackberry"
Project manager:
"but I thought you said it works without CSS and JavaScript?"
Developer:
"yes it works fine without CSS and JavaScript, we've built it in semantic HTML"
Project manager:
"so it should work on anything that understands HTML?"
Developer:
"... yes ..."
Project manager:
"so why doesn't it work on the Blackberry??"
Developer: ".... err ....


The NoScript tag has struck, pretty much all user agents support JavaScript. Much better to use progressive enhancement instead.

Consider this:


<noscript>
<p>
Important information for users without JavaScript
</p>
</noscript>
<script type="text/javascript">
if (document.getElementById){
// do funky things
...
}
</script>



We have just created a crack down the back of the sofa which has swallowed every user-agent that supports javascript but doesn't support document.getElementById or doesn't get the JavaScript in the first place. These users don't get the JavaScript enhancement and they don't get the noscript fallback : (

Tuesday, 24 February 2009

Are images enabled?

If your not sure what image replacement is, it's a technique to replace a bit of text (often an H1 level header) with an image. It's not really a very good idea, for one thing it creates a no fall back situation, e.g. you hide the text and put in a nice background image, which, if images are disabled the user can't see (oops!) and since it's a background image there is no alt text, hence no fall back, just an empty space.

So what to do? Using progressive enhancement you wouldn't want to implement something unless you know it's supported, you can use JavaScript to test if images are enabled and then add a class name to the html tag is one way to go.

Browsers seem to fall into two camps when images are turned off. Ones that don't load images at all and ones that load all img tags with an empty image. So you need to create two tests, first attach an onload function to an image you know exists, this will not fine on browsers that don't load images at all.

e.g...

var existentimg = new Image;
existentimg.onload = function(){
// if this didn't fine, images aren't enabled
}
existentimg.src = "know_to_exist.png";



As the above will fire on browsers that load images when images are disabled you need to do the same test again but this time attach the onload to an image you know does not exist.

e.g...

var nonexistentimg = new Image;
nonexistentimg.onload = function(){
// if this fires, images are disabled
}
nonexistentimg.src = "/nonexistent.gif";



I've put an example function at the bottom of this page that combines the two functions.

What to do with the info when you have it? Once you know if the user-agent has images enabled you can add a class name (e.g. "img") to the HTML tag, this will provide a way of using the information in your CSS.

e.g...

/* these styles will only be implemented if images are enabled */
html.img h1 {background-image:url(H1.png);width:XXXpx;height:XXpx;}
html.img h1 span {position:absolute;left:-9999px;}


Anonymous JavaScript function example, run this on DOM ready


(function(existingimageurl){
var existentimg = new Image;
existentimg.onload = function(){
document.getElementsByTagName('html')[0].className+= " img";
var nonexistentimg = new Image;
nonexistentimg.onload = function(){
document.getElementsByTagName('html')[0].className = document.getElementsByTagName('html')[0].className.replace(/\bimg\b/,"");
}
nonexistentimg.src="/nonexistentimg.png";
}
existentimg.src = existingimageurl || (document.images.length?document.images[0].src:'http://www.google.co.uk/images/nav_logo.png');
})();


If your using jQuery (or something similar) and you know there is at least one image on your page...


$(document).ready(function(){
(function(){
var existentimg = new Image;
existentimg.onload = function(){
$('html').addClass('img');
var nonexistentimg = new Image;
nonexistentimg.onload = function(){
$('html').removeClass('img');
}
nonexistentimg.src="/nonexistent.gif";
}
existentimg.src = document.images[0].src;
})();
})

Saturday, 21 February 2009

JavaScript support, who does, who doesn't?

JavaScript or lack of is a thorny issue, but if we take a quick look at some of the user groups that this effects:

1: User agents that don't have JavaScript enabled. As a lot of user tracking software relies on JavaScript to work so it's hard to tell how many users actually don't have JS, but in the beginning of 2009 it could be about 6%. Made up of user-agents that don't support JS, user-agents that have it turned off as part of company policy and user-agents routed though a proxy (e.g. public proxies normally don't support JavaScript)

2: User-agent that you haven't tested your JavaScript on. Just because a user-agent supports JavaScript doesn't mean your script will work (ever done this: if (!document.getElementById){return} ? ), even the four (webkit/moz/opera/ie) main desktop browsers diverge radically in some areas, meaning that there is a good chance that you scripts may not work on anything you haven't tested them on.

3: User-agents where your script is meaningless. e.g. if the user is using a small screen (or zoom software) and they click on a DHTML link that moves some page content from out of view left (eg. margin-left:-9999px) to out of view right (e.g. margin-left:800px;). In these cases JavaScript is no help to the user.

4: Assistive technologies: Most assistive technologies like screen-readers run on the top of your normal browser so although the browser understands JavaScript the assistive technology may not. They may not see things you have written in with JavaScript rendering your JavaScript content inaccessible.

There are probably other user groups effected, will add when they come to mind...

So our user groups fall in to a number of categories...

1. users with browsers that don't support JavaScript at all, or have JavaScript turned off
2. users with browsers can't run your scripts (they error or don't support DOM)
3. users accessing your site though anal proxy, firewall etc...
4. users for whom your JavaScript is redundant (not really any help)
5. users for whom your JavaScript is actively blocking access to content
 

Note: the opinions on this page don't represent that of my employer in anyway. And, actually only vaguely represent my opinions on the date of publication. (Unlike Ms T, I am very much for turning)