asked a similar question earlier but i've been stuck at this for a while.
i have a div that v-shows on certain events, for example when hovering over div1 and clicking on div2. i want to make so this div disappears when the mouse hasn't touched it for a certain amount of time, let's say three seconds.
my problems are that i cant use v-on:mouseleave (because the div appears without the mouse being on it) so i'd need something that after a certain delay toggles v-show on the div. is there something i'm missing? what should i be using?
thanks!
The simplest way is to use a component and add an event listener in the mounted hook that uses a timeout to set a flag attached to v-show, so:
Vue.component('my-deiv', {
template: `<template id="block"><div v-show="show">A div</div></template>`,
mounted(){
this.$el.addEventListener('mousemove', () => {
setTimeout( () => {
this.show = false;
}, 3000)
})
},
data(){
return{
show: true
}
}
});
Now whenever the mouse moves over the div it fires the timeout, here's the JSFiddle: https://jsfiddle.net/nb80sn52/
EDIT
If you want to hide the div when the mouse has not moved on it for a certain amount of time - but not when the mouse exits, then you can restart the timeout each time the mouse moves and then cancel it altogether when the mouse leaves, here's the updated version:
Vue.component('block', {
template: "#block",
mounted() {
this.timer = null;
this.$el.addEventListener('mousemove', () => {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.show = false;
}, 3000)
})
this.$el.addEventListener('mouseleave', () => {
clearTimeout(this.timer);
})
},
data() {
return {
show: true
}
}
})
And the JSFiddle for that: https://jsfiddle.net/utaaatjj/
You could setTimeout in your component render function (or any other function) which would change this.visible = true to this.visible = false after a predefined period of time.
Related
I have been working on an application. There are multiple components on the page. The content inside them is scrollable. The expected functionality is when I scroll inside the component the hover effects on different elements should be disabled. After searching in the internet I have a working solution. I have created a HoverDisabler component like this,
import React, {useEffect} from 'react';
export const HoverDisabler = ({children}) => {
let timer = 0;
useEffect(() => {
document.addEventListener('scroll', () => {
clearTimeout(timer);
if(!document.body.classList.contains('hoverDisabled')){
document.body.classList.add('hoverDisabled');
}
timer = setTimeout(() => {
document.body.classList.remove('hoverDisabled');
},500);
}, true);
}, []);
return children;
}
The css for hoverDisabled is as follows,
.hoverDisabled {
pointer-events: 'none',
}
And I am wrapping my root App component with HoverDisabler like this,
<HoverDisabler><App /></HoverDisabler>
Now in all the component, if I start scrolling the hoverDisabled class is added in the body and it gets removed when I stop scrolling. Everything is working perfectly. I am curious if this is the correct approach of having this functionality? Is there any shortcomings of this approach or some problem I am overlooking because of my lack of experience?
Since scroll event is an expensive event you can add a debounce on your scroll event like this:
function debounce(method, delay) {
clearTimeout(method._tId);
method._tId= setTimeout(function(){
method();
}, delay);
}
function scrollFunction(){
clearTimeout(timer);
if(!document.body.classList.contains('hoverDisabled')){
document.body.classList.add('hoverDisabled');
}
timer = setTimeout(() => {
document.body.classList.remove('hoverDisabled');
},500);
}
document.addEventListener('scroll', function() {
debounce(scrollFunction, 100);
});
This will surely optimize your code, as it will only fire scroll function lesser number of times. Even though there may be other approaches to the problem you're trying to solve I'm just suggesting a way to optimize your current code.
I have a page in my project that contains several categories and each category has a Flexslider with images. Each category is displayed once and clicking another, the former is hidden and clicked appears, similar scheme with Tabs.
I need that when I click on another category, it destroys the function of Flexslider initialised in the former category and is executed in this category.
Here's what I've done so far, without success:
Function that starts Flexslider:
vm.sliderCol = function () {
setTimeout(function () {
$('.sliderCol').flexslider({
animation: "slide",
controlNav: false
})
}, 1000)
}
Function that enter the category button:
vm.clicou = function(){
$('.sliderCol').flexslider("destroy")
setTimeout(function () {
vm.sliderCol()
}, 1000)
}
Until then I tried to destroy the Flexslider do not know if there is some method to stop performing the function and start it, can anyone help?
With ng-click on each category playing the role, I managed to destroy the slider and start it again with the following function:
vm.clicou = function(){
$('.sliderCol').flexslider("destroy");
$('.sliderCol').removeData("flexslider");
setTimeout(function () {
vm.sliderCol();
}, 100);
}
I have implemented on a website a picture gallery that does not allow (it seems) the auto sliding. So at the moment I have to push on a button to see the next picture. My purpose is to catch the function that allows to move to the next picture and to set a timeout to go to the next picture automatically.
How can I get the JS function name using Google Chrome developer tools?
Thank you
UPDATE
This is the Gallery script: http://tympanus.net/Development/ScatteredPolaroidsGallery/
I would like to implement auto sliding on it
source for code proposal from: https://github.com/codrops/ScatteredPolaroidsGallery/issues/4
(function() {
function autoSliding(timeout) {
var self = this;
clearTimeout(self.timeOut);
self.timeOut = setTimeout(function() {
self._navigate('next');
}, timeout);
}
new Photostack( document.getElementById( 'photostack-1' ), {
afterShowPhoto: function(context) {
autoSliding.call(context, 3000)
},
afterNavigate: function(context) {
autoSliding.call(context, 3000)
}
});
new Photostack( document.getElementById( 'photostack-2' ), {
afterShowPhoto: function(context) {
autoSliding.call(context, 3000)
},
afterNavigate: function(context) {
autoSliding.call(context, 3000)
}
});
}())
This should do the work
$('.navigate-next').click();
Or for auto scroll
setInterval(function(){$('.navigate-next').click();},1000);
Change 1000 for whatever you wish
If you are allowed to use jquery in your code, then, you can use $._data() method.
syntax is $._data($("selector of the element")[0], "events")
This will return an Object of all events bounded to that element. Then get the click event and call the handler attribute of the click event.
I can't run clearInterval for my functions. I use them to scroll the window by firing setInterval with function that fires scrollLeft. The code:
function scrollSpan() {
$('nav#scrolling').children().css('width',config.windowWidth/10+'px');
var inter;
$('nav#scrolling').children('span').hover(function() {
var value;
if($(this).is('.scrollLeft')) {
value = '-=50'
} else {
value = '+=50'
}
inter = setInterval(function() {
$('body, html').animate({
scrollLeft: value
}, 50);
},0)
})
$('nav#scrolling').children('span').mouseleave(function() {
clearInterval(inter)
})
}
Problem is, when mouseleave is triggered, interval doesn't stop.
Fiddle: http://jsfiddle.net/FpX4M/
You are using hover where you should be using mouseenter. When only one handler is passed to hover that handler is called both on enter and leave. So your hover is called twice (once entering and once leaving) but your mouseleave is only called once. This is why even though one interval is cleared, the other remains.
See the documentation, in particular the signature added in v1.4 which takes only a single handler (scrolldown).
EDIT: Jsfiddles with proof:
http://jsfiddle.net/FpX4M/1/
Open your console and see that the handlers trigger twice and that interval continues.
http://jsfiddle.net/FpX4M/2/
In the console you will now see only one firing of the handler and then the intervals stop on leave.
Your whole scope is a little wonky. Try something like this:
var inter;
function scrollSpan() {
$('nav#scrolling').children().css('width',config.windowWidth/10+'px');
}
$('nav#scrolling').children('span').hover(function() {
var value;
if($(this).is('.scrollLeft')) {
value = '-=50'
} else {
value = '+=50'
}
inter = setInterval(function() {
$('body, html').animate({
scrollLeft: value
}, 50);
},0)
});
$('nav#scrolling').children('span').mouseleave(function() {
clearInterval(inter)
});
You need to make sure the inter variable is accessible outside of the function. Also, generally, state functions shouldn't be assigned within functions unless you're changing them rapidly - and it doesn't look like you're detaching them anywhere. The only things that need to be in the function are things that will be repeated. Maybe add a clearInterval(inter); right before your inter = setInterval... to make sure no old intervals persist.
I have a link:
Here's my link
This is not a normal clickable link, it's coded in jQuery like this:
$("#link").hover(function(e) {
e.preventDefault();
$("#tv").stop().animate({marginLeft: "50px"});
$("#tv img)").animate({opacity: 1});
})
So after hovering unclickable link there's change of #tv's margin and opacity.
Is there any way of making this work only after the user hovers the link area with pointer for more than two seconds?
Because now everything happens in real time.
I know there's delay(), but it doesn't work because it just delays the animation and in this case I don't want any action if the pointer is over for less than two seconds.
Possible without a loop?
What you're after is called hoverIntent.
var animateTimeout;
$("#link").hover(function() {
if (animateTimeout != null) {
clearTimeout(animateTimeout);
}
animateTimeout = setTimeout(animate, 2000);
}, function() {
clearTimeout(animateTimeout);
});
function animate() {
//do animation
}
You just need a setTimeout() to delay the code, along with a clearTimeout() to clear it if the user leaves the link within 2 seconds.
Example: http://jsfiddle.net/mNWEq/2/
$("#link").hover(function(e) {
e.preventDefault();
$.data(this).timeout = setTimeout(function() {
$("#tv").stop().animate({marginLeft: "50px"});
$("#tv img)").animate({opacity: 1});
}, 2000);
}, function(e) {
clearTimeout($.data(this,'timeout'));
});