Designing and Catering for Javascript

As progressive developers, we need to be mindful of the huge audience that the internet presents. There is a plethory or browsers, operating systems, devices, screen resolutions and technology. One item of technology that we sometimes "take for granted" is Javascript. With all the libraries that are available and because Javascript is relatively platform agnostic, we can sometimes assume that our finished project can use Javascript without causing any compatibility issues. But there are some instances when Javascript just will not run, and we need to cater for those scenarios.

Even though the numbers are quite small (according to Yahoo it's about 1%), it is still an issue that can seriously affect the user experience on your site. There are still some screen readers out there that do not support Javascript and some people just purposely turn it off. Some malicious sites use Javascript to deliver compromising code. Some sites (not ours, of course) have somewhat bloated Javascript files which can affect page loads and some people just like to disable Javascript because it will natually make a page load faster (less HTTP_REQUEST calls). To cater for these instances, we need to carefully plan the infrastructure of our sites so that even if Javascript is disabled, our functionality degrades well.

The latest CSS and HTML specifications offer more functionality to assist in this quest. For example, years ago we may have used Javascript to change the state of an element based on an event.

<input id="ClickMe" onmouseover="hover()" onmouseout="hoverout()" type="button" value="Go" />
function hover() { 
	var el = document.getElementById("something"); 
	el.style.backgroundColor = "#00ffff"; 
	el.style.color = "#000000"; 
}

Whereas, with HTML5 and CSS3, we can do this without Javascript.

#ClickMe:hover{ background: "#00ffff"; color: "#000000"; }

Voila, no Javascript.

Things can become a little more complex though. Say we have some important functionality in our page that requires Javascript. We need to carefully plan our sites so that the functionality does not compromise responsiveness. The best way I have found to ensure that functionality degrades well, is to add required functionality using Javascript. That way, functionality is reduced when Javascript is disabled, but the user doesn't have page "bloat" with elements and styles that do not function. Let me explain what I mean.

Our scenario is a page section that lists a number of items. These items are categorised and we want to allow the user to filter the list based on the categories.

<ul>
	<li>All</li>
	<li>Pears</li>
	<li>Apples</li>
	<li>Watermelons</li>
	<li>Oranges</li>
</ul>
<ul>
	<li><a class="apple" href="#">5 Apples</a></li>
	<li><a class="apple" href="#">2 Apples</a></li>
	<li><a class="orange" href="#">3 Oranges</a></li>
	<li><a class="pear" href="#">2 Pears</a></li>
	<li><a class="orange" href="#">1 Orange</a></li>
	<li><a class="watermelon" href="#">1 Watermelon</a></li>
	<li><a class="pear" href="#">5 Pears</a></li>
	<li><a class="watermelon" href="#">6 Watermelons</a></li>
</ul>

To make the filtering work, we just need some Javascript and JQuery to filter the list based on the classes.

$("#legend li a").click(function() {
	var $this = $(this); 
	var type = $this.attr("class"); 
	$("#legend li").hide() 
		.filter("." + type); 
		.show() return false; 
});

This will work fine with Javascript on. Even with Javascript disabled, the page will look OK, but think about the UL with ID legend. If Javascript is disabled, there is a list of links that do nothing when clicked. So what's the point? This will just frustrate the user and they may even blame the site for being "broken".

To remedy this, why not add the #legend UL with Javascript. That way, if Javascript is disabled, the UL won't be added to the DOM. The only affect for non-Javascript browsers will be that the filtering doesn't work. The beauty of this though, is that those users will not even know what they are missing out on.

var OptionList = "
<ul>
	<li>All</li>
	<li>Pears</li>
	<li>Apples</li>
	<li>Watermelons</li>
	<li>Oranges</li>
</ul>
"; $("#itemlist").before(OptionList) .children("li") .addClass("all");

Til next time ...