Hallo all,
I have some working code (well, no focus yet but I’m assuming if the code is cleaned up this will help me implement focus), something I was rewriting after getting to the accordion portion of the Javascript Live course and going through the version in Simply Javascript (Events chapters). Mine is more complicated than the SJ example because I have two sets of rules going on plus an extra conditional behaviour.
html (temp)
http://stommepoes.nl/jstest/shlinks.html
CSS in the same folder
http://stommepoes.nl/jstest/shl.css
JS in the same folder:
modified-from-Core functions at http://stommepoes.nl/jstest/funclib.js
page js: http://stommepoes.nl/jstest/shl.js
Posted main JS file:
/*shl link lijst expand/collapse*/
var LinkLijst = {
init: function() {
//collapse everything onload
var mainUL = document.getElementById('beschrijflinks');
var mainLIs = mainUL.childNodes;
for(i=0, ii=mainLIs.length; i<ii; i++) {
if(mainLIs[i].nodeType == 1) {
var mainLI = mainLIs[i]; //reduce variable lookups
LinkLijst.collapse(mainLI);
var subULs = mainLI.getElementsByTagName('ul');
for(j=0, jj=subULs.length; j<jj; j++) {
var subUL = subULs[j];
LinkLijst.collapse(subUL);
}
}
}
//add anchors to headers onload
var h2s = mainUL.getElementsByTagName('h2'),
h3s = mainUL.getElementsByTagName('h3');
for(k=0, kk=h2s.length; k<kk; k++) {
var anchor = Basis.createAnchor('+', 'a_'+k);
h2s[k].insertBefore(anchor, h2s[k].firstChild);
Basis.addEventListener(anchor, 'click', LinkLijst.mainClickListener);
// Basis.addEventListener(anchor, 'focus', LinkLijst.focusListener);
}
for(m=0, mm=h3s.length; m<mm; m++) {
var anchor = Basis.createAnchor('+', 'a_'+m);
h3s[m].insertBefore(anchor, h3s[m].firstChild);
Basis.addEventListener(anchor, 'click', LinkLijst.subClickListener);
// Basis.addEventListener(anchor, 'focus', LinkLijst.focusListener);
}
}, //init
collapse: function(chunk) {
Basis.addClass(chunk, 'collapse');
},
expand: function(chunk) {
Basis.removeClass(chunk, 'collapse');
},
expandAll: function(chunk) {
LinkLijst.expand(chunk);
var alink = Basis.getPrevSibling(chunk).firstChild;
alink.firstChild.nodeValue = '-';
},
collapseAll: function(chunk) {
LinkLijst.collapse(chunk);
var alink = Basis.getPrevSibling(chunk).firstChild;
alink.firstChild.nodeValue = '+';
},
mainClickListener: function(event) {
var anchor = this,
mainLI = this.parentNode.parentNode;
if (Basis.hasClass(mainLI, 'collapse')) {
LinkLijst.expand(mainLI);
anchor.firstChild.nodeValue = '-';
}
else {
LinkLijst.collapse(mainLI);
anchor.firstChild.nodeValue = '+';
}
Basis.preventDefault(event);
},
subClickListener: function(event) {
var anchor = this,
h3 = anchor.parentNode,
div = h3.parentNode,
subs = div.getElementsByTagName('ul'),
subUL = Basis.getNextSibling(h3);
if(Basis.hasClass(subUL, 'collapse')) {
if(h3.childNodes[1].nodeValue == 'Algemeen') {
for(p=0, pp=subs.length; p<pp; p++) {
LinkLijst.expandAll(subs[p]);
}
}
else {
LinkLijst.expand(subUL);
anchor.firstChild.nodeValue = '-';
}
}
else {
if(h3.childNodes[1].nodeValue == 'Algemeen') {
for(p=0, pp=subs.length; p<pp; p++) {
LinkLijst.collapseAll(subs[p]);
}
}
else {
LinkLijst.collapse(subUL);
anchor.firstChild.nodeValue = '+';
}
}
Basis.preventDefault(event);
},
focusListener: function(event) {
var anchor = this;
if(anchor.parentNode.nodeName == 'H2') {
var mainLI = anchor.parentNode.parentNode;
if (Basis.hasClass(mainLI, 'collapse')) {
LinkLijst.expand(mainLI);
anchor.firstChild.nodeValue = '-';
}
}
else if(anchor.parentNode.nodeName == 'H3') {
var h3 = anchor.parentNode,
subUL = Basis.getNextSibling(h3);
if (Basis.hasClass(subUL, 'collapse')) {
LinkLijst.expand(subUL);
anchor.firstChild.nodeValue = '-';
}
}
}
};
Basis.begin(LinkLijst);
In the Simply Javascript version, I believe the reason focus doesn’t interfere with click is because he loops through (existing) anchors and starts at 1 for his counter instead of 0… but I’m not entirely sure.
I’m looping through header tags and adding anchors… so not sure how to stop focus from interfering with click when doing it this way.
Mostly though I want to know how I can optimise and better write this. The subClickListener has a whole lotta vars listed, and I list them often because listing vars is done inside for loops so I’m repeating myself a lot.
I think expand and collapse should also be dealing with the anchor text as well, but the problem is that those functions could be called by different thises which changes who the element is getting the “collapse” class.
Expand and collapse do the same thing on different elements. Does it make sense to try to get one Listener to use these expand/collapse functions instead of two listeners??
At one point I had looping through two nodeLists (the h2’s and the h3’s) and giving them all just one clickListener, but then there was a lot of iffing around before assigning the functions.
Anyway I would just like some feedback on this code. It works, so the behaviour you see is what is stated in my instructions. Possibly better structured HTML would help?
note
Please don’t mention switching to libraries. I’m learning to write real JS, and the Javascript Live course already showed a BIG discrepancy between how jQuery grabs elementsByTagName versus vanilla Javascript! (jQuery seems to maybe make a real array instead of a nodeList?) I want to improve my vanilla, please.
Thanks in advance,
poes