?
Solved

How to Prevent Bubbling in a DIV Drop Down Menu w/JavaScript or jQuery?

Posted on 2011-10-31
10
Medium Priority
?
330 Views
Last Modified: 2012-05-12
I've spent hours on this and it's becoming a bit frustrating. Anyway, I'm trying to create a custom drop down menu using DIVs and JavaScript/jQuery in my MVC 3 application. I can get it to work when the user clicks on the menu header, then clicks on it again to close it. But I want to be able to close the menu when a user moves their mouse off the "selectMain" DIV.

I tried to do this on the "selectMain" div, but because of bubbling, as soon as you move your mouse to access the first menu item, the menu disappears.

I've probably been to a dozen different sites trying to find the answer and cannot.

The HTML is listed below, the  entire drop down menu is located in the DIV with ID "selectMain". And the menu itself that should appear and disappear is located in the DIV with ID "selectMenu".

<body>
    <div class="page">
        <div id="header">
            <div id="title">
                <a href="/" style="width:242px;height:64px;"><h1><span>site logo</span></h1></a>
            </div>
            <div id="menucontainer">
                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")<img src="/Content/Images/divider.gif" /></li>
                    <li>@Html.ActionLink("Learn More", "Learn", "Home")<img src="/Content/Images/divider.gif" /></li>
                    <li>@Html.ActionLink("Products", "Index", "Products")<img src="/Content/Images/divider.gif" /></li>
                    <li>@Html.ActionLink("Specifications", "Specifications", "Home")</li>
                    <li>
                        <div id="selectMain">
                            <div id="select" onclick="showHideMenu('menu');">
                                <span style="font-family:arial">OUR FAMILY OF BRANDS</span>
                                <div id="img"><img src="/Content/Images/select_arrow.gif" alt="Our Family of Brands" /></div>
                                <div id="selectMenu">
                                    <div><a href="url" target="_blank">Site 1</a></div>
                                    <div><a href="url" target="_blank">Site 2</a></div>
                                    <div><a href="url" target="_blank">Site 3</a></div>
                                    <div><a href="url" target="_blank">Site 4</a></div>
                                    <div><a href="url" target="_blank">Site 5</a></div>
                                </div>
                            </div>
                        </div>
                    </li>
                </ul>
            </div>
        </div>
        <div id="main">
            @RenderBody()
        </div>
        <div id="footer" class="clear"></div>
    </div>
</body>

Open in new window


And here is the JavaScript/jQuery that is doing the opening & closing when a user clicks on "select" DIV.

function showHideMenu(f) {
    var selectMenuObj = $("#selectMenu");
    var curVis = selectMenuObj.css('visibility');

    if (f == "menu") {
        if (curVis == "hidden") {
            selectMenuObj.css({ 'visibility': 'visible' });
            selectMenuObj.css({ 'display': 'block' });
        }
        else {
            selectMenuObj.css({ 'visibility': 'hidden' });
            selectMenuObj.css({ 'display': 'none' });
        }
    }
}

Open in new window


I'd also prefer not to rework the HTML and add or get rid of DIVs if possible because I don't want to have to rewrite the CSS all over again.

Please help! Thanks!!
0
Comment
Question by:infotechelg
  • 6
  • 2
  • 2
10 Comments
 
LVL 19

Expert Comment

by:moagrius
ID: 37061971
you can stop propagation of an event with event.stopPropagation:

$('#something').mouseover(function(e){
  e.stopPropagation();  // will not fire mouseover handler bound to a parent element
});

but i don't think that's what you want - since the mouseout is still actually firing...  rather, i think you want the mouseleave event, bound to the selectMain element, which only fires when the mouse leaves the element it's bound to entirely, and does not fire when moving over children.
0
 

Author Comment

by:infotechelg
ID: 37062959
I tried this in my .js file and nothing happened.

$("#selectMain").mouseleave(function () {
    $("#selectMenu").hide();
});

Open in new window

0
 

Author Comment

by:infotechelg
ID: 37062987
Plus, I read that "mouseleave" only works in IE, so this isn't an option. I see what I want to do all the time, so there has to be a way to make this work.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 19

Accepted Solution

by:
moagrius earned 1000 total points
ID: 37063401
the jQuery implementation of mouseleave is cross-browser: http://api.jquery.com/mouseleave/

i can't tell you why it's not working for you from that brief description - did you remove the previous mouseout code?

here's a very simple fiddle showing mouseleave behavior:  http://jsfiddle.net/UhaEZ/

if you change it to mouseout, you'll see it fires when the mouse enters child nodes

0
 

Author Comment

by:infotechelg
ID: 37063462
I never had mouseout code to begin with.

So, I added to LINE 15 in the code above an "onmouseleave" command and it works in IE & Opera, but it doesn't work in FF, Safari, or Chrome.

<div id="select" onclick="showHideMenu('menu');" onmouseleave="showHideMenu('menu');">

Open in new window


I still can't get this to function using jQuery.
0
 
LVL 14

Assisted Solution

by:Designbyonyx
Designbyonyx earned 1000 total points
ID: 37063496
First off, get rid of the inline "onclick" - that's not good practice and makes for a very difficult to maintain application... which sort of negates your efforts in using MVC - which is a fairly easy-to-maintain development pattern.

See my attached code.  If you have any questions, I would be glad to explain what is going on.  Take note of the padding on #selectMain - this is required to ensure the "mouseout" event get triggered.  If you remove the padding, you will notice the "mouseout" event is only triggered when you are moving your mouse really slow.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
	var $selectMain = $('#selectMain'),
		$selectMainHeading = $selectMain.find('#select > span'),
		$selectMainMenu = $selectMain.find('#selectMenu');
	
	$selectMainHeading.bind('click.dropdown', function() {
		if( $selectMainMenu.is(':visible') ) {
			$selectMain.unbind('mouseout.dropdown');
			$selectMainMenu.hide();
		} else {
			$selectMainMenu.show();
			$selectMain.bind('mouseout.dropdown', function(e) {
				console.log( $(e.target).attr('id') );
				if( $(e.target).is($selectMain) ) {
					$selectMainHeading.trigger('click.dropdown');
				}
			});
		}
	});
});
</script>

<style type="text/css">
#selectMain {
	padding: 1em;
	border: 1px solid blue;	
}
#selectMenu {
	display: none;
	border: 1px solid red;
}
</style>
</head>

<body>

<div id="selectMain">
    <div id="select">
        <span style="font-family:arial">OUR FAMILY OF BRANDS</span>
        <div id="img"><img src="/Content/Images/select_arrow.gif" alt="Our Family of Brands" /></div>
        <div id="selectMenu">
            <div><a href="url" target="_blank">Site 1</a></div>
            <div><a href="url" target="_blank">Site 2</a></div>
            <div><a href="url" target="_blank">Site 3</a></div>
            <div><a href="url" target="_blank">Site 4</a></div>
            <div><a href="url" target="_blank">Site 5</a></div>
        </div>
    </div>
</div>

</body>
</html>

Open in new window

0
 
LVL 14

Expert Comment

by:Designbyonyx
ID: 37063511
DOH - I left logging code in there - that line will cause the code to break in browsers that don't have a console.  Remove that line before you start using this code... put it back for debugging purposes only.

Cheers.
0
 

Author Comment

by:infotechelg
ID: 37063702
Hey designbyonyx,

Thank you for taking the time to write the code. however, it doesn't function properly. The "click" works and the menu appears below the select header. But if I move my mouse out down past the bottom of the menu that appears, the menu remains. It only disappears if my mouse is within that blue bounding box your styles created AND not over the actual menu.

If that makes any sense.
0
 

Assisted Solution

by:infotechelg
infotechelg earned 0 total points
ID: 37063774
Thanks, designbyonyx and moagrius. Both of your comments helped. Design, i modified yours a bit using comments by moagrius and got it to work perfectly. Here's the code:

$(function () {
    var $selectMain = $('#selectMain'),
            $selectMainHeading = $selectMain.find('#select'),
            $selectMainMenu = $selectMain.find('#selectMenu');

    $selectMainHeading.bind('click.dropdown', function () {
        if ($selectMainMenu.is(':visible')) {
            $selectMain.unbind('mouseout.dropdown');
            $selectMainMenu.hide();
        } else {
            $selectMainMenu.css({ 'visibility': 'visible' });
            $selectMainMenu.css({ 'display': 'block' });

            $selectMain.mouseleave(function () {
                $selectMainMenu.hide();
            });
        }
    });
});

Open in new window

0
 

Author Closing Comment

by:infotechelg
ID: 37089771
Thanks for all your help. The code I provided works in IE, FF, Opera, Chrome, Safari.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will give core knowledge of JavaScript and will head in to your first JavaScript program. I am Durvesh Naik and I am here to deal with this series of JavaScript. I will teach you JavaScript in part wise , as its quite boring to read big…
This article discusses how to create an extensible mechanism for linked drop downs.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…
Suggested Courses

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question