En gros, tout le plan du site est intégré dans la page et structuré avec des ul et des li imbriqués :
Voir le code HTML
<ul id="menuCol">
<li>
2005
<ul>
<li>
July
<ul>
<li>
27
<ul>
<li>
<a href="?id=4">
Joulie Interface
</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
September
<ul>
<li>
29
<ul>
<li>
<a href="?id=11">
Version Texte
</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
October
<ul>
<li>
29
<ul>
<li class="selected">
<a href="?id=18">
Qjelt Octobre en VideoCast
</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
November
<ul>
<li>
08
<ul>
<li>
<a href="?id=19">
alt-i.fr
</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
December
<ul>
<li>
08
<ul>
<li>
<a href="?id=20">
OW Pick !!!
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Ensuite, ma classe Javascript va masquer et afficher les bons ul selon les clicks sur les li. Le menu se crée en créant un nouvel objet de la sorte :
<script type="text/javascript" charset="utf-8">
//<![CDATA[
var test = new MenuCol.Menu('menuCol');
MenuCol.Item.open();
//]]>
</script>
La statique open() permet d'initialiser le menu sur le li qui contient la classe 'selected' afin de revenir sur le menu correspondant après un chargement de page.
Tout ceci fonctionne grâce au script MenuCol.js, que je rends disponible sous licence GPLv3. Faites en ce que voulez, mais souvenez vous de citer mon nom.
Voir le code Javascript
// Global object
var MenuCol = {};
/**
* Flag to stop propagation of event
* @type Boolean
*/
MenuCol._stopPropagation = false;
/**
Shortcut to document.getElementById
* @param {String/Element} id Element or Element's id
* @returns Element
*/
MenuCol.get = function(id)
{
var elmt = document.getElementById(id);
if (elmt)
{
return elmt;
}
return id;
};
// Objects collection
MenuCols = new Array();
/**
* Menu class
* @constructor
* @param {String/Element} elmt UL menu Element or it's id
* @author Hadrien Lanneau
*/
MenuCol.Menu = function(elmt)
{
/**
* Element
* @type Element
*/
this.element = MenuCol.get(elmt);
/**
* Items inside Menu
* @type Array
*/
this.items = new Array();
MenuCols.push(this);
this.init();
}
MenuCol.Menu.prototype =
{
/**
* Initialize
*/
init: function()
{
// Make Item object with all li children
var lis = this.element.getElementsByTagName('li');
for (var i = 0; lis[i]; i++)
{
if (lis[i].parentNode == this.element)
{
var item = new MenuCol.Item(
lis[i]
);
item.parent = this;
this.items.push(
item
);
}
}
},
/**
* Hide menu
*/
hide: function()
{
this.element.style.display = 'none';
},
/**
* Show Menu
*/
show: function()
{
this.element.style.display = 'block';
}
};
MenuCol.Items = new Array();
/**
* MenuCol.Item class
* @constructor
* @param {String/Element} elmt UL menu Element or it's id
* @author Hadrien Lanneau
*/
MenuCol.Item = function(elmt)
{
/**
* Element
* @type Element
*/
this.element = MenuCol.get(elmt);
/**
* Submenu
* @type MenuCol.Menu
*/
this.submenu = null;
MenuCol.Items.push(this);
this.init();
}
MenuCol.Item.prototype =
{
/**
* Initialize
*/
init: function()
{
// Make Menu object with all UL children
var uls = this.element.getElementsByTagName('ul');
for (var i = 0; uls[i]; i++)
{
if (uls[i].parentNode == this.element)
{
this.submenu = new MenuCol.Menu(
uls[i]
);
this.submenu.parent = this;
this.submenu.hide();
}
}
// Add on click Event on element
this.element.parent = this;
this.element.onclick = this.onclick;
},
/**
* onclick event
*/
onclick: function()
{
// Exec only on first fire
if (!MenuCol._stopPropagation)
{
// If item hasn't submenu, we don't do anything
if (!this.parent.submenu)
{
return true;
}
// Hiding all sub menus of same level
for (var i = 0; this.parent.parent.items[i]; i++)
{
if (this.parent.parent.items[i].submenu)
{
this.parent.parent.items[i].submenu.hide();
this.parent.parent.items[i].activate(
true,
true
);
}
}
// …and their children
for (i = 0; this.parent.submenu.items[i]; i++)
{
this.parent.submenu.items[i].activate(true);
if (this.parent.submenu.items[i].submenu)
{
this.parent.submenu.items[i].submenu.hide();
}
}
// Show corresponding sub menu
this.parent.submenu.show();
// And its parents
var parent = this.parent ?
this.parent :
null;
while (parent)
{
parent.parent.show();
parent.activate(
false,
false
);
parent = parent.parent ?
parent.parent.parent :
null;
}
// Activate item
this.parent.activate(
false,
true
);
// Prevents event propagation on parent's elements
MenuCol._stopPropagation = true;
setTimeout(
function()
{
MenuCol._stopPropagation = false;
},
20
)
}
},
/**
* activate element
* @param {Boolean} oupa True to deactivate
*/
activate: function(oupa, submenu)
{
// Activate item
if (!oupa)
{
this.element.className = 'selected';
}
else
{
this.element.className = '';
}
// Activate submenu
if (submenu)
{
if (!oupa)
{
this.submenu.element.className = 'selected';
}
else
{
this.parent.element.className = '';
}
}
}
};
/**
* Open menu on activated li. Will open on li with 'selected' class
*/
MenuCol.Item.open = function()
{
for (var i = 0; MenuCol.Items[i]; i++)
{
if (MenuCol.Items[i].element.className == 'selected')
{
if (MenuCol.Items[i].submenu)
{
MenuCol.Items[i].element.onclick();
}
else
{
MenuCol.Items[i].parent.parent.element.onclick();
MenuCol.Items[i].activate();
}
}
}
}
Commentaires