Accessible JavaScript 101: Rotating Banners

By Forum Member Web Developer

As a web developer, we want everyone to be able to access our pages even when JavaScript isn't available to them. This tutorial will show you how to do just that with a Rotating Banner script.

Separation of structure from presentation is the cornerstone of accessible web design. This is the first core technique that is discussed whenever the subject of accessibility is brought up. This separation is achieved by using HTML to describe document structure and CSS to describe document presentation for different types of media.

The two are often compared to layers, HTML being the core layer accessible to all devices and CSS an optional outer layer for the devices capable of interpreting it.

When it comes to accessibility and client side scripting the same methodology should be applied. Scripting is just another layer that provides advanced functionality on top of the existing content and presentation.

Any web site will have up to three layers:
  • HTML defining document structure
  • CSS defining document presentation
  • JS providing additional functionality
When these layers are designed from core out, the accessibility is assured by the design process - each underlying layer is made to work before proceeding to the next one.

Rotating Banner Requirements

Links to affiliate web sites are not only for human visitors. Actually, human visitors rarely use those links - just think about how many times you have actually clicked on an advertisement banner in the past day or week. The greater advantage for having other sites link to yours is the better search engine rating. But this will only work if these links are accessible to the search engine bots.

Therefore, it only makes sense to have all affiliate links that make up rotating banners presented in HTML code.

Core Layer - Document Structure - HTML

The proper presentation for rotating banners is the list of links that can optionally be enclosed within a block element that also contains a heading:
<div id="banners">
  <h4>Affiliate Links</h4>
  <ul>
    <li><a href="www.google.com"><img alt="Search Web with Google" src="googlelogo.png"></a></li>
    <li><a href="www.yahoo.com"><img alt="Search Web with Yahoo" src="yahoologo.png"></a></li>
    <li><a href="www.msn.com"><img alt="Search Web with MSN" src="msnlogo.png"></a></li>
  </ul>
</div>

Presentation Layer - CSS

It is a reasonable assumption that the banner list will be placed towards the end of the HTML document while its presentation in the graphical browser will usually be at the top of the page. This can be achieved using the absolute positioning of the block containing the banners:
#banners
  { position: absolute;
    top: 10px; /* top coordinate */
    right: 10px; /* puts banners in the top right corner */
  }
Users of graphical browsers do not really need to see the header as the images are self explanatory. Also, the default border around images inside links is usually removed. And we want to make sure that there are no margins and padding that can affect presentation:
#banners h4
  { display: none;
  }

#banners img
  { border: none;
  }

#banners ul, #banners li, #banners a, #banners img
  { margin: 0;
    padding: 0;
  }
Another reasonable assumption is that all the banner images are of the same size. For illustration purposes let's say 200px wide by 80px high. We can make the height of the banners list the same as the images and setting the overflow to hidden will cause only the first banner visible as the default presentation of the page.
#banners ul
  { display: block;
    height: 80px;
    overflow: hidden;
  }

#banners li
  { display: block;
    list-item-style: none;
  }
Another option is to set the overflow to auto for the banners list so that visitors can scroll through the list of all banners, making them accessible without significant impact (extra scrollbar) on the presentation.

Advanced Functionality Layer - Javascript

Now that the banners were made accessible with the basic HTML and CSS design, we can add the extra scripting functionality that will show them one at a time automatically.

It is a good practice to encapsulate such behavior within a class (reasoning for this is beyond the scope of current discussion). I decided to name it lIterator (scripting literacy is as important as iterating through a list). The basic template I use is as follows:

function lIterator(listElement,delay)
  { /* Constructor */ 
    
    /* Dynamic Methods */
		 
  }
/* Static Properties */

/* Static Methods */
We start by writing the constructor for the class.

The first order of business is to remove all extra nodes from the UL element passed to the constructor. These could be empty text nodes added to document tree by compliant browsers, comment nodes, or HTML nodes that do not belong within the list element:

    for(var i=listElement.childNodes.length-1; i>=0; i--) 
	    if(!/li/i.test(listElement.childNodes[i].nodeName))
		    listElement.removeChild(listElement.childNodes[i]);
Next step is to hide all the list items but first one
    for(var i=1; i<listElement.childNodes.length; i++)
	    listElement.childNodes[i].style.display = 'none';
Then add a dynamic property to the class that will store the pointer to the currently displayed list item:
    this.currentLI = listElement.firstChild;
Now, we need to address the timer function. Since the dynamic class method can not be passed to setInterval we create a static array containing all the class instances:
/* Static Properties */
lIterator.instances = new Array();
The next step for the constructor would be to store the class there and add another property that stores its ID:
    this.id = lIterator.instances.length;
	lIterator.instances.push(this);
Now we can finish the constructor by calling the setInterval function that will start the iteration:
setInterval('lIterator.instances['+this.id+'].showNext()',delay);
All that is left to do is write the showNext() dynamic method:
/* Dynamic Methods */
	this.showNext = function()
	  { this.currentLI.style.display = 'none';
	    /* Following line is broken for readability */
		this.currentLI =
		    this.currentLI.nextSibling ?
                this.currentLI.nextSibling :
				this.currentLI.parentNode.firstChild;
        
		this.currentLI.style.display = 'block';
	  }
Now that the lIterator class is complete, instances need to be created when the page loads. Taking into consideration the HTML code above the onload event will be:
onload="new lIterator((document.getElementById('banners')).getElementsByTagName('ul')[0],1000);"
There you have it! You can create code that is accessible by everyone if you take precautions, and it doesn't have to be painful.

Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •  
  •  
  •  
Thanks for your registration, follow us on our social networks to keep up-to-date