Disable hover on scroll to prevent browser repaint - javascript

I have a hover effect on a list of div, the css is:
.product:hover {
background-color: #f6f6f7;
border-left-color: #f6f6f7 !important;
border-right-color: #f6f6f7 !important;
outline: 10px solid #f6f6f7;
z-index: 1;
}
I want this hover effect to not be triggered when the user is scrolling the page, to not force the browser to repaint/reflow.
So I tried:
doc = $(document)
doc.scroll(->
$('.product').unbind('mouseenter').unbind('mouseleave')
)
But it doesn't seem to work, when I scroll the hover effect is still triggered. Any idea why? Or how I have achieve that?

Add this in your css style page
.disable-hover {
pointer-events: none;
}
You have to do is add the .disable-hover class to the body when you begin to scroll. This then allows the users cursor to pass through the body and thus disable any hover effects.
var body = document.body,timer;
window.addEventListener('scroll', function() {
clearTimeout(timer);
if(!body.classList.contains('disable-hover')) {
body.classList.add('disable-hover')
}
timer = setTimeout(function(){
body.classList.remove('disable-hover')
},500);
}, false);
Add this script and execute it will works:-

Try setting
document.body.style.pointerEvents = 'none';
when scroll event is triggered. Detailed docs here.

CSS hover has nothing to do with JavaScript events.
If you want to do what you are after, you will need to do it by adding/removing a class onscroll
var scrollTimer;
$(window).on("scroll", function() {
if(scrollTimer) window.clearTimeout(scrollTimer);
$("body").removeClass("effect");
scrollTimer = window.setTimeout( function()
$("body").removeClass("effect");
}, 100);
});
and the CSS
.effect .product:hover {
background-color: #f6f6f7;
border-left-color: #f6f6f7 !important;
border-right-color: #f6f6f7 !important;
outline: 10px solid #f6f6f7;
z-index: 1;
}
and PS: using important is BAD practice

Related

How to make an element reset its position after mouseout event in javascript

trying to make a button like this: https://gyazo.com/9afbd559c15bb707a2d1b24ac790cf7a. The problem with the code right now is that it works as it is supposed to on the first time; but after that, instead of going from left to right as intented, it goes from right to left to right.
HTML
<div class="btn-slide block relative mx-auto" style="overflow: hidden; width: 12rem;">
<span class="z-10">View Pricing</span>
<span class="slide-bg block absolute transition" style="background-color: rgba(0,0,0,.1); z-index: -1; top: 0; left:-10rem; width: 10rem; height: 3rem;"></span>
</div>
Javascript
const btns = document.querySelectorAll(".btn-slide");
const slide = document.getElementsByClassName('slide-bg');
btns.forEach(function(btn) {
btn.addEventListener('mouseout', function () {
slide[0].style.transform = 'translateX(230%)';
slide[0].style.transform = 'none';
})
btn.addEventListener('mouseover', function() {
slide[0].style.transform = 'translateX(80%)';
}, true)
})
Unless you have to compute a value in JavaScript (like the height of an element).
Use CSS classes as modifiers (is-hidden, is-folded, is-collapsed, ...).
Using JavaScript, only add/remove/toggle the class
yourElement.addEventListener(
"mouseenter",
function (event)
{
yourElement.classList.remove("is-collapsed");
}
);
yourElement.addEventListener(
"mouseleave",
function (event)
{
yourElement.classList.add("is-collapsed");
}
);
is-collapsed is only an exemple, name it according to your class naming standard.
You're probably going to need a bit more code than what you're showing, as you have two mutually exclusive CSS things you want to do: transition that background across the "button" on mouseenter/mouseout, which is animated, and then reset the background to its start position, which should absolutely not be animated. So you need to not just toggle the background, you also need to toggle whether or not to animation those changes.
function setupAnimation(container) {
const fg = container.querySelector('.label');
const bg = container.querySelector('.slide-bg');
const stop = evt => evt.stopPropagation();
// step one: make label text inert. This is critical.
fg.addEventListener('mouseenter', stop);
fg.addEventListener('mouseout', stop);
// mouse enter: start the slide in animation
container.addEventListener('mouseenter', evt => {
bg.classList.add('animate');
bg.classList.add('slide-in');
});
// mouse out: start the slide-out animation
container.addEventListener('mouseout', evt => {
bg.classList.remove('slide-in');
bg.classList.add('slide-out');
});
// when the slide-out transition is done,
// reset the CSS with animations _turned off_
bg.addEventListener('transitionend', evt => {
if (bg.classList.contains('slide-out')) {
bg.classList.remove('animate');
bg.classList.remove('slide-out');
}
});
}
setupAnimation(document.querySelector('.slide'));
.slide {
position: relative;
overflow: hidden;
width: 12rem;
height: 1.25rem;
cursor: pointer;
border: 1px solid black;
text-align: center;
}
.slide span {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.slide-bg {
background-color: rgba(0,0,0,.1);
transform: translate(-100%, 0);
transition: none;
z-index: 0;
}
.slide-bg.animate {
transition: transform 0.5s ease-in-out;
}
.slide-bg.slide-in {
transform: translate(0%, 0);
}
.slide-bg.slide-out {
transform: translate(100%, 0);
}
<div class="slide">
<span class="label">View Pricing</span>
<span class="slide-bg"></span>
</div>
And thanks to browsers being finicky with rapid succession mouseenter/mouseout events, depending on how fast you move the cursor this may not even be enough: you might very well still need a "step" tracker so that your JS knows which part of your total animation is currently active, and not trigger the mouseout code if, by the time the slide-in transition ends, the cursor is in fact (still) over the top container (or, again).
I advice you use the .on event listener
$('').on("mouseentre","elem",function(){$('').toggleclass('.classname')})
$('').on("mouseleave","elem",function(){$('').toggleclass('.classname')})
Then you can toggle css classes to your element in the function
toggle class adds the css of a class to your jquery selection, you can do it multiple times and have keyframes for animation in the css class
Keyframes are great way to implement animation and are supported on every browers

Expanding / Retracting Menu Bar

I'm using jQuery to expand/retract a menu bar from the left-side of the screen.
Here's what I have so far:
$(document).ready(function(){
$('.menu-button').on("click",
function(){
$('.menu').css("left","0");
$('.menu-button').addClass("clicked");
}
);
$('.menu-button clicked').on("click",
function(){
$('.menu').css("left","-168");
$('.menu-button').removeClass("clicked");
}
);
});
The menu bar is expanding, but not retracting back. I think this code makes sense- but apparently not. Thoughts?
You need to change
$('.menu-button clicked')
to
$('.menu-button.clicked')
But then the problem is when you click again. Both clicks will happen. So you add and remove the class. To fix that you could do something like
$(document).ready(function(){
$('.menu-button').on("click", function(){
if($('.menu-button').hasClass('clicked')) {
$(this).removeClass("clicked");
$('.menu').css("left","-168");
} else {
$(this).addClass("clicked");
$('.menu').css("left","0");
}
});
});
But the most simple would be to use toggleClass like so:
$('.menu-button').on("click", function(){
$('.menu').toggleClass( "clicked" );
$(this).toggleClass( "clicked" );
});
and if possible you should always change CSS via CSS and not use javascript inline-styles.. so now with .toggleClass you toggle the class and change your css. Just adding colored borders here to give you an idea but you change your styles how ever you need them.
.menu {
/* add your styles here */
left: -168px;
border: solid 2px red;
}
.menu.clicked {
/* add your styles here */
left: 0;
border: solid 2px green;
}
.menu-button {
/* add your styles here */
border: solid 2px orange;
}
.menu-button.clicked {
/* add your styles here */
border: solid 2px lime;
}

How to change hover state when element is moved?

In short: clicking on an image moves it with a css transition. I want the hover effect of the image to go away when it moves away from under the mouse.
I have an image without a border. When you click on it the page zooms in using zoomooz. When you hover over the image a border shows and stays there while the page is zoomed in.
If you click anywhere you zoom back out. However if you click on the image to zoom out and don't move the mouse, the image stays in the hover state so the image will keep the border even when the mouse is not currently over the image.
I understand that this is logical because there is no event that triggers the change, but what would be a way to solve this? I tried adding a style change just to the click event but then there is no animation because it's not a transition in css ($("img").css("border-color","rgba(0,0,0,0)");))
Here is a JSFiddle
This is my HTML:
<body>
<img src="https://i.imgur.com/e1TsDx0.png" id="abc"/>
</body>
CSS
img {
width: 100px;
border: 1px solid black;
border-color: rgba(0, 0, 0, 0);
margin-left: 10px;
transition: border-color 600ms;
}
img:hover {
border: 1px solid black;
transition:border-color 0s;
}
.zoomedimg {
border-color: rgba(0, 0, 0, 1);
}
Javascript:
$(document).ready(function() {
$("img").click(function(evt) {
event.stopPropagation()
if ($("img").hasClass('zoomedimg')) {
$("img").removeClass('zoomedimg');
$("body").zoomTo();
} else {
$("img").addClass('zoomedimg');
$("img").zoomTo();
}
});
$(window).click(function(evt) {
$("body").zoomTo({});
$("img").removeClass('zoomedimg');
});
});
Very closely related to these questions:
How to remove hover state when the element moves This had a very sober
answer, which in that example I could not get to work. I did try setting the border color when I clicked the image like in that solution. But then the changing border doesn't count as a transition so it will not animate.
Hover state is maintained during a transition even if the element has gone
This had a very extensive answer, but I didn't really understand how to apply it to my situation.
Edit: Junaid Ahmed offered a solution to make the hover transition using jQuery and a class. When you click to zoomout you remove the "hover" class and thus also the border. This poses a new problem:
if you hover over the image while clicking and you keep hovering until the zoomout ends the border disappears and doesn't return until you mouseout and mouseover again.
How would I solve this?
#Jason is right. You could drop the hover effect using CSS and accomplish the hover effect with JS/JQuery. Check my forked JSFiddle
The CSS:
img {
width: 100px;
border: 1px solid black;
border-color: rgba(0, 0, 0, 0);
margin-left: 10px;
transition: border-color 600ms;
}
img.hover {
border: 1px solid black;
transition:border-color 0s;
}
.zoomedimg {
border-color: rgba(0, 0, 0, 1);
}
The JS:
$(document).ready(function() {
$("img").on('mouseover', function(){
$("img").addClass('hover');
});
$("img").on('mouseout', function(){
$("img").removeClass('hover');
});
$("img").click(function(evt) {
event.stopPropagation()
if ($("img").hasClass('zoomedimg')) {
$("img").removeClass('zoomedimg').removeClass('hover');
$("body").zoomTo();
} else {
$("img").addClass('zoomedimg');
$("img").zoomTo();
}
});
$(window).click(function(evt) {
$("body").zoomTo({});
$("img").removeClass('zoomedimg').removeClass('hover');
});
});
use a variable to switch over the states:
<script>
var state;
function switch() {
if (state == 1){
/* your code to remove the border */
state = 0;
}else{
state = 1;
}
}
</script>
<img onclick="switch()">
customize the code as you need.
I changed like this, Check this.
$(document).ready(function() {
$("img").hover(function(evt) {
$("img").addClass('zoom-border');
event.stopPropagation()
if ($("img").hasClass('zoomedimg')) {
$("img").removeClass('zoomedimg');
} else {
$("img").addClass('zoomedimg');
$("img").zoomTo();
}
});
$(window).click(function(evt) {
$("body").zoomTo({});
$("img").removeClass('zoomedimg');
$("img").removeClass('zoom-border');
});
});
img {
width: 100px;
border-color: rgba(0, 0, 0, 0);
margin-left: 10px;
transition: border-color 600ms;
}
.zoom-border{
border: 1px solid black;
transition:border-color 0s;
}
.zoomedimg {
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://dropfruitduo.github.io/jquery.zoomooz.min.js"></script>
<body>
<img src="https://i.imgur.com/e1TsDx0.png" id="abc"/>
</body>

Change DIV display value using Javascript/Jquery function

Update: Fixed and working. Thanks everyone for the help.
Hello I'm making a javascript/jQuery button that when its clicked, a Div appears (display: inline-block), and when its clicked again the Div goes back to display: none. Ideally I would want to animate the movement, but I really just want to get it working first.
My button...
<button> Menu Test </button>
My function (updated)...
<script>
$("button").click(function(){
$("#flexMenu").toggle("slow", function() {
});
});
</script>
The CSS for flexMenu...
#flexMenu {
/* display: inline-block;*/
position: fixed;
float: left;
background: #1f1f1f;
margin: 3.9em 0 0 0;
padding: .25em;
width: 15%;
height: 6em;
border: 2px solid #fff;
z-index: 100;
}
I'm really just to sure how to grab the display property of the ID and change it. I've done a hover function before using CSS ease-out to make divs grow in size when hovered and change class by using $(this).toggleClass(nameOfClass), but I have never tried just changing an element. The other questions like this didn't really fit just changing the display value. Thanks for any help.
you should use jquery :
$("button").click(function(){
$("#flexMenu").toggle();
});
Updated with the jQuery .on() method which allows you to bind specific events to that button (event listeners).
$("button").on('click', function () {
$('#flexMenu').toggle("slow");
});
Fiddle

After resetting transition, div stays visible; no new transition

I'm trying to make a <div> display and then fade out, on button click.
This works so long as the user waits for the fade to complete between <button> presses.
My problem is, if the <button> is clicked while the fade is ongoing, the <div> needs to immediately reappear, and then fade out.
I've managed to get it to immediately reappear, but now it doesn't fade out again.
To get an easier idea of what I'm doing, take a look at the JSFiddle I've setup.
Can anyone help me get this to fade out if clicked whilst already fading out?
I'm only targeting webkit.
<div id="saved">Saved!</div>
<button id="save">Save</button>
function save()
{
// Little "Saved!" div
var div = document.getElementById('saved');
// If still showing from previous save
if(div.style.visibility === 'visible')
{
resetTransition();
div.style.visibility = 'visible';
//div.style.opacity = 0;
console.log('reset');
}
// On transition end
div.addEventListener('webkitTransitionEnd', resetTransition);
function resetTransition()
{
// Disable transitions
div.className = 'notransition';
// Hide the div and reset the opacity
div.style.visibility = 'hidden';
div.style.opacity = 1;
// Need time to let CSS changes (^) refresh
setTimeout(function()
{
// Re-enable transitions
div.className = '';
// Remove the event listener by way of cloning
var dolly = div.cloneNode(true);
div.parentNode.replaceChild(dolly, div);
}, 1);
}
// Show the div and fade out - on timer due to "if still showing" needing
// to process first
setTimeout(function()
{
div.style.visibility = 'visible';
div.style.opacity = 0;
}, 1);
}
document.getElementById('save').addEventListener('click', save);
div#saved
{
-webkit-transition: opacity 1.25s ease-out;
-webkit-transition-delay: 0.75s;
background-color: #FFC;
/* Courtesy of http://fatcow.com/free-icons */
background-image: url('http://i.imgur.com/JMlclKE.png');
background-position: 3px 4px;
background-repeat: no-repeat;
border: 1px solid #333;
border-radius: 6px;
left: 5px;
opacity: 1;
padding: 10px 4px 10px 52px;
position: absolute;
top: 5px;
visibility: hidden;
width: 68px;
}
.notransition
{
-webkit-transition: none !important;
-webkit-transition-delay: none !important;
}
button
{
position: absolute;
top: 100px;
}
I updated your fiddle, moving the cloning to the top and clearing the timeout.
// Little "Saved!" div
clearTimeout(save.t);
var dolly = document.getElementById('saved');
// Remove the event listener by way of cloning
var div = dolly.cloneNode(true);
dolly.parentNode.replaceChild(div, dolly);
/* etc til */
save.t = setTimeout(/* */);

Categories

Resources