Home > database >  Change hover to click function after resize screen
Change hover to click function after resize screen

Time:07-11

I hope $(".menu-item-has-children").hover(...); works when screen width >= 768, and $(".menu-item-has-children").click(...) works when screen width < 768.

I try to use resize() to check if the screen width larger than 768px.

The problem is when I open the page with the screen width over 768px, then resize it under 768px, the hover() function still work.

How do I make the hover function works only when screen width > 768px ?

let show = function () {
    try {
      clearTimeout(leavetimer);
    } catch {}
    entertimer = setTimeout(() => {
      $(this).find("ul").addClass("active");
    }, 400);
  },
  hide = function () {
    clearTimeout(entertimer);
    leavetimer = setTimeout(() => {
      $(this).find("ul").removeClass("active");
    }, 400);
  },
  large = $(window).width() >= 768;
$(window)
  .resize(function () {
    large = $(window).width() >= 768;
  })
  .resize();

$(document).ready(() => {
  if (large) {
    $(".menu-item-has-children").hover(show, hide);
  } else {
    $(".menu-item-has-children").click(function () {
      if (!$(this).find("ul").hasClass("active")) {
        $(this).find("ul").addClass("active");
      } else {
        $(this).find("ul").removeClass("active");
      }
    });
  }
});
.menu-item-has-children ul {
  display: none;
}
.menu-item-has-children ul.active {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
    <li ><a>class 1</a>
        <ul >
            <li><a href="#">child 1</a></li>
            <li><a href="#">child 2</a></li>
            <li><a href="#">child 3</a></li>
            <li><a href="#">child 4</a></li>
            <li><a href="#">child 5</a></li>
        </ul>
    </li>
    <li><a href="#">class 2</a></li>
</ul>

CodePudding user response:

The browser executes your document.ready block exactly once, on the initial page load. Resizing happens after the initial code has executed - your resize event is there, but you haven't told the browser what to do with it yet. You need to apply the logic to the event listener for the resize event, binding and unbinding click/mouseenter/mouseleave event listeners.

Note: Since the event logic is used by two seperate listeners, you can put it in a seperate function. I left that up to you. DNRY! :)

let show = function () {
    try {
      clearTimeout(leavetimer);
    } catch {}
    entertimer = setTimeout(() => {
      $(this).find("ul").addClass("active");
    }, 400);
  },
  hide = function () {
    clearTimeout(entertimer);
    leavetimer = setTimeout(() => {
      $(this).find("ul").removeClass("active");
    }, 400);
  },
  large = $(window).width() >= 768;
$(window).resize(function () {
    large = $(window).width() >= 768;
    if (large) {
      // remove previously applied listener
      $(".menu-item-has-children").off('click');
      $(".menu-item-has-children").hover(show, hide);
    } else {
      // equals to hover(). I suggest using .on('...') instead of .hover()
      $(".menu-item-has-children").off('mouseenter mouseleave');
      $(".menu-item-has-children").click(function () {
        if (!$(this).find("ul").hasClass("active")) {
          $(this).find("ul").addClass("active");
        } else {
          $(this).find("ul").removeClass("active");
        }
      });
    }
  });

$(document).ready(() => {
  if (large) {
    $(".menu-item-has-children").hover(show, hide);
  } else {
    $(".menu-item-has-children").click(function () {
      if (!$(this).find("ul").hasClass("active")) {
        $(this).find("ul").addClass("active");
      } else {
        $(this).find("ul").removeClass("active");
      }
    });
  }
});
.menu-item-has-children ul {
  display: none;
}
.menu-item-has-children ul.active {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
    <li ><a>class 1</a>
        <ul >
            <li><a href="#">child 1</a></li>
            <li><a href="#">child 2</a></li>
            <li><a href="#">child 3</a></li>
            <li><a href="#">child 4</a></li>
            <li><a href="#">child 5</a></li>
        </ul>
    </li>
    <li><a href="#">class 2</a></li>
</ul>

CodePudding user response:

here is my way to achieve this with common function

var entertimer;
var leavetimer;

let show = function () {
  try {
    clearTimeout(leavetimer);
  } catch { }
  entertimer = setTimeout(() => {
    $(this).find("ul").addClass("active");
  }, 400);
},
  hide = function () {
    if (entertimer) {
      clearTimeout(entertimer);
    }
    leavetimer = setTimeout(() => {
      $(this).find("ul").removeClass("active");
    }, 400);
  },
  large = $(window).width() >= 768;

$(window).resize(function () {
  large = $(window).width() >= 768;
  change();
}).resize();

$(document).ready(() => {
  change();
});

function change() {
  if (large) {
    $(".menu-item-has-children").hover(show, hide);
    $(".menu-item-has-children").unbind('click');
  } else {
    $(".menu-item-has-children").unbind('click');
    $(".menu-item-has-children").click(function () {
      $(".menu-item-has-children").unbind('mouseenter mouseleave');
      console.log('$(this).find("ul")', $(this).find("ul"))
      if (!$(this).find("ul").hasClass("active")) {
        $(this).find("ul").addClass("active");
      } else {
        $(this).find("ul").removeClass("active");
      }
    });

  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <style>
    .menu-item-has-children ul {
  display: none;
}
.menu-item-has-children ul.active {
  display: block;
}
  </style>
</head>

<body>
  <ul >
    <li ><a>class 1</a>
      <ul >
        <li><a href="#">child 1</a></li>
        <li><a href="#">child 2</a></li>
        <li><a href="#">child 3</a></li>
        <li><a href="#">child 4</a></li>
        <li><a href="#">child 5</a></li>
      </ul>
    </li>
    <li><a href="#">class 2</a></li>
  </ul>
</body>

</html>

  • Related