I have a dropdown menu system setup such as this…
This is the scripting section of the HTML page.
$('.ui-dropdown').each(function () {
$(this).dropdown();
});
Then in the actual HTML…
<li class="ui-dropdown">
<a href="#">Dropdown Menu</a>
<div>
Test
</div>
</li>
It works very simply. the div is set to display: none;. Then there are methods in the jQuery plugin.
// drop the menu down so that it can be seen.
function drop(e) {
// show the menu section.
options.menu.show();
}
// lift the menu up, hiding it from view.
function lift(e) {
if (!options.menu.is(':visible'))
return;
options.menu.hide();
}
Now, this works okay, but I want the menu to vanish when someone clicks anywhere other than the components inside of the div or the menu’s triggering button. To try and fix that approach, I added this code.
$(document).click(lift);
This works, a little too well. It is catching (obviously) everything, including clicks to the button, the menu, etc. So I tried to fix it with the following functions.
options is defined as follows.
options.button = $(this);
options.menu = $(this).find('> div');
options.links = $(this).find('> a');
options.button.click(function (e) {
options.menu.is(':visible') ? lift() : drop();
e.stopPropogation(); // prevent event bubbling
});
options.links.click(function (e) {
e.stopPropagation(); //prevent event bubbling
});
options.menu.click(function (e) {
e.stopPropagation(); // prevent event bubbling
});
But still no avail. How can I get $(document).click(lift) to be ignored when the menu I am wishing to be interacted with is clicked upon?
Below is the entire jQuery Plugin, just for reference.
jQuery.fn.dropdown = function () {
var defaults = {
class: null,
button: null,
menu: null
};
return this.each(function () {
// initialize options for each dropdown list, since there
// very well may be more than just one.
var options = $.extend(defaults, options);
// specifically assign the option components.
options.class = '.' + $(this).attr('class');
options.list = $(this); // keep a constant reference to the root.
options.button = $(this).find('> a');
options.menu = $(this).find('> div');
// bind the lift event to the document click.
// This will allow the menu to collapse if the user
// clicks outside of it; but we will stop event bubbling to
// keep it from being affected by the internal document links.
$(document).click(function (e) {
var $target = $(e.target);
// check to see if we have clicked on one of the dropdowns, and if so, dismiss
// the execution. We only want to lift one if we're not trying to interact with
// one.
if ($target.is(options.class) || $target.closest(options.class).length)
return false;
lift(e);
});
// when the button is clicked, determine the state of the
// dropdown, and decide whether or not it needs to be lifted
// or lowered.
options.button.click(function (e) {
options.menu.is(':visible') ? lift() : drop();
e.stopPropogation(); // prevent event bubbling
});
// drop the menu down so that it can be seen.
function drop(e) {
// show the menu section.
options.menu.show();
// style the button that drops the menu, just for aesthetic purposes.
options.list.addClass("open");
}
// lift the menu up, hiding it from view.
function lift(e) {
if (!options.menu.is(':visible'))
return;
options.menu.hide();
// style the button that drops the menu, just for aesthetic purposes.
options.list.removeClass('open');
}
});
};
You need to check the target on the click first to make sure that they didn’t click in the list.