README
Droppy
Pure JavaScript multi-level drop-down menu.
At it's core, Droppy adds or removes CSS classes. This way you are able to
control the menu appearance, just editing the .droppy_drop
and
.droppy__drop--active
CSS classes.
<!-- Classic HTML menu -->
<nav>
<ul class="menu">
<li>
<a href="#">First level - Link #1</a>
<ul class="menu">
<li><a href="#">Second level - Link #1</a></li>
<li><a href="#">Second level - Link #2</a></li>
</ul>
</li>
<li><a href="#">First level - Link #2</a></li>
<li><a href="#">First level - Link #3</a></li>
</ul>
</nav>
Quick Start
Start using Droppy in three steps.
- Download latest Droppy package from Github or via NPM or Bower.
# NPM
npm install droppy-menu --save
# Bower
bower install droppy-menu --save
- Add
dist/droppy.min.css
anddist/droppy.min.js
to your web page.
<link href="/path/to/droppy/dist/droppy.min.css" rel="stylesheet" media="screen">
<script src="/path/to/droppy/dist/droppy.min.js"></script>
- Initialize Droppy in a custom script.
var element = document.querySelector( '.dropdown-menu' );
// Initialize Droppy.
var droppy = new Droppy( element, {
parentSelector: 'li',
dropdownSelector: 'li > ul.menu',
triggerSelector: 'a'
} );
That's it. You're all set to start using Droppy.
Initialize with HTML
You can initialize Droppy in HTML, just adding data-droppy
attribute to the
menu element. Options can be set in its value using valid JSON.
<!-- Init with HTML -->
<nav class="dropdown-menu" data-droppy='{ "parentSelector": "li", "dropdownSelector": "li > ul.menu", "triggerSelector": "a", "closeOthers": true, "clickOutToClose": true, "clickEscToClose": true, "animationIn": '', "animationOut": '', "preventDefault": true }'>
Options
To make Droppy work properly you have to describe your menu structure by
setting the options parentSelector
, dropdownSelector
and triggerSelector
.
// Default options.
var droppy = new Droppy( element, {
parentSelector: 'li',
dropdownSelector: 'li > ul',
triggerSelector: 'a',
closeOthers: true,
clickOutToClose: true,
clickEscToClose: true,
animationIn: '',
animationOut: '',
preventDefault: true
}, callbacks );
<nav class="dropdown-menu"> <!-- The Droppy's element -->
<ul class="menu">
<li> <!-- The parent selector "li" -->
<a href="#">Link #1</a> <!-- The trigger selector "a" -->
<ul class="menu"> <!-- The drop-down selector "li > ul" -->
<li><a href="#">Link #1</a></li>
<li><a href="#">Link #2</a></li>
</ul>
</li>
<li><a href="#">Link #2</a></li>
<li><a href="#">Link #3</a></li>
</ul>
</nav>
dropdownSelector - It's a valid CSS selector of your drop-down. In the example above I have a drop-down when there is a
<ul class="menu">
son of a<li>
. That's why thedropdownSelector
is set toli > ul.menu
.parentSelector - It's a valid CSS selector of your parent element. The parent element have to contain the trigger element and the drop-down element. It should be the closest parent. In the example above the closest parent of both -
dropdownSelector
andtriggerSelector
- is the<li>
element. That's why theparentSelector
is set toli
.triggerSelector - It's a valid CSS selector of the element that triggers the open or close event. In the example above the trigger is the
<a>
element. That's why thetriggerSelector
is set toa
.closeOthers - A boolean value. Set to
true
if you want keep open only one drop-down at a time.clickOutToClose - A boolean value. Set to
true
if you want to close all the drop-downs by clicking on the outside of the current menu.clickEscToClose - A boolean value. Set to
true
if you want to close all the drop-downs by clicking ESC.animationIn - A CSS class where is declared an animation. This class will be applied at the open of a drop-down and removed at the end of the animation.
animationOut - A CSS class where is declared an animation. This class will be applied at the close of a drop-down and removed at the end of the animation.
preventDefault - A boolean value. If the
triggerSelector
is an element that fires an event, you can prevent the execution of the default behavior setting this option totrue
. E.g. IftriggerSelector
is a link, we want the browser opens the drop-down, not follows the link. SettingpreventDefault
totrue
prevents the browser to follow the link.
Methods
Methods are actions done by Droppy instances.
// Instantiate
var droppy = new Droppy( element, options, callbacks );
init()
Initialize a Droppy object. It adds Droppy CSS classes and events.
// Init Droppy object
droppy.init();
destroy()
Reset a Droppy instance to a pre-init state. It removes Droppy CSS classes and events.
// Reset Droppy instance to a pre-init state
droppy.destroy();
open( dropdown, withDescendants )
Open the given drop-down. If closeOthers
is set to true
, the other
drop-downs will be closed before opening the current one.
{Element|DroppyNode} dropdown
- The drop-down element to open.{Boolean} [withDescendants=false]
- Should open or not all the drop-downs in the given drop-down.
var dropdown = document.querySelector( '#menu-main .droppy__drop' )
// Open a drop-down
droppy.open( dropdown );
close( dropdown, withDescendants )
Close the given drop-down and all its descendants.
{Element|DroppyNode} dropdown
- The drop-down element to close.{Boolean} [withDescendants=true]
- Should close or not all the drop-downs in the given drop-down.
var dropdown = document.querySelector( '#menu-main .droppy__drop' )
// Close a drop-down
droppy.close( dropdown );
toggle( dropdown, withDescendants )
Open or close the given drop-down.
{Element|DroppyNode} dropdown
- The drop-down element to toggle.{Boolean} [withDescendants=undefined]
- Should toggle or not all the drop-downs in the given drop-down.
var dropdown = document.querySelector( '#menu-main .droppy__drop' )
// Toggle a dropdown
droppy.toggle( dropdown );
openAll()
Open all drop-downs of a menu.
// Open all drop-downs
droppy.openAll();
closeAll()
Close all drop-downs of a menu.
// Close all drop-downs
droppy.closeAll();
on( event, callback, context )
Subscribe to an event.
{string} event
- The name of the event to subscribe to.{function} callback
- The function to call when the event is emitted.context
- The context to bind to the callback.
// The callback function.
function alertOpen( event ) {
alert( 'Open!' );
console.log( event );
}
// Subscribe to open event.
droppy.on( 'open', alertOpen );
once( event, callback, context )
Subscribe to an event once.
{string} event
- The name of the event to subscribe to.{function} callback
- The function to call when the event is emitted.context
- The context to bind to the callback.
// SUbscribe to open event once.
droppy.once( 'open', alertOpen );
off( event, callback )
Unsubscribe to an event. If no callback is provided, unsubscribe from all events.
{string} event
- The name of the event to unsubscribe from.{function} callback
- The function used when binding to the event.
// Unsubscribe to open event.
droppy.off( 'open', alertOpen );
Droppy.prototype.isInitialized( droppy )
It returns true if the given Droppy instance is initialized, false otherwise.
var droppy = new Droppy( element, options );
// Check if initialized
var initialized = Droppy.prototype.isInitialized( droppy );
Droppy.prototype.getInstance( element )
It returns the Droppy instance used by the given element.
var element = document.querySelector( '[data-droppy]' );
// Get the instance
var droppy = Droppy.prototype.getInstance( element );
Events
Events are "things" that happen at a specific point of execution. You can listen to Droppy's events and react to them. Here's a list of Droppy's events.
init
- Dispatched when a Droppy object is initialized.destroy
- Dispatched when a Droppy object is destroyed.open
- Dispatched when a drop-down is opened.close
- Dispatched when a drop-down is closed.openAll
- Dispatched when all drop-downs of a menu are opened.closeAll
- Dispatched when all drop-downs of a menu are closed.
Callbacks
DEPRECATED - Callbacks will be removed in v2.0.0 in favor of events.
Callbacks are function called at a specific point of execution. Callbacks does
not wait for animation end, this may cause the execution of afterOpen
,
afterClose
, afterOpenAll
and afterCloseAll
when the drop-down is not
completely opened or closed yet.
// Default callbacks.
var droppy = new Droppy( element, options, {
beforeOpen: null,
afterOpen: null,
beforeClose: null,
afterClose: null,
beforeOpenAll: null,
afterOpenAll: null,
beforeCloseAll: null,
afterCloseAll: null,
beforeInit: null,
afterInit: null,
beforeDestroy: null,
afterDestroy: null
} );
Define a callback
Define a callback in three steps.
- Create your callback function.
function alertCallback() {
alert( 'Before open.' );
}
- Assign the function to the
callbacks
object.
var callbacks = {
beforeOpen: alertCallback
}
- Create a Droppy object with the callbacks.
var droppy = new Droppy(element, options, callbacks);
Detect drop-down structure
Understanding how Droppy detect your drop-down menu structure, can help you set
*Selector
options correctly.
Droppy starts from dropdownSelector
to detect your drop-down menu structure.
For each drop-down, Droppy loops through element parents until reach the first
element that matches the parentSelector
. Once got the parent element, Droppy
selects the first element child of the parent element that matches the
triggerSelector
.
Instead of querying at every click the DOM, Droppy stores your drop-down menu
structure in the tree
property. The tree
is an array of DroppyNode
instances.
var droppy = new Droppy( element, options, callbacks );
// Print the tree
console.log( droppy.tree );
Polyfills
Droppy uses a bunch of polyfills to be compatible with old browsers. Here's a list of polyfills used.