
Originally Posted by
jscheuer1
Numbering the functions is good, do that to all the variables, id names, anything unique to the script too, if you are thorough it will work. The name of the game is, don't let anything in one version of the script affect the other version.
Time would probably be better spent rewriting the script after reading my treatise on creating re-usable scripts. Of course, it would need more work than that:
Code:
var createMultipartSection = (function() {
var getElementById;
if(!Array.prototype.push) {
Array.prototype.push = function() {
for(var j = 0, n = arguments.length; j < n; ++j) {
this[this.length] = arguments[j];
}
return this.length;
};
}
if(document.getElementById) {
getElementById = function(id) {return document.getElementById(id);};
} else if(document.all) {
getElementById = function(id) {var r = document.all[id];
if(('number' == typeof r.length) && r.tags) {
for(var j = 0, n = r.length; j < n; ++j) {
if(r[j].id == id) {return r[j];}
}
} else if(r.id == id) {return r;}
return null;
};
} else {getElementById = function() {return null;};}
function getParts(ancestor) {
var elements = ancestor.getElementsByTagName
? ancestor.getElementsByTagName('*')
: ancestor.all ? ancestor.all : [],
r = [];
for(var j = 0, n = elements.length, c, cN; j < n; ++j) {
c = elements[j]; cN = c.className;
if(('string' == typeof cN) && /(^|\s+)multipart-part(\s+|$)/.test(cN)) {
r.push(c);
}
}
return r;
}
function showElement(element, show) {
if(element.style) {element.style.display = show ? '' : 'none';}
}
return function(id, loop, navProvided, start) {
var current = start || 0,
next = loop
? function() {return cycle(1);}
: function() {return move(1);},
previous = loop
? function() {return cycle(-1);}
: function() {return move(-1);},
back, forward, parts, section;
function cycle(delta) {
showElement(parts[current], false);
current = (current + delta + parts.length) % parts.length;
showElement(parts[current], true);
return false;
}
function move(delta) {
if(((current + delta) < parts.length) && ((current + delta) >= 0)) {
showElement(parts[current], false);
current += delta;
showElement(parts[current], true);
showElement(back, current != 0);
showElement(forward, current != (parts.length - 1));
}
return false;
}
if((section = getElementById(id)) && (parts = getParts(section)).length) {
if(navProvided) {
back = getElementById(id + '-back');
forward = getElementById(id + '-forward');
} else if(document.createElement && document.createTextNode
&& document.body && document.body.appendChild)
{
var n = document.createElement('ul'),
b = document.createElement('li'),
f = document.createElement('li');
back = document.createElement('a');
forward = document.createElement('a');
if(n && b && back && f && forward && n.appendChild) {
n.id = id + '-navigation';
back.id = id + '-back'; back.href = '#';
forward.id = id + '-forward'; forward.href = '#';
back.appendChild(document.createTextNode('Back'));
b.appendChild(back);
n.appendChild(b);
forward.appendChild(document.createTextNode('Forward'));
f.appendChild(forward);
n.appendChild(f);
document.body.appendChild(n);
} else {back = forward = null;}
b = f = n = null;
}
if(back && forward) {
back.onclick = previous;
forward.onclick = next;
showElement(back, current != 0);
showElement(forward, current != (parts.length - 1));
for(var j = 0, n = parts.length; j < n; ++j) {
if(j != current) {showElement(parts[j], false);}
}
}
}
};
})();
The code above creates a function, createMultipartSection, which takes four arguments:
- id - A string containing the id attribute of an element which is the ancestor of a group of parts. Required.
- loop - A boolean which indicates whether the parts should be navigated in a cyclic or linear fashion. Defaults to false (linear).
- navProvided - A boolean which indicates whether createMultipartSection needs to create navigation controls or if they are already in the document. Defaults to false (create).
- start - A number specifying which part to show first. Defaults to zero (0).
If the navigation generation feature isn't used, the code should work with IE4+ and any DOM supporting user agent (Opera, Firefox, Safari, etc). If the navigation generation feature is used, the script will not work with IE4 as it doesn't possess a particularly useful document.createElement method. That said, the script is currently untested, but it should work.
The behaviour of the script has changed, and does have new features.
- The class name which parts should use is multipart-part. This can be changed by editing the regular expression in the getParts function. The use of a regular expression for class name matching also allows for the use of multiple class names rather than only one.
- The expected naming of the navigation elements is based upon the id passed as the first argument. The navigation container should have the id, id-navigation, the back control should have id-back, and the forward control should have id-forward. If the navigation elements are generated, they will follow the same pattern so you can reliably style them.
- The generated navigation controls will be in the form of an unordered list, inserted at the end of the document. A basic CSS rule for styling them would be:
Code:
#id-navigation {
list-style-type: none;
margin: 1em 0;
padding: 0;
}
#id-navigation li {
display: inline;
margin: 0;
padding: 0 1ex;
}
You can, of course, add things such as absolute positioning. Adjust as you see fit. If you want to control your own placement, and what is used for the controls, specify true for the third argument and follow the pattern in the previous point. - The parts found during execution will be hidden automatically, with the exception of the starting part. They must not be hidden via a style sheet rule.
The function must be called after the containing element, its parts, and any provided navigation has been parsed by the user agent. Calling the function as part of a load event handler will obviously accomplish this, but an earlier call is possible.
Have fun, 
Mike
Bookmarks