Jquery call function on hover if element is of class A but not class B

I want to call a function when hovering over elements with a specific class attribute, but not another. I feel like the :not selector should work, but it is still firing for all elements of class A.

I have elements with a specific class .sidebar-section, but one of them has another class attribute .show, I want to call a function on hover for class sidebar-section excluding elements that are also of the class show.

    <div class="sidebar-section show" id="one">
        <div class="sidebar-title">Ones</div>
    </div>
    <div class="sidebar-section" id="two">
        <div class="sidebar-title">Twos</div>
    </div>

I want to set up a hover listener for sidebar-section that will fire when hovering over Twos but not over Ones. I have tried $(".sidebar-section:not(.show)").hover() but for some reason this is not working, since it still fires for all sidebar-sections.

$(".sidebar-section:not(.show)").hover(
    function () {
        toggleSection(this.id);
    },
    function () {
        toggleSection(this.id);
    }
);

Here is a mock-up of what I’m trying to achieve. Basically I want to expand the divs on mouseenter and collapse them again on mouseexit, unless the div is already expanded.

Thanks to @CBroe’s suggestion I’ve edited the code by moving the check for the show class into hover handler. This accomplished the main part of my question since the shown element no longer collapses when hovered over, and will work in my project. But I’m starting to realize my structure doesn’t lend itself to elegant solutions.

Would it be better to use show for whatever is set externally as visible. And then have another class attribute like isHover to track state while hovering? Or should the whole approach be reworked?

//Contents are hidden unless section is selected
$(function () {
    $(".sidebar-contents").hide();
    toggleSection("one");
});

$(".sidebar-section").hover(
    function () {
        if(!$(this).hasClass("show")){
            toggleSection(this.id);
        }
    },
    function () {
        toggleSection(this.id);
    }
);

//toggles collapsed/expanded view of sidebar sections
function toggleSection(name) {
    $("#" + name).children('.sidebar-contents').toggle();
    $("#" + name).children('.sidebar-title').toggle();
    $("#" + name).toggleClass('show');
}
#sidebar-container {
    display: flex;
    height: 100%;
}

.sidebar-section {
    background-color: blue;
    writing-mode: vertical-lr;
}

.sidebar-section.show {
    background-color: yellow;
    writing-mode: horizontal-tb;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sidebar-container">
    <div class="sidebar-section" id="one">
        <div class="sidebar-title">Ones</div>
        <ul class="sidebar-contents">
            <li>Item 1</li>
        </ul>
    </div>
    <div class="sidebar-section" id="two">
        <div class="sidebar-title">Twos</div>
        <ul class="sidebar-contents">
            <li>Item 2</li>
        </ul>
    </div>
</div>

25 thoughts on “Jquery call function on hover if element is of class A but not class B”

  1. The problem is with your toggleSection function. When you hover over an item, you are toggling the show class. That is why, your selector doesn’t work. Can you update your hover function with this:

    $(".sidebar-section").hover(
        function () {
            $(this).children('.sidebar-contents').show();
            $(this).children('.sidebar-title').hide();
            $(this).addClass('show');
        },
        function () {
            $(this).children('.sidebar-contents').hide();
            $(this).children('.sidebar-title').show();
            $(this).removeClass('show');
        }
    );
    
    Reply

Leave a Comment