Files
2026-06-17 14:00:51 +02:00

164 lines
4.4 KiB
JavaScript

/*
Turns a DL list into a folded FAQ
How:
By surrounding the dt with a link, an empty i element is also added for an icon if required.
The dd is moved off screen until the dt link is clicked.
Adding a class="on" to a dt will show the related dd(s).
Parameters (optional):
faqClass : "faq", // class of the dl's to apply folding too, default "faq".
onClass : "on", // class applied to show the dd, default "on", also used to switch the dt icon state.
linkClass : "" // class added to the dt show/hide link. Default none.
It is recomended to leave the first question open to provide a hint to the user about the functionality presented.
Please ensure the link colours used are different to standard links.
Author: mike foskett mike.foskett@websemantics.co.uk
http://websemantics.co.uk/resources/simple_faq/
*/
document.documentElement.className="hasJS";
var FAQ = (function () {
var faqClass,
onClass,
lnkClass,
DLs,
i,
ii,
iii,
faqDLs = [],
dts,
lnkObj,
ns,
lnkTxt;
function hasClass(o,c){return new RegExp('(\\s|^)'+c+'(\\s|$)').test(o.className);}
function addClass(o,c){if(!hasClass(o,c)){o.className+=' '+c;}}
function removeClass(o,c){if(hasClass(o,c)){o.className=o.className.replace(new RegExp('(\\s|^)'+c+'(\\s|$)'),' ').replace(/\s+/g,' ').replace(/^\s|\s$/,'');}}
function getNextSibling(o) {
var n = o.nextSibling;
while (n !== null && n.nodeType !== 1) {
n = n.nextSibling;
}
return n;
}
function showHideDDs() {
var dds = this.siblings,
i = dds.length,
p = this.parentNode;
if (hasClass(p, onClass)) { //remove "on" class
removeClass(p, onClass);
while (i--) {
removeClass(dds[i], onClass);
}
} else { // add "on" class
addClass(p, onClass);
while (i--) {
addClass(dds[i], onClass);
}
}
return false;
}
function init(cfg) {
// default over-rides
faqClass = cfg.faqClass || "faq";
onClass = cfg.onClass || "on";
lnkClass = cfg.linkClass || "";
// create a list from all DL's identified by faqClass
DLs = document.getElementsByTagName("dl");
i = DLs.length;
while (i--) {
if (hasClass(DLs[i], faqClass)) {
faqDLs.push(DLs[i]);
}
}
i = faqDLs.length;
while (i--) {
dts = faqDLs[i].getElementsByTagName('dt');
ii = dts.length;
while (ii--) {
// create an activating link object
lnkObj = document.createElement('a');
// get a list of DT siblings and attach to the link object
lnkObj.siblings = [];
ns = getNextSibling(dts[ii]); // the DT's first sibling
while (ns !== null) {
// Only interested if it is a DD
if (ns.tagName === "DD") {
lnkObj.siblings.push(ns);
ns = getNextSibling(ns);
} else {
// next sibling is not a DD therefore end loop
ns = null;
}
}
// Only add link object and associated html changes if there is at least one DD
iii = lnkObj.siblings.length;
if (iii) {
// store original text and then empty.
lnkTxt = dts[ii].innerHTML;
dts[ii].innerHTML = "";
// if a class is required for the activating link then add one
if (lnkClass !== "") {
lnkObj.className = lnkClass;
}
// add click functionality
lnkObj.href = "#";
lnkObj.onclick = showHideDDs;
// add an i element to display a show/hide icon
lnkObj.appendChild(document.createElement('i'));
// insert original text back into the new link
lnkObj.appendChild(document.createTextNode(lnkTxt));
// add link to HTML
dts[ii].appendChild(lnkObj);
// If a DT already has an "on" class, then add the "on" class to its DD's too.
if (hasClass(dts[ii], onClass)) {
while (iii--) {
addClass(lnkObj.siblings[iii], onClass);
}
}
} else {
// add a B element to reserve space without displaying an icon
dts[ii].innerHTML = "<b></b>" + dts[ii].innerHTML;
}
}
}
}
return {
init : init
};
}());
FAQ.init({
faqClass : "faq", // Default "faq"
onClass : "on", // Default "on" used to show dd and switch dt icon state.
linkClass : "" // Default none
});