Search code examples
jqueryfocusanchoronfocus

Use jQuery to add class to parent div based on what anchor is focused


I have a list of anchors, and I want them to add a unique class to a particular div ID, based on what anchor is currently focused. I have it working for anchor hover, but I'm having a hard time figuring out how to also do this for anchor focus. I want to implement anchor focus, so that he class still gets added to the div ID even if someone navigates through the anchors via keyboard.

Here is my code (which could probably be cleaned up) for the hover classes. I need these classes (unique per anchor) to be added to the #industries div if the anchor has focus (not just on hover).

HTML structure:

<div id="industries" class="et_pb_section">
    <div class="et_pb_row">
        <div class="et_pb_column">
            <div id="industries-list" class="et_pb_module">
                <div class="et_pb_text_inner">
                    <ul>
                        <li><a href="#education">Education</a></li>
                        <li><a href="#energy">Energy</a></li>
                        <li><a href="#healthcare">Healthcare</a></li>
                    </ul>
                </div>
            </div> <!-- .et_pb_text -->
        </div> <!-- .et_pb_column -->
    </div> <!-- .et_pb_row -->
</div> <!-- .et_pb_section -->

jQuery code:

(function ($) {

    $(document).ready(function () {
        industriesBackgrounds();
    });

    function industriesBackgrounds() {
        $('#industries-list [href="#education"]').hover(function(){     
            $('#industries').addClass('industry-education-hover');    
        },
        function(){    
            $('#industries').removeClass('industry-education-hover');     
        });
        $('#industries-list [href="#energy"]').hover(function(){     
            $('#industries').addClass('industry-energy-hover');    
        },
        function(){    
            $('#industries').removeClass('industry-energy-hover');     
        });
        $('#industries-list [href="#healthcare"]').hover(function(){     
            $('#industries').addClass('industry-healthcare-hover');    
        },
        function(){    
            $('#industries').removeClass('industry-healthcare-hover');     
        });
    }

})(jQuery);

Update:

For now, I have this sort of working, by adding this code to my industriesBackgrounds function.

$('#industries').delegate( '#industries-list a[href="#education"]', 'focus blur', function() {
    var anchor = $( this );
    setTimeout(function() {
        $('#industries').toggleClass( 'industry-education-focus', anchor.is( ":focus" ) );
    }, 0 );
});
$('#industries').delegate( '#industries-list a[href="#energy"]', 'focus blur', function() {
    var anchor = $( this );
    setTimeout(function() {
        $('#industries').toggleClass( 'industry-energy-focus', anchor.is( ":focus" ) );
    }, 0 );
});
$('#industries').delegate( '#industries-list a[href="#healthcare"]', 'focus blur', function() {
    var anchor = $( this );
    setTimeout(function() {
        $('#industries').toggleClass( 'industry-healthcare-focus', anchor.is( ":focus" ) );
    }, 0 );
});

I'm not sure if this is the best way to go about it. But, since a user can technically have one anchor focused, while hovering over a different one, it may be ideal to use 2 separate classes (one for focus, and one for hover), to determine the true "event" taking place.

But is this the best way to code these 2 states? Is there a cleaner solution to achieving the goal of adding a class to the ID, for hover and focus?


Solution

  • You can shorten your code by combining selector and event delegation. .hover() is shorthand for mouseenter mouseleave:

    I would provide more advise if I had a working example.

    See this example:

    (function($) {
    
      $(document).ready(function() {
        industriesBackgrounds();
      });
    
      function industriesBackgrounds() {
        $('#industries-list a').on("mouseenter mouseleave", function(e) {
    
          const type = e.type;
          const href = jQuery(this).attr("href").replace("#", "");
    
          $('#industries').toggleClass(`industry-${href}-hover`, type == 'mouseenter');
          
          console.log((type == 'mouseenter') ? `Added` : `Removed`, `industry-${href}-hover`);
        }).on("focus blur", function(e) {
    
          const type = e.type;
          const href = jQuery(this).attr("href").replace("#", "");
    
          $('#industries').toggleClass(`industry-${href}-hover`, type == 'focus');
          console.log((type == 'focus') ? `Added` : `Removed`, `industry-${href}-hover`);
    
        });
      }
    
    })(jQuery);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="industries" class="et_pb_section">
      <div class="et_pb_row">
        <div class="et_pb_column">
          <div id="industries-list" class="et_pb_module">
            <div class="et_pb_text_inner">
              <ul>
                <li><a href="#education">Education</a></li>
                <li><a href="#energy">Energy</a></li>
                <li><a href="#healthcare">Healthcare</a></li>
              </ul>
            </div>
          </div>
          <!-- .et_pb_text -->
        </div>
        <!-- .et_pb_column -->
      </div>
      <!-- .et_pb_row -->
    </div>
    <!-- .et_pb_section -->