Unintentionally Blank

Phil Nash on the Internet, Web Standards and Accessibility

Stylesheet Switcher - Part 2

Aug 18, 2006

by Phil Nash

Yesterday I began to create a stylesheet switcher using javascript and the HTML DOM. I finished up with an example of the work so far, but I failed to address a few of the points in my requirements, namely:

  • Use a dropdown box to select styles
  • Populate the dropdown box with stylesheet names from the title attribute of the link tag
  • Graceful degradation in browsers without script
  • Future proof javascript

Today I will tackle these issues.

Dropdown Boxes

This isn't really a javascript issue, but not having had much experience with dropdown boxes, I had to look this up. A dropdown box is an element of an HTML form, so must exist within the form element. However, since we aren't using server side scripts there is no need to give the form a method or an action. In fact, the dropdown box will trigger the script itself. We set up the dropdown box as so:

<form>
<select onChange="setStyleSheet »
(this.options[this.selectedIndex].text)"> <option>stylesheet</option> ...

So we use the function created yesterday to change the stylesheet, but what is

this.options[this.selectedIndex].text
? I'll break it down:

this.options
this refers to the dropdown box and options will be the <option> elements that will populate the list
this.selectedIndex
selectedIndex returns the position of the option selected (starting with 0)
[this.selectedIndex].text
appending .text to the selectedIndex means that it will return the text within the option element

In all, when an option is selected, the option text that was selected will be handed to the setStyleSheet function. The only drawback of this method is that the text in each of the options has to match the titles of your stylesheets in order that the function works. This is where javascript steps in again.

Self Populating Options

Rather than creating the dropdown box in the HTML source of my site, I decided to let javascript do it. This has two bonuses, firstly a user who has disabled javascript won't see the dropdown box and won't know what they are missing out on (graceful degradation - we don't want a dropdown box on the page if the user won't be able to use the functions) and secondly we can use our functions we came up with yesterday to iterate through the available stylesheets creating an option for each one.

"This will be easy," I thought. So I started writing a whole bunch of document.write(...) statements ready to output the dropdown box. However, there have been changes in what is and isn't allowed within javascript, chages I came across whilst reading about good javascript practices. I was surprised to see that document.write will not work with XHTML. The reasons were compelling enough and, even though I use HTML 4.01 throughout this site, having a script that will work for HTML and XHTML is important for the future.

The DOM and createElement

So I needed a new way of dynamically producing a dropdown box. Rather than writing out the HTML with document.write, it turns out that modern javascript programmers create all the objects separately and then add them to the DOM tree. There is a superb DOM tutorial at webreference.com, and it taught me everything I needed to know to create my dropdown box. I'll walk through the method then post the code so that you can see how it all happened.

  1. Create the form element
  2. Create the select element
  3. Add the onChange attribute to the select element
  4. Append the select element to the form
  5. Get the stylesheets
  6. Get the stylesheet that is currently in use (the preferred stylesheet)
  7. For all the stylesheets:
    1. Get the title of the stylesheet
    2. Create an option element
    3. If the stylesheet is the preferred stylesheet, add the selected attribute to the option element
    4. Create a text node using the title of the stylesheet
    5. Append the text to the option element
    6. Append the option to the select element
  8. Append the form to the area of the document that you select

The last point needs some extra explanation. Due to the nature of creating and appending elements to the DOM tree, rather than writing HTML directly to the page as it is processed, the form element needs to be appended to a relevant element that already exists in the DOM tree. To deal with this I included a parameter in the call of the function. All you need to do is add the id of the element you want the dropdown box to appear in. The code will show how it works.

function linkBox(elementID) {
  var form = document.createElement("form");
  var drop = document.createElement("select");
  drop.setAttribute("onChange",»
"setStyleSheet(this.options[this.selectedIndex].text)"); form.appendChild(drop); var stylesheets = getStyleSheets(); var preferred = getPreferredStyleSheet(); for (var i=0;i<stylesheets.length; i++) { var title = stylesheets[i].getAttribute("title"); var option = document.createElement("option"); if (title==preferred) { »
option.setAttribute("selected","selected"); } var optionText = document.createTextNode(title); option.appendChild(optionText); drop.appendChild(option); } document.getElementById(elementID).appendChild(form); }

The Final Product

Here is the final demonstration of the stylesheet switcher with dropdown box. You can download the full script here.

To use the script, just add your stylesheets and the script to the header as yesterday then place the following script where you want your dropdown box to appear:

<script type="text/javascript" language="javascript">
<!--
linkBox('elementID');
//-->
</script>

I hope this will be useful, for both accessibility and adding new styles to a site. If you do use it and would like to show off (or have problems with it), please let me know. Also, if you have any ideas for accessibility driven bits of code that either exist and need updating/explaining, or should exist, tell me and I will see what I can do.

Problems! Turned out that this doesn't work in Internet Explorer (oh don't we love it so). You can, however, find out how I fixed it.

Unintentionally Blank is Phil Nash's thoughts on web development from 2006-2008. Any code or opinions may be out of date.