Style Switcher - *Non* jQuery version

Posted on Wednesday, August 27th, 2008

A tutorial that I wrote explaining how to develop a degradable style switcher in jQuery and PHP has just been published on NETTUTS.

I thought it would be a good idea to expand on the tutorial for the benefit of those who want to integarete the style-switcher into their own website.

In the tutorial, we made use of the popular JavaScript library, jQuery. I’m a big fan of jQuery and think it’s a time-saver and definitely something you should pursue if you want to add UX enhancements throughout your site. Though in some situations it’s not a good idea to use jQuery; if you’re only using it for a couple of features within your site then it might be better to just write the actual JavaScript instead, to save space. (jQuery.min is ~50k!)

So, for anyone you wants it, I have written the non-jQuery version.

NOTE: Just like the jQuery version it works in IE6, IE7, Opera, FF and Safari. If you followed the concepts outlined in the tutorial then it shouldn’t be too hard to see what’s going on here. - Since I’m using no library it’s bound to be a longer script; "one line with jQuery is several lines without it!"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
var styleSwitcher = {
	// Begin script:
	init: function(){
		// Initialise the CSS dummy method:
		// (If you don't know what this is then read through the NETTUTS tutorial!)
		styleSwitcher.cssDummy.init();
		// Specify container of the links (<A>) to different styles:
		var ss = document.getElementById('style-switcher');
		// If it exists on the page:
		if (ss) {
			// Get anchors within the container and assing length to variable:
			var ssLinks = ss.getElementsByTagName('a'), l = ssLinks.length;
			// Loop through all anchors:
			while (l--) {
				// Assign onclick event:
				ssLinks[l].onclick = (function(){
					var href = this.href;
					// Load the stylesheet:
					styleSwitcher.loadStyleSheet(href);
					return false;
				});
			}
		}
	},
	loadStyleSheet: function(href){
		// Create new overlay DIV element and style it:
		// (applyCSS is another method)
		if(!document.getElementById('overlay')) {
			var overlay = document.createElement('div');
			overlay.id = "overlay";
			styleSwitcher.applyCSS(document.body,{height:'100%'}); // For IE6
			styleSwitcher.applyCSS(overlay,{
				position: 'absolute',
				top:0,
				left: 0,
				width: '100%',
				height: '100%',
				zIndex: 1000,
				background: 'black url(img/loading.gif) no-repeat center',
				opacity: 0,
				filter: 'alpha(opacity=0)'
			});
			// Append our overlay to the document:
			document.body.appendChild(overlay);
		} else {
			var overlay = document.getElementById('overlay');
		}
		// Fade in the overlay
		styleSwitcher.fadeIn(overlay,function(){
			// Callback function: Get response from style-switcher.php:
			styleSwitcher.AJAX.load(href + '&js',function(data){
				// Do stuff with the data response:
				var link = document.getElementById('stylesheet');
				if(link) link.href = 'css/' + data + '.css';
				// Initiliase the "check" method of cssDummy:
				styleSwitcher.cssDummy.check(function(){
					// Once CSS has loaded fade-out the overlay:
					styleSwitcher.fadeOut(overlay);
				});
			})
		})
	},
	// It makes sense to make a quick method to apply CSS rules to elements:
	applyCSS: function(element,styles){
		// If styles are passed in as an object the proceed:
		if (typeof styles == "object") {
			// We don't want an array though:
			if (!styles[0]) {
				// Loop through array and apply styles:
				for (var i in styles) {
					element.style[i] = styles[i];
				}
			}
		}
	},
	// fadeIn method:
	fadeIn: function(element,callback) {
		element.style.display = "block";
		function nudgeOpacity(to) {
			// If the element has NOT finished fading in the proceed:
			if (parseInt(to,10) < 10) {
				element.style.opacity = to/10; // For all the good browsers
				element.style.filter = 'alpha(opacity=' + to*10 + ')'; // For IE
				// Pause for 50 milliseconds then nudge opacity up another step:
				setTimeout(function(){
					nudgeOpacity(to + 1)
				},50)
			} else {
				// If the element HAS finished fading in then initiate callback function:
				callback();
			}
		}
		nudgeOpacity(0);
	},
	// fadeOut method:
	fadeOut: function(element,callback) {
		function nudgeOpacity(to) {
			// If the element has NOT finished fading out the proceed:
			if (parseInt(to,10) > 0) {
				element.style.opacity = to/10; // For all the good browsers
				element.style.filter = 'alpha(opacity=' + to*10 + ')'; // For IE
				// Pause for 50 milliseconds then nudge opacity down another step:
				setTimeout(function(){
					nudgeOpacity(to - 1);
				},50)
			} else {
				// If the element HAS finished fading out then initiate callback function:
				if(callback) callback();
				// Then make sure overlay is properly hidden:
				styleSwitcher.applyCSS(element,{
					opacity: 0,
					filter: 'alpha(opacity=0)',
					display: 'none'
				});
			}
		}
		nudgeOpacity(10);
	},
	AJAX: {
		// This will load style-switcher.php gives us the response data:
		http:false,
		callback:function(data){},
		opt:new Object(),
		getHTTPObject : function() {
			var http = false;
			if(typeof ActiveXObject != 'undefined') {
				try {http = new ActiveXObject("Msxml2.XMLHTTP");}
				catch (e) {
					try {http = new ActiveXObject("Microsoft.XMLHTTP");}
					catch (E) {http = false;}
				}
			} else if (XMLHttpRequest) {
				try {http = new XMLHttpRequest();}
				catch (e) {http = false;}
			}
			return http;
		},
		load : function (url,callback) {
			this.init(); 
			if(!this.http||!url) return;
			if (this.http.overrideMimeType) this.http.overrideMimeType('text/xml');
			this.callback=callback;
			var ths = this;
			var now = "uid=" + new Date().getTime();
			// Solve caching problem in IE7:
			url += (url.indexOf("?")+1) ? "&" : "?";
			url += now;
			var parameters = null;	
			this.http.open('GET', url, true);
			this.http.onreadystatechange = function () {
				if(!ths) return;
				var http = ths.http;
				if (http.readyState == 4) {
					if(http.status == 200) {
						var result = "";
						if(http.responseText) result = http.responseText;
						if(ths.callback) ths.callback(result);
					} else {
						// If style-switcher.php does not exist:
						alert('Cannot find theme specified')
					}
				}
			}
			this.http.send(parameters);
		},
		init : function() {this.http = this.getHTTPObject();}
	},
	// cssDummy method which tells us whether stylesheet has loaded:
	cssDummy: {
		init: function(){
			var dummy = document.createElement('div');
			dummy.id="dummy-element";
			dummy.style.display='none';
			document.body.appendChild(dummy);
		},
		check: function(callback) {	
			// Get computed styles (cross-browser):
			function getStyle(el, prop) {
				if (document.defaultView && document.defaultView.getComputedStyle) {
					var a = document.defaultView.getComputedStyle(el, null)[prop];
					if(parseInt(a,10)!==0) return a;
				}
				if (el.currentStyle) {
					var b = el.currentStyle[prop];
					if(parseInt(b,10)!==0) return b;
				} else {
					var c = el.style[prop];
					if(parseInt(c,10)!==0) return c;
				}
			}
			// If 2px width is detected then initiate callback:
			if (getStyle(document.getElementById('dummy-element'),'width')=='2px') callback();
			// Otherwise check again in 500 milliseconds:
			else setTimeout(function(){styleSwitcher.cssDummy.check(callback)}, 500);
		}
	}
};

At the bottom of index.php you should replace $('#style-switcher a').styleSwitcher(); with the following:

styleSwitcher.init()

Please let me know if you have any questions about the above script or the one posted on NETTUTS! :)

2 Responses to “Style Switcher - *Non* jQuery version”

  1. Gravatar #1 :: taylan Says:

    Great script. I like non jquery version and try it. Thank you.

  2. Gravatar #2 :: Swapnil Sarwe Says:

    Hey James,
    Since I am just started to learn javascript, didn’t wanted to get overwhelmed by the beauty of jQuery, and hence always look forward towards snippets and codes which are non-jQuery but work similarly so that I can understand.
    I liked your non-Jquery version of style-switcher, and I am using it on my site, for trial versions of my CSS.
    Thanx a lot. for sharing.

Leave a Response

Allowed elements include: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <em> <i> <q cite=""> <strike> <strong>.
Please wrap any multi-line code snippets in the <pre> element. (Characters are automatically escaped this way) - also you can specify the language within the lang attribute, e.g. <pre lang="php">echo 'hello';</pre>. (Available languages: "php", "javascript", "html4strict")