JavaScript - Apply function to a specific div in a collection of divs with the same class name

When I hover over .winner-container, the JS function tells .headline to move out of .winner-container and it tells .bottom to move into .winner-container. When I unhover, the opposite occurs.

The problem is, I'm going to have hundreds of these containers, all with the .winner-container class. So I've realised that when I hover over one of the containers, the function is applied to hundreds of different containers all at once. I only want the function to be applied to the specific container I'm hovering over. I could do this by giving each container an id, and then write new JS code for each id, but that would require a lot of work, considering there will be hundreds of these divs. Is there a more elegant solution?

https://jsfiddle.net/6sm6ajht/

HTML

<div class="winner-container">
  <div class="top">
    <h4 class="headline">SME Example 1</h4>
  </div>
  <div class="bottom">
    <div class="winner-words">
      <h6>SME Examle 1 is a technology company.</h6>
      <h6><a>Learn more...</a></h6>
    </div>
  </div>
</div>

<div class="winner-container">
  <div class="top">
    <h4 class="headline">SME Example 2</h4>
  </div>
  <div class="bottom">
    <div class="winner-words">
      <h6>SME Examle 2 is an e-commerce company.</h6>
      <h6><a>Learn more...</a></h6>
    </div>
  </div>
</div>

CSS

.winner-container {
  position: relative;
  box-shadow: 0px 2.5px 1px 0px rgba(0, 0, 0, 0.25);
  border: 1px solid #074E68;
}

.winner-container,
.top,
.bottom {
  width: 10em;
  height: 12em;
  overflow: hidden;
}

.bottom {
  position: absolute;
  height: 12em;
  width: 100%;
  top: 12em;
  transition: 0.5s ease-in-out;
}

.top .headline {
  position: absolute;
  top: 2.5em;
  width: 100%;
  background: rgba(255, 255, 255, 0.8);
  box-shadow: 0px 1px 1px 2px rgba(0, 0, 0, 0.1);
  transition: 0.5s ease-in-out;
}

.top-up .headline {
  top: -2.5em;
}

.bottom-up.bottom {
  top: 0em;
  background-color: rgba(0, 0, 0, 0.65);
}

JavaScript

$(".winner-container").on("mouseenter", function() {
  $(".top").addClass('top-up');
  $(".bottom").addClass('bottom-up');
});

$(".winner-container").on("mouseleave", function() {
  $(".top").removeClass('top-up');
  $(".bottom").removeClass('bottom-up');
});

4 answers

  • answered 2017-06-17 19:34 Quagaar

    Change your selectors for .top and .bottom to $(this).find('.top') and $(this).find('.bottom').

    this in the context of the event handler is the element on which the event occurred.

  • answered 2017-06-17 19:34 glhrmv

    This is a great opportunity for the $(this) selector. Because there are many identical elements but you only want each event handler to refer to that particular element, you can use $(this) and use a relative selector like .children to target other elements relative to the this element.

    JSfiddle

    $(".winner-container").on("mouseenter", function() {
      $(this).children(".top").addClass('top-up');
      $(this).children(".bottom").addClass('bottom-up');
    });
    
    $(".winner-container").on("mouseleave", function() {
      $(this).children(".top").removeClass('top-up');
      $(this).children(".bottom").removeClass('bottom-up');
    });
    

  • answered 2017-06-17 19:34 Maxime G

    you can try using the $(this) selector in order to specify that you only want the current element to be the scope of your directives:

    $(".winner-container").on("mouseenter", function() {
      $(this).children(".top").addClass('top-up');
      $(this).children(".bottom").addClass('bottom-up');
    });
    
    $(".winner-container").on("mouseleave", function() {
      $(this).children(".top").removeClass('top-up');
      $(this).children(".bottom").removeClass('bottom-up');
    });
    

  • answered 2017-06-17 19:34 Daniel H

    $(".winner-container") will target all element with class winner-container and add an event to each of them, that's why you have two elements but you only need to define it once.

    Same as $('.top'), this will target all class called top, you need to use $(this).find('.top') inside the event to target ONLY the current element and use find() to search inside this element, find top and bottom add or remove class do whatever you want.

    $(".winner-container").on("mouseenter", function() {
      $(this).find('.top').addClass('top-up');
      $(this).find('.bottom').addClass('bottom-up');
    });
    
    $(".winner-container").on("mouseleave", function() {
      $(this).find('.top').removeClass('top-up');
      $(this).find('.bottom').removeClass('bottom-up');
    });
    .winner-container {
      position: relative;
      box-shadow: 0px 2.5px 1px 0px rgba(0, 0, 0, 0.25);
      border: 1px solid #074E68;
    }
    
    .winner-container,
    .top,
    .bottom {
      width: 10em;
      height: 12em;
      overflow: hidden;
    }
    
    .bottom {
      position: absolute;
      height: 12em;
      width: 100%;
      top: 12em;
      transition: 0.5s ease-in-out;
    }
    
    .top .headline {
      position: absolute;
      top: 2.5em;
      width: 100%;
      background: rgba(255, 255, 255, 0.8);
      box-shadow: 0px 1px 1px 2px rgba(0, 0, 0, 0.1);
      transition: 0.5s ease-in-out;
    }
    
    .top-up .headline {
      top: -2.5em;
    }
    
    .bottom-up.bottom {
      top: 0em;
      background-color: rgba(0, 0, 0, 0.65);
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="winner-container">
      <div class="top">
        <h4 class="headline">SME Example 1</h4>
      </div>
      <div class="bottom">
        <div class="winner-words">
          <h6>SME Examle 1 is a technology company.</h6>
          <h6><a>Learn more...</a></h6>
        </div>
      </div>
    </div>
    
    <div class="winner-container">
      <div class="top">
        <h4 class="headline">SME Example 2</h4>
      </div>
      <div class="bottom">
        <div class="winner-words">
          <h6>SME Examle 2 is an e-commerce company.</h6>
          <h6><a>Learn more...</a></h6>
        </div>
      </div>
    </div>