Search code examples
jqueryjquery-selectorsjquery-animatemouseeventmouseenter

How to rebind event handler after .off() and upon animation completion using CSS selectors and jQuery


I am new to JavaScript and attempting to create animated buttons with a mask that changes opacity, revealing what is behind the mask. I am using .mouseenter() and .mouseleave() as my event handlers/listeners. I would like to wait for the animation to complete before the animation can be called again. I am trying to use multiple buttons and pass the selector parameter to change the mask selection. I am turning .off() the event handler for the length of the animation then attempting to turn it back on/re-bind it.

My questions are:

How do I make sure the selector is working properly (if I hover over the second button it triggers animation in the first)?

How do I rebind the event handler to the .button element after unbinding it with .off();?

Any help would be greatly appreciated! I am trying to learn how to make my code more modular. Any suggestions/tips are definitely welcomed!

CODEPEN: http://codepen.io/dclappert/full/eDJkp

JavaScript:

$(document).ready(function(){

   var maskOne = 1;
   var maskTwo = 2;

   setEvent(maskOne, maskTwo);

   function setEvent(maskOne, maskTwo){

       $('#navCon div:nth-child(1)').on().mouseenter(function(){fadeOutMask(maskOne);}).on().mouseleave(function(){fadeInMask(maskOne);});

       $('#navCon div:nth-child(2)').on().mouseenter(function(){fadeOutMask(maskTwo);}).on().mouseleave(function(){fadeInMask(maskTwo);});  

   };

   function fadeOutMask(selector){
       $('#navCon div:nth-child('+selector+') div:nth-child('+selector+')')
       .css({opacity: 0.75}).delay(500).animate({opacity: 0}, 2000);

       turnOffEventHandler(selector);

       setTimeout(function(){turnOnEventHandler();},2000);

   };

   function fadeInMask(selector){

      $('#navCon div:nth-child('+selector+') div:nth-child('+selector+')')
      .css({opacity: 0.0}).delay(500).animate({opacity: 0.75}, 2000);    

   };

   function turnOffEventHandler(selector){

      $('#navCon div:nth-child('+selector+')').off();

   };

   function turnOnEventHandler(){

      setEvent();

   };

});

HTML:

<head>
<link href='http://fonts.googleapis.com/css?family=Oswald:700' rel='stylesheet' type='text/css'>
</head>
<body>
  <div id = "navCon">
    <div class = "button">
        <div class = "mask"></div>
        <text>mouseover</text>
    </div>
    <div class = "button">
        <div class = "mask"></div>
        <text>mouseover</text>
    </div>
  </div>
</body>

CSS:

text{font-family: 'Oswald', sans-serif;display:table-cell; vertical-align:middle; text-align:center; font-size: 20px;color: #f1f1f1;}

.button{osition: relative; display:table; background:#2d2d2d; height:100px; width:300px;margin-top:10px;}

.mask{position:absolute; height:100px; width:300px; background: #d4d4d4; z-index: 1; opacity:0.75;}

Solution

  • Click the button below to run the code. See comments in my code.

    $(document).ready(function() {
    
      // pass a jquery object to setevent, in this case an array of elements with the class .mask
      setEvent($('.mask'));
    
      function setEvent($masks) {
        // by convention $ in front of the variable name means the variable contains a jQuery object.
    
        $masks.each(function() {
          $(this).on().mouseenter(function() {
            fadeOutMask($(this));
          });
    
          // the following is unnecessary since you'll never trigger the fadeInMask with a mouseleave, only with turnOnEventHandler below
    
          /* .on().mouseleave(function() {
            fadeInMask($(this));
          });  */
        });
    
    
    
      };
    
      function fadeOutMask($mask) {
        $mask
          .css({
            opacity: 0.75
          }).delay(500).animate({
            opacity: 0
          }, 2000);
    
        turnOffEventHandler($mask);
    
        setTimeout(function() {
          turnOnEventHandler($mask);
        }, 2000);
    
      };
    
      function fadeInMask($mask) {
        $mask
          .css({
            opacity: 0.0
          }).delay(500).animate({
            opacity: 0.75
          }, 2000);
    
      };
    
      function turnOffEventHandler($mask) {
    
        $mask.off();
    
      };
    
      function turnOnEventHandler($mask) {
        // when you call setEvent this time, you're passing the $mask object which points only to the one that was moused-over.
        setEvent($mask);
        // manually call in the fadeIn
        fadeInMask($mask);
    
      };
    
    });
    text {
      font-family: 'Oswald', sans-serif;
      display: table-cell;
      vertical-align: middle;
      text-align: center;
      font-size: 20px;
      color: #f1f1f1;
    }
    .button {
      osition: relative;
      display: table;
      background: #2d2d2d;
      height: 100px;
      width: 300px;
      margin-top: 10px;
    }
    .mask {
      position: absolute;
      height: 100px;
      width: 300px;
      background: #d4d4d4;
      z-index: 1;
      opacity: 0.75;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <head>
      <link href='http://fonts.googleapis.com/css?family=Oswald:700' rel='stylesheet' type='text/css'>
    </head>
    
    <body>
      <div id="navCon">
        <div class="button">
          <div class="mask"></div>
          <text>mouseover</text>
        </div>
        <div class="button">
          <div class="mask"></div>
          <text>mouseover</text>
        </div>
      </div>
    </body>