Generic CSS Switcher
After reading the recent digg article about a Time Sensitive CSS Switcher, I was inspired to make a more generic version that would allow you to switch the style based on whatever criteria you wanted. For instance, what if I wanted to switch the style based on the referring URL instead of the time of day?
Demo, or it didn't happen!
To all of you who just want to skip the boring details and see the demo, here it is.
How it works
Note: I know this is probably better done on the server side, but this is an exercise in JavaScript, so I will leave the server side implementation to someone else.
The code to switch the stylesheet can be removed from the logic of deciding which style should be presented. So, when you want to change how you decide which stylesheet is used (ie: via the refering URL), you don't need to worry about actually switching the stylesheet because that is already done for you.
I also wanted the flexibility to define how the style was switched. Switching the stylesheet is great, but you could also modify the ID of the body element.
Edit: Someone has suggested adding multiple class names to the body element in order to achieve a similar effect. Its an interesting idea.
I decided that I would build a function called StyleSwitcher to encapsulate the stylesheet switching. This function takes a Switcher object as a parameter, this object must have the following properties:
- strategy (String)
- The strategy for switching the style (body ID or stylesheet)
- targetId (String)
- If the strategy is defined as stylesheet, targetId is expected. This defines the id of the stylesheet link element to use to switch the stylesheet.
- getStyle (Function)
- A function that returns the style to apply.
- defaultStyle (String)
- A default style to apply if the getStyle function returns false.
So, the StyleSwitcher function is expecting an object that conforms to a specific set of guidelines. In object oriented programming, this "specific set of guidelines" is called an interface. So, this means that I can pass the StyleSwitcher function any object which conforms to the Switcher interface and it can do its work.
For the sake of keeping everything encapsulated in one namespace, I've put the function in an object named StyleSwitcher and defined a function called doswitch.
Note: Don't worry about copying this code, I've provided an example page where you can download everything.
Here is what the function looks like:
var StyleSwitcher = {
doswitch : function (switcher) {
if (!switcher.strategy || typeof(switcher.strategy) != "string") throw new Error("strategy must be defined as a string in switcher object");
if (!switcher.getStyle || typeof(switcher.getStyle) != "function") throw new Error("getStyle must be defined as a function in switcher object");
if (!switcher.defaultStyle || typeof(switcher.defaultStyle) != "string") throw new Error("defaultStyle must be defined as a string in switcher object");
var newStyle = switcher.getStyle() || switcher.defaultStyle;
switch (switcher.strategy) {
case "id":
document.body.id = newStyle;
break;
case "stylesheet":
if (!switcher.targetId || typeof(switcher.targetId) != "string") throw new Error("stylesheet switchers must have targetId defined");
var ss = document.getElementById(switcher.targetId);
if (!ss) throw new Error("switcher targetId refers to non-existent element");
if (!ss.rel || ss.rel != "stylesheet") throw new Error("switcher targetId does not refer to a stylesheet element");
ss.setAttribute("href", newStyle);
break;
default:
throw new Error("strategy must be one of 'id' or 'stylesheet' in switcher object");
break;
}
}
}
Basically, the function verifies that the Switcher object passed in has the correct parameters, runs the getStyle function and then sets the resulting style using either the stylesheet or body id strategy. You might be wondering what an example Switcher object looks like, so here is an example one using the referrer:
var ReferrerSwitcher = {
strategy : "stylesheet",
targetId : "style_target",
defaultStyle : "referrer.css",
styles : {'/digg.com/' : 'digg.css',
'/stephenminded.com/' : 'sm.css'},
getStyle : function () {
var ref = document.referrer;
for (var i in this.styles)
{
var pattern = new RegExp(i);
if (pattern.test(ref)) return this.styles[i];
}
return false;
}
};
I've put together a demo which includes switching by referrer as well as time of day like the digg article I mentioned. Here is the demo. Skip the demo and download the code.
Note: I used jQuery to attach to the onload event because it provides a nice way of ensuring the DOM is loaded, but by no means is jQuery required.





Have the honour of commenting first!