Search code examples
javascriptjqueryjquery-eventsmouseentermouseleave

Prevent flickering/code running too often with on() and mouseenter/mouseleave


I need to show some hidden content above an image when mousing over the image. The issue I'm running into is the content flashes (due to the opacity) and because the show/hide events fire way to much.

How can this be updated so it will only run one time when hovering over the image?

What is the best way to attach/detach the click event for the anchor?

JSFiddle

HTML:

<ul>
    <li>
        <img src="http://placehold.it/350x150" />
        <div>
             <h3>Title</h3>

            <p>Vivamus hendrerit arcu sed erat molestie vehicula. Sed auctor neque eu tellus rhoncus ut eleifend nibh porttitor. Ut in nulla.</p> <a href="#">+</a>

        </div>
    </li>
    <li>
        <img src="http://placehold.it/350x150" />
        <div>
             <h3>Title</h3>

            <p>Vivamus hendrerit arcu sed erat molestie vehicula. Sed auctor neque eu tellus rhoncus ut eleifend nibh porttitor. Ut in nulla.</p> <a href="#">+</a>

        </div>
    </li>
    <li>
        <img src="http://placehold.it/350x150" />
        <div>
             <h3>Title</h3>

            <p>Vivamus hendrerit arcu sed erat molestie vehicula. Sed auctor neque eu tellus rhoncus ut eleifend nibh porttitor. Ut in nulla.</p> <a href="#">+</a>

        </div>
    </li>
    <li>
        <img src="http://placehold.it/350x150" />
        <div>
             <h3>Title</h3>

            <p>Vivamus hendrerit arcu sed erat molestie vehicula. Sed auctor neque eu tellus rhoncus ut eleifend nibh porttitor. Ut in nulla.</p> <a href="#">+</a>

        </div>
    </li>
</ul>

CSS:

body {
    margin: 0;
    padding:0;
}
ul {
    overflow: hidden;
    margin: 0;
    padding:0;
    list-style-type: none;
}
li {
    float: left;
    padding: 0;
    cursor: pointer;
    margin: 0;
    width: 50%;
    position: relative;
}
img {
    display: block;
}
div {
    display: none;
    background: black;
    opacity: .4;
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    padding: 1em;
    color: white;
}
h3 {
    margin-top: 0;
}

jQuery:

var $img = $('ul').find('img');

$img.on({
    mouseenter: function () {
        var $div = $(this).siblings('div'),
            $a = $div.find('a');

        $div.show();

        $a.on('click', function (e) {
            var $container = $(this).closest('.content');

            e.preventDefault();

            console.log('clicked');
        });
    },
    mouseleave: function () {
        var $div = $(this).siblings('div'),
            $a = $div.find('a');

        $div.hide();
        $a.off('click');
    }
});

Solution

  • Why do you assign and delete the click event to the anchor over and over again? Do it once:

    $('ul a').click(function(e) {
        var $container = $(this).closest('.content');
    
        e.preventDefault();
    
        console.log('clicked');
    });
    

    And then let the magic work with CSS by adding this:

    li:hover div {
        display: block;
    }
    

    Much less Javascript now: JsFiddle