The script is fully functional, unobtrusive and pretty much bullet proof. The only real problem is that it is not yet maintenance friendly.
Probably the biggest issue of scripts and their application is that not all maintainers know JavaScript and are willing to go through your scripts to find different parts to change.
To avoid maintainers having to do that, the safest bet is to separate the functionality of your script from the names and IDs used by both the script and CSS. Furthermore it is a good plan to separate out the text labels used in the script as they are likely to change, for example when the script gets localized to other languages.
The first thing to bring out of the main script are the tool functions other scripts could re-use. This is probably how most of the big JavaScript libraries started :)
tools.js:
/* helper methods */
tools = {
addEvent:function( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){
obj['e'+type+fn]( window.event );
}
obj.attachEvent( 'on'+type, obj[type+fn] );
} else
obj.addEventListener( type, fn, false );
},
removeClass:function(o,c){
var rep=o.className.match(' '+c)?' '+c:c;
o.className=o.className.replace(rep,'');
},
addClass:function(o,c){
var test = new RegExp("(^|\\s)" + c +
"(\\s|$)").test(o.className);
if(!test){o.className+=o.className?' '+c:c;}
},
cancelClick:function(e){
if (window.event){
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (e && e.stopPropagation && e.preventDefault){
e.stopPropagation();
e.preventDefault();
}
}
}
The next step is to separate the look and feel classes and IDs out into an own include. As other scripts are not likely to use them, it is safer to keep them in the slideshow namespace. It also doesn't hurt to write a short explanatory comment.
slideshow-css.js:
slideshow.css = {
/*
These are the classes and IDs used in the slideshow.
You can change any of them here. Please make sure
to use quotation marks around the names and end
all but the last one with a comma.
*/
showID :'slideshow',
dynamicClass :'js',
slideNavigationClass :'slidenav',
currentClass :'current'
}
Last but not least let's put the text labels in an own include, again namespaced to our slideshow.
slideshow-labels.js:
slideshow.labels = {
/*
These are the text labels used in the slideshow.
You can change any of them here. Please make sure
to use quotation marks around the values and end
all but the last one with a comma.
*/
previous : '<<',
next : '>>',
counterDivider : ' of '
}
We then need to change the main script to use this information instead of relying on embedded data. There are not many changes, and this could easily be done with search + replace.
slideshow.js:
slideshow = {
current:0,
init:function(){
if(document.getElementById && document.createTextNode){
var list =document.getElementById(slideshow.css.showID);
if(list){
slideshow.items = list.getElementsByTagName('li');
slideshow.all = slideshow.items.length;
if(slideshow.all > 1){
tools.addClass(list, slideshow.css.dynamicClass);
slideshow.createNav(list);
}
}
slideshow.show();
}
},
createNav:function(o){
var p = document.createElement('p');
tools.addClass(p, slideshow.css.slideNavigationClass);
slideshow.prev = document.createElement('a');
slideshow.prev.setAttribute('href', '#');
var templabel = document.createTextNode(
slideshow.labels.previous);
slideshow.prev.appendChild(templabel);
tools.addEvent(slideshow.prev, 'click', slideshow.show);
p.appendChild(slideshow.prev);
slideshow.count = document.createElement('span');
templabel =document.createTextNode((slideshow.current+1) +
slideshow.labels.counterDivider + slideshow.all);
slideshow.count.appendChild(templabel);
p.appendChild(slideshow.count);
slideshow.next = document.createElement('a');
slideshow.next.setAttribute('href', '#');
var templabel = document.createTextNode(
slideshow.labels.next);
slideshow.next.appendChild(templabel);
tools.addEvent(slideshow.next, 'click', slideshow.show);
p.appendChild(slideshow.next);
o.parentNode.insertBefore(p, o);
},
show:function(e){
if(this === slideshow.next || this === slideshow.prev){
tools.removeClass(slideshow.items[slideshow.current],
slideshow.css.currentClass);
var addto = this === slideshow.next ? 1 : -1;
slideshow.current = slideshow.current + addto;
if(slideshow.current < 0){
slideshow.current = (slideshow.all-1);
}
if(slideshow.current > slideshow.all-1){
slideshow.current = 0;
}
}
var templabel = document.createTextNode(
(slideshow.current+1)+slideshow.labels.counterDivider
+ slideshow.all);
slideshow.count.replaceChild(templabel,
slideshow.count.firstChild);
tools.addClass(slideshow.items[slideshow.current],
slideshow.css.currentClass);
tools.cancelClick(e);
}
}
tools.addEvent(window,'load',slideshow.init);
That is all that is needed to make sure future maintainers can work with your script without having to bother your. The file names should make it pretty obvious what is what and can over time become a standard for scripting:





This work is licensed under a Creative Commons Attribution-Share Alike 3.0 License. Written by Christian Heilmann, CSS based on the Yahoo! User Interface Library