Accordion menu with Wayfinder
From MODx Wiki
In this article, we are going to build a menu using Wayfinder snippet that has an accordion effect like script.aculo.us. When we are ready, it should look something like this demo (but in a menu).
Contents |
Get Started
To get started, we need to have a two level document structure that is built from containers and the documents inside them. So do something like this:
- Container 1
- Document 1.1
- Document 1.2
- Container 2
- Document 2.1
- Container 3
- Document 3.1
- Document 3.2
- Document 3.3
A container, is automatically created when you place or create a document inside another document (by either setting the parent when creating a document, or by right clicking on some document and selecting Create new document here from the context menu). In there is also a checkbox in the page settings tab to control this.
Create Chunks
Once you have that done, let's create the needed chunks for the menu.
wfStyle
wfStyle = This chunk contains the CSS styles for the menu. Alternatively, you could place the styles in your stylesheet.
<style>
#accordion {
border: 1px solid #1F669B;
width: 300px;
font-family: Trebuchet MS, Arial, Helvetica, sans-serif;
font-size: 11px;
}
h3 {
font-size: 12px;
padding: 4px 6px 4px 6px;
margin: 0;
border-style: solid none solid none;
border-top-color: #BDC7E7;
border-bottom-color: #182052;
border-width: 1px 0px 1px 0px;
color:#fff;
background-color: #63699C;
cursor:pointer;
}
#visible {
color:#CED7EF;
background-color: #63699C;
}
#panel1, #panel2, #panel3, #panel4 {
margin: 0;
padding-bottom: 0;
border: none;
}
.panel_body {
}
</style>
wfJs
wfJs - This chunk contains the javascript code needed for the menu. Alternatively, you could place this in an external .js file and include that in your template.
<script type="text/JavaScript">
function accordion(el) {
if ($('visible') == el) {
return;
}
if ($('visible')) {
var eldown = el.parentNode.id+'-body';
var elup = $('visible').parentNode.id+'-body';
new Effect.Parallel(
[
new Effect.SlideUp(elup),
new Effect.SlideDown(eldown)
], {
duration: 0.1
});
$('visible').id = '';
}
el.id = 'visible';
}
function init() {
// hide all elements apart from the one with id visible
var acc = document.getElementById('accordion');
var apanels = acc.getElementsByTagName('div');
for (i = 0; i < apanels.length; i++) {
if (apanels[i].className == 'panel_body') {
apanels[i].style.display = 'none';
}
}
var avis = document.getElementById('visible').parentNode.id+'-body';
document.getElementById(avis).style.display = 'block';
}
function addEvent(elm, evType, fn, useCapture) {
elm["on"+evType]=fn;return;
}
addEvent(window, "load", init);
</script>
wfOuter
wfOuter - This chunk does the top level templating in Wayfinder. We want to wrap the menu in a div with id of "accordion", that is referred to by the javascript code.
<div id="accordion">[+wf.wrapper+]</div>
wfParentRow
wfParentRow - This chunk templates the rows that are containers. We want to have a individual id for every outer div container. So I have used [+wf.docid+] placeholder in the id. If you look at the accordion() javascript function, you'll notice that it also expects the children of the container to be wrapped in a div that has an id that is the same as the containers, but has a -body suffix. I have also used the [+wf.docid+] placeholder in the div that wraps the children.
<div id="panel[+wf.docid+]">
<h3 onClick="accordion(this)">[+wf.linktext+]</h3>
<div id="panel[+wf.docid+]-body" class="panel_body">
<div>
[+wf.wrapper+]
</div>
</div>
</div>
wfParentRowHere
wfParentRowHere - This chunk templates the rows that are containers and currently active. If you look at the javascript code again, you'll notice that it expects a element with id of "visible" to be on that container div whose children will be shown. So this is basically just the same chunk as wfParentRow with the id="visible" attribute added to the h3 tag.
<div id="panel[+wf.docid+]">
<h3 id="visible" onClick="accordion(this)">[+wf.linktext+]</h3>
<div id="panel[+wf.docid+]-body" class="panel_body">
<div>
[+wf.wrapper+]
</div>
</div>
</div>
wfInner
wfInner - This chunk templates the child items of the menu. We will set it to be an unordered list for now.
<ul>[+wf.wrapper+]</ul>
Snippet Call
At this point the menu is fully functional for testing. Go and create a new template or put the following call to some existing template (or just into some document).
[[Wayfinder? &startId=`0` &level=`2` &outerTpl=`wfOuter` &innerTpl=`wfInner` &parentRowHereTpl=`wfParentRowHere` &parentRowTpl=`wfParentRow` &activeParentRowTpl=`wfParentRowHere` &cssTpl=`wfStyle` &jsTpl=`wfJs`]]
Then you also need to include script.aculo.us and prototype javascript libraries to the template. MODx comes with those allready included to the release, so just add the following lines to your template:
<script src="[(base_url)]manager/media/script/scriptaculous/prototype.js" type="text/javascript"></script> <script src="[(base_url)]manager/media/script/scriptaculous/scriptaculous.js" type="text/javascript"></script>
Conclusion
Now go and view your site and you should see the accordion menu working. Next thing to do is to style it the way you want, for example add &innerRowTpl and &innerHereTpl templates to style the child documents in the menu etc.
