0

I am trying to debug the following script to ensure the best, desired UX. This script is not working quite as desired, as seen on this fiddle.

    $("ul.menu li").mouseover(function() {
        $(this).find("ul.sub-menu").animate({"opacity": "show"}, 800, "swing");

        $(this).hover(function() {}, function(){
            $(this).find("ul.sub-menu").animate({"opacity": "hide"}, "slow");
        });
    });

As you can see the animations don't trigger initially. Also if the user accidentally hovers over multiple links then undesired animations get stuck playing for many seconds onward. I want to edit this responsiveness. What are currently some of the top ways to deal with this in professional UI design when working with jQuery and how can I implement these solutions into my script?

Jim22150
  • 511
  • 2
  • 8
  • 22
  • 1
    What is your expected output? – ATOzTOA Jan 28 '13 at 04:37
  • 1
    pretty sure `show` and `hide` are not valid `opacity` settings. regardless, this is how you should animate for maximum compatibility http://stackoverflow.com/questions/14312849/jquery-call-css3-version-of-stoptrue-false-and-animate-from-event –  Jan 28 '13 at 04:44

3 Answers3

1

Try .stop().animate({...}); to stop any existing animations before beginning a new one.

Docs: http://api.jquery.com/stop/

Chris Barr
  • 29,851
  • 23
  • 95
  • 135
1

I can't reproduce your first problem. However, I updated the script a bit to hopefully get your desired behavior (at least closer):

  1. Use .stop after the animations to halt them so they don't queue with repeated events
  2. Don't bind the .hover event inside the callback. Bind it separately
  3. Use .mouseenter/.mouseleave so that the event is not triggered by moving over different elements with the same parent.

http://jsfiddle.net/pF8wZ/2/

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • Good answer, however I noticed another bug. When hovering over a parent menu item to trigger the animation, if you move your mouse down into the submenu before the animation is finished then the previously hovered submenu flashes back into place, hiding the newly selected item's submenu. Can you provide an approach to address this bug? Thanks again! – Jim22150 Jan 28 '13 at 05:54
1

You are nesting mouseover() and .hover() which was the main issue. You just simply want to show something when you hover over it, and then reverse the animation when you hover out.

Try this: http://jsfiddle.net/pF8wZ/4/

jQuery(document).ready(function($) {
    $("ul.menu > li").hover(
        function() {
            $(this).find("ul.sub-menu").stop().animate({
                height: 'toggle',
                opacity: 'toggle'
            });
        }
    );
});

I also cleaned up your CSS from the fiddle. You just need this to make the hovering behavior work:

#access {
background: #000;
margin: 0 auto;
display: block;
float: left;
    position: relative;
}
ul.menu { 
    list-style: none;
    margin: 0;
}
ul.menu > li {
    float: left;
    padding: 5px;
    background: #ccc;
}
#access ul .sub-menu {
    position: absolute;
    left: 0;
    top: 100%;
    margin: 0;
    width: 200px;
    background-color: #474747;
    -moz-border-radius-bottomleft: 10px;
    -webkit-border-bottom-left-radius: 10px;
    -moz-border-radius-bottomright: 10px;
    -webkit-border-bottom-right-radius: 10px;
    display: none;
}
#access ul .sub-menu a {
    background: #333;
    line-height: 1em;
    display: block;
    padding: 3px 5px;
    background-image: -moz-linear-gradient(100% 100% 90deg, #474747, #939393);
    background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#939393), to(#474747));
}

And the HTML:

<div id="access">
<div class="menu-header">

<ul id="menu-wordpress-sandbox-menu" class="menu">
    <li id="menu-item-17" class="menu-item">
        <a href="#">Fruits</a>
        <ul class="sub-menu">
            <li id="menu-item-19" class="menu-item"><a href="#">Oranges</a></li>
            <li id="menu-item-20" class="menu-item"><a href="#">Apples</a></li>
        </ul>
    </li>
    <li id="menu-item-32" class="menu-item">
        <a href="#">Colors</a>
        <ul class="sub-menu">
            <li id="menu-item-30" class="menu-item"><a href="#">Blue</a></li>
            <li id="menu-item-31" class="menu-item"><a href="#">Red</a></li>
        </ul>
    </li>
    <li id="menu-item-33" class="menu-item">
        <a href="#">Links</a>
        <ul class="sub-menu">
            <li id="menu-item-34" class="menu-item"><a href="#">Google</a></li>
            <li id="menu-item-35" class="menu-item"><a href="#">Yahoo!</a></li>
        </ul>
    </li>
</ul>

</div>
</div>
matthewpavkov
  • 2,918
  • 4
  • 21
  • 37
  • It looks like you have a typo in your fiddle link url, Matthew. – Jim22150 Jan 28 '13 at 05:02
  • 1
    Yes I did. Updated. Thanks. – matthewpavkov Jan 28 '13 at 05:17
  • Good answer, however I noticed another bug. When hovering over a parent menu item to trigger the animation, if you move your mouse down into the submenu before the animation is finished then the previously hovered submenu flashes back into place, hiding the newly selected item's submenu. Can you provide an approach to address this bug? Thanks again! – Jim22150 Jan 28 '13 at 05:55
  • 1
    I updated my answer. I believe this gets you pretty close to the behavior you want. As others suggested here, I added in `stop()`. Additionally, I'm using `toggle` values for `height` and `opacity`. There were also some CSS and HTML adjustments. – matthewpavkov Jan 28 '13 at 16:33
  • Very impressive shortening the code, but the bug is still appearing on my machine. It doesn't appear on the initial hover of each parent item. It seems to only happen, [as can be seen from your fiddle](http://jsfiddle.net/pF8wZ/4/), if hovered over 2nd parent item, then hover 1st parent, then quickly hover into 1st sub-menu, you will see the desired sub-menu disappear, very strange. – Jim22150 Jan 28 '13 at 22:37
  • Also, I should add that also if hovered over 3rd parent item, then hover 2nd parent, and then quickly hover into 2nd sub-menu, you will again see the undesired effects, or bug. How can these events be eliminated to ensure the best UX? Thanks. – Jim22150 Jan 28 '13 at 22:54
  • Ok, what's happening is you're hovering back over the submenu before it completely collapses. You hover over parent `A` then hover over parent `B`, parent `B` submenu shows, you move your mouse back to `A` and immediately move down over the submenu, *but* `B` submenu hasn't yet full collapsed. There's nothing you can really do to prevent this, as that is the correct behavior. http://jsfiddle.net/pF8wZ/7/ – matthewpavkov Jan 29 '13 at 03:18
  • 1
    Well, you could do something like this http://jsfiddle.net/pF8wZ/8/ You'll lose the collapsing animation if you immediately hover back over a `li`. Really, I think how it is currently is acceptable. However, this way is a little more user-proof. – matthewpavkov Jan 29 '13 at 03:24
  • Yes, I believe this is the user-proof effect I need. Very nice addition to the script. It is butter smooth now! Thanks a ton! – Jim22150 Jan 29 '13 at 20:48