window.addEvent('domready', function(){
var menu = new BouncyMenu('container',{
duration: 250
});
$('detach').addEvent('click', function(){
menu.detach();
});
$('attach').addEvent('click', function(){
menu.attach();
});
});
var BouncyMenu = new Class({
Implements: Options,
options: {
duration: 500,
distance: 30
},
initialize: function(element, options){
this.setOptions(options);
this.elements = document.id(element).getChildren();
this.setupElements();
this.attach();
},
setupElements: function(){
this.elements.each(function(element){ // inside this function ...
element.store('originalPadding', element.getStyle('padding-top'));
// `this` would refer to the element ...
element.set('tween',{
duration: this.options.duration // so this wouldn't work ...
});
}, this); // but `each` takes a final argument for binding
// so we bind `this` (the class instance) so `this.options` is
// the options of the class instance instead of element.options
// which isn't what we want
},
attach: function(){
this.elements.each(function(element){
var events = {
mouseenter: function(){
element
.set('tween',{ transition: 'bounce:out' })
.tween('padding-top', this.options.distance); // another option
}.bind(this), // so we have to bind the class instance again
mouseleave: function(){
element
.set('tween',{ transition: 'circ:out' })
.tween('padding-top', element.retrieve('originalPadding'));
}
};
element.store('menuEvents', events);
element.addEvents(events);
}, this);
return this;
},
detach: function(){
this.elements.each(function(element){
element.removeEvents(element.retrieve('menuEvents'));
});
return this;
}
});
<button id="detach">detach</button> <button id="attach">attach</button>
<ul id="container">
<li>The Dark Knight</li>
<li>The Joker</li>
<li>Two Face</li>
<li>Alfred</li>
</ul>
li {
float: left;
padding: 10px;
padding-top: 10px;
background: #f0f0f0;
margin: 4px;
cursor: pointer;
color: #333;
border-bottom: solid 1px #aaa;
}
ul#container {
min-width: 400px;
}
body {
font-family: helvetica, arial;
font-size: 12px;
}