Hide element in VueJs while scrolling - javascript

I am making vue project.
I want to hide some component while mouse scrolling, but when scroll ends, want to show component again.
I know using scroll event, but again doesn't shows component.
<div class="table" #scroll="handleScroll()">
.....
</div>
....
<div class="table" id="sumTable">
....
</div>
.....
methods: {
handleScroll() {
$('#sumTable').hide();
},
}
Is this possible in vue?

I resolved this issue.
handleScroll() {
if(this.timer !== null) {
clearTimeout(this.timer);
$("#sumTable").hide();
}
this.timer = setTimeout(function() {
$("#sumTable").show();
}, 150);
},
timer variable is applied.

Related

Remove hover effects when scrolling

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.

Toggle visibility using v-show or v-if in Vue while using a setTimeout function

I am using Vue2. I have a form. When submit is clicked I want to show a "Loading" Div for X amount of time. After this X amount of time, I want to Load the Form again. In a nutshell, after a click, toggle visibility, after certain code is executed and waited certain time, toggle it again.
I have two Divs:
<div v-if="this.isHidden">
LOADING....
</div>
<div v-if="!this.isHidden"> <!--or v-else -->
<form #submit.prevent="">
<!--Fields-->
<button #click="updateProduct(product)" type="button">Submit</button>
</form>
</div>
On load, only "CONTENT" shows (isHidden = false).
When the method updateProduct() is executed I want the div "LOADING" to appear for X amount of seconds (isHidden=true) while "CONTENT" div must hide. Then after executing some code inside a setTimeout function, I want them to toggle once again (isHidden = false).
data: function() {
return {
//isHidden is initialized as false
isHidden: false,
};
},
My method looks like this:
updateProduct(product){
this.isHidden = true;
alert(this.isHidden + 'This correctly shows true. CONTENT correctly toggles and HIDES. LOADING also works correctly and APPEARS.');
//I want to delay the following code with setTimeout so that I am able to control for how long I want to show LOADING
setTimeout(function(){
//do a bunch of tasks that work correctly...
axios.post('/api/product/' + product.id, data)
.then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});
//After all my code is executed, I am still inside the setTimeout function inside the updateProduct method so now i do this:
this.isHidden = false;
alert(this.isHidden + ' This correctly shows false BUT DIVS DO NOT UPDATE ANYMORE, I am stuck with the LOADING div');
//although my code works fine and the alert shows the correct value for isHidden, my view is stuck in LOADING
}, 2000);
}
I have attempted to move this.isHidden = false; outside of the setTimeout function but it still doesn't "toggle" the visibility.
I have also tried to use v-if instead of v-show, same behaviour.
Your main issue is this inside the setTimeout callback
Because you use function() {} it's NOT what you want this to be
Either use arrow notation setTimeout(() => {}, 2000)
updateProduct(product) {
this.isHidden = true;
setTimeout(() => {
//do a bunch of tasks that work correctly...
axios.post('/api/product/' + product.id, data)
.then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
});
this.isHidden = false;
}, 2000);
}
Or, if arrow notation scares you setTimeout(function() {}.bind(this), 2000)
updateProduct(product) {
this.isHidden = true;
setTimeout(function() {
//do a bunch of tasks that work correctly...
axios.post('/api/product/' + product.id, data)
.then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
});
this.isHidden = false;
}.bind(this), 2000);
}
As a side note, do not use alert for debugging - it blocks execution of javascript and can lead to unreliable debugging results
Just Use V-else
<div v-if="!this.isHidden"> <!--or v-else -->
<form #submit.prevent="">
<!--Fields-->
<button #click="updateProduct(product)" type="button">Submit</button>
</form>
</div>
<div v-else>
<div v-if="this.isHidden">
LOADING....
</div>
</div>

Prevent Scrolling in VueJS

I am trying to prevent scrolling only when the lightbox component is open, but cannot seem to do so. I hope to not use any outside libraries or plug-ins to do this.
My App.vue contains the "LightBox" component, so I am assuming the prevent scrolling function should live in the App.vue as well.
App.vue snippet:
<template>
<div class="SocialAlbumWidget">
<div v-if="isModalVisible && media[activeIndex]">
<LightBox
...
/>
I currently have a "showModal ()" function in the "methods" section, so was thinking of passing that through another function.
Methods:
mothods: {
...
showModal () {
this.isModalVisible = true
},
closeModal () {
this.isModalVisible = false
}
I expect the body to have scroll when the"Lightbox" component is closed and disabled when the "Lightbox" component is open. Thanks! Let me know what other code would be useful.
Prevent scrolling events on LightBox modal itself -
<LightBox
#wheel.prevent
#touchmove.prevent
#scroll.prevent
/>
style overflow: hidden might create some concerns.
such as;
Visibility of scrollbar
UI bounce w.e.f overflow toggle
You could use a watcher to react to changes in isModalVisible and disable the scrolling function by using style="overflow: hidden".
Something along these lines:
// HTML
<btn #click="dialog = !dialog" >Click Me </btn>
// JS
new Vue({
el: '#app',
data () {
return {
dialog: false,
}
},
watch: {
isModalVisible: function() {
if(this.isModalVisible){
document.documentElement.style.overflow = 'hidden'
return
}
document.documentElement.style.overflow = 'auto'
}
}
})

hide div when mouse hasn't moused over x time, vue.js

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.

angular ui-router stuck in between states

I am using UI-Router in a project. I am using the state resolve functionality provided by the router. When I want to display a loader in between two states and I change states very often the spinner pops up but don't disappear anymore.
The same effect can be found here.
http://rp.js.org/angular-ui-view-spinner/example/index.html
If one clicks fast between the two states the loader won't hide.
I am waiting for the stateChangeStart broadcast and display the loader and on statChangeSuccess, stateChangeError and viewContentLoaded I want't to hide the loader. The stateChangeStart gets fired but stateChangeSuccess doesn't. Any idea why this behaviour appears?
I am using angular-ui-router in version 0.2.18
Here the Code for show and hide:
$rootScope.$on('$stateChangeStart', showLoading);
$rootScope.$on('$stateChangeSuccess', hideLoading);
$rootScope.$on('$stateChangeError', hideLoading);
$rootScope.$on('$viewContentLoaded', hideLoading);
function showLoading() {
$timeout(function () {
angular.element('.loading-indicator').show();
}, 50);
}
function hideLoading() {
$timeout(function () {
angular.element('.loading-indicator').hide();
}, 50);
}
You need to cancel previous timer. See documentation here: https://docs.angularjs.org/api/ng/service/$timeout.
var yourTimer;
function showLoading() {
if (yourTimer) {$timeout.cancel(yourTimer);}
yourTimer = $timeout(function () {
angular.element('.loading-indicator').show();
}, 50);
}
function hideLoading() {
if (yourTimer) {$timeout.cancel(yourTimer);}
yourTimer = $timeout(function () {
angular.element('.loading-indicator').hide();
}, 50);
}
I can't understand for which reason you use a timer for loading spinner, i recommend use only css if you use for the animation.
Here a little of my code:
HTML
<div ui-view class="fade container-fluid"></div>
<div class="spinner modal-viewer" hidden>
<div class="transparente"></div>
<div class="contenedor">
<div class="center-middle">
<div class="sk-circle">
<div class="sk-circle1 sk-child"></div>
<div class="sk-circle2 sk-child"></div>
...
<div class="sk-circle11 sk-child"></div>
<div class="sk-circle12 sk-child"></div>
</div>
</div>
</div>
</div>
You need manage them out of the uiView, because when you let out of a state, you will lose control of the state controller, then you can't disappear the spinner.
For that, put the spinner out of the uiView element, as above example.
JS
document.querySelector('.spinner')['style'].display = 'none';
My apologies for my poor previous answer.

Categories