How to enable mousewheel in chrome? - javascript

I disable mousewheel with javascript, when i scroll the page to the special block.
I use a lot of methods, but all of them worked in firefox, not in chrome.
For chrome i find a specital method with preventDefault.
But i don't know how to enable them.
This is the code:
const options = {
rootMargin: "-400px"
};
const observer = new IntersectionObserver(function (entries, observer) {
entries.forEach(entry => {
console.log(entry.isIntersecting);
if (entry.isIntersecting === true) {
document.querySelector('body').classList.add('fixed');
document.body.addEventListener('wheel', function (e) {
e.preventDefault();
}, {passive: false});
$('html, body').animate({
scrollTop: scrollCenter
}, 1000);
setTimeout(function () {
document.querySelector('body').classList.remove('fixed');
document.body.addEventListener('wheel', function (e) {
// override prevented flag to prevent jquery from discarding event
e.isDefaultPrevented = function () {
return false;
}
});
}, 1000);
}
});
}, options);
observer.observe(produtsBlock);
Thanks for help.

Stacking up a listener to invalidate a previous listener is tricky as they are fired in FIFO sequence.
Some options:
1. Removing the listener
You could remove the blocking listener after that period of time.
With a named function:
const prevent = (e) => e.preventDefault();
document.body.addEventListener('wheel', prevent, { passive: false });
You can remove it afterwards:
setTimeout(function () {
document.querySelector('body').classList.remove('fixed');
document.body.removeEventListener('wheel', prevent);
}, 1000);
2. Using a flag
Use a state flag to handle preventDefault.
const state = { prevent: true };
const prevent = (e) => {
if (state.prevent) {
e.preventDefault();
}
};
document.body.addEventListener("wheel", prevent, { passive: false });
Then alter the flag:
setTimeout(function () {
document.querySelector("body").classList.remove("fixed");
state.prevent = false;
}, 1000);

Related

How to remove an eventListener (window.removeEventListener) in Vue 2, when certain condition is met

Code :-
<template>
// html
</template>
<script>
import _ from "lodash";
data() {
return {
renderComponent: false,
};
},
watch: {
// when this property is true, want to stop calling scroll event with this.onScroll method
renderComponent(val) {
if(val === true) {
console.log("////////I am removing you");
window.removeEventListener('scroll', this.onScroll);
}
}
},
methods: {
onScroll() {
console.log("I am called////////");
let similarTickerHeading = this.$refs.similarTicker;
if(similarTickerHeading) {
let margin = similarTickerHeading.getBoundingClientRect().top;
let innerHeigth = window.innerHeight;
console.log("Window Screen", innerHeigth);
console.log("Component located", margin);
// when this condition is true, I want to stop listening for the scroll event with this (onScroll method)
if(margin - innerHeigth < 850) {
console.log("I should start loading the actual component");
this.renderComponent = true;
this.$vs.loading.close("#loader-example > .con-vs-loading");
// removing eventListener for scrolling with the onScroll Method
window.removeEventListener('scroll', this.onScroll);
}
}
}
},
mounted() {
this.renderComponent = false;
this.$vs.loading({
container: "#loader-example",
type: "point",
scale: 0.8,
});
this.$nextTick(function() {
window.addEventListener('scroll', _.throttle(this.onScroll,250));
this.onScroll();
})
},
beforeDestroy() {
window.removeEventListener('scroll', this.onScroll);
},
</script>
In the above code, I want to stop listening for the scroll event with onScroll method when my if block in onScroll method becomes true. But, still, the onScroll method gets called whenever I scroll even though when I tried to remove the eventListener. I even created a watcher to remove the eventListener, yet the method keeps on getting called on scroll.
How can I remove the scroll eventListener with onScroll method ?
UPDATE : If I remove throttling and cut out _.throttle, the scroll event does get removed. Due to the use of _.throttle, I cannot remove the scroll event listener.
The function reference passed to window.addEventListener() must be the same reference passed to window.removeEventListener(). In your case, there are two different references because you've wrapped one of them with _.throttle().
Solution
Cache the function reference passed to addEventListener() so that it could be used later for removeEventListener():
export default {
mounted() {
👇
this._scrollHandler = _.throttle(this.onScroll, 250)
this.$nextTick(() => { 👇
window.addEventListener('scroll', this._scrollHandler);
this.onScroll();
})
},
beforeDestroy() {
👇
window.removeEventListener('scroll', this._scrollHandler);
},
}
demo

how to replicate onGestureEvent onBegin action using useAnimatedGestureHandler

I need my gesture handler to respond as soon as a user puts his thumb down on the screen, actually onStart only fires when the thumb starts moving right or left. How can I dot this? Thank you.
const onGestureEvent = useAnimatedGestureHandler({
onStart: () => {
isActive.value = true;
},
onActive: (event) => {
...
},
onEnd: () => {
isActive.value = false;
},
});

How can we detect onTabClosed(event) in Chrome Mobile Browser in Android / iOS using Javascript

I've been researching for 3 days straight about how to detect when a client closes a browser tab on Chrome mobile Android.
I couldn't find any working code :(
I've used Samsung Galaxy Note 10 Plus to debug through Type-C cable with Chrome PC (chrome://inspect/#devices)
and I used Android Studio's Emulator (Google Pixel),
both devices have same results, when a tab closes, nothing fires.
When I run same code on Chrome PC, it works.
I also used: requestbin.com to debug through GET Request
Here are all my research codes below. Any suggestion or idea would be appreciated.
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="lifecycle.es5.js"></script><!-- https://github.com/GoogleChromeLabs/page-lifecycle -->
<script>
function leftThePage(x){
var URL = 'https://enf***********.m.pipedream.net/?test=true&x='+x+'&date='+(new Date()+"").replace(/\s/g, '');
console.log("Client have left the page", x);
fetch(URL, { method: "GET" });
$.ajax(URL, {
async: true,
type: 'GET', // http method
success: function (data, status, xhr) {
console.log("SENT1!", x);
},
error: function (jqXhr, textStatus, errorMessage) {
console.log("ERROR1!", x);
}
});
$.ajax(URL, {
async: false,
type: 'GET', // http method
success: function (data, status, xhr) {
console.log("SENT2!", x);
},
error: function (jqXhr, textStatus, errorMessage) {
console.log("ERROR2!", x);
}
});
document.getElementById("output").innerHTML += "Bam! " + x + "<br/>";
alert("Bam! " + x);
}
window.addEventListener("beforeunload", function(event) {
leftThePage(1);
return null;
});
window.addEventListener("beforeunload", (event) => {
leftThePage(2);
return null;
});
window.onbeforeunload = function(event) {
leftThePage(3);
return null;
};
window.onbeforeunload = (event) => {
leftThePage(4);
return null;
};
window.addEventListener("onunload", (event) => {
leftThePage(5);
return null;
});
window.addEventListener("onunload", function(event) {
leftThePage(6);
return null;
});
window.onunload = function(event) {
leftThePage(7);
return null;
};
window.onunload = (event) => {
leftThePage(8);
return null;
};
$(window).on('beforeunload', function(){
leftThePage(9);
//return null;
});
$(window).on('beforeunload', () => {
leftThePage(10);
//return null;
});
$(window).on('unload', function(){
leftThePage(11);
return null;
});
$(window).on('unload', () => {
leftThePage(12);
return null;
});
// https://developers.google.com/web/updates/2018/07/page-lifecycle-api#observing-page-lifecycle-states-in-code
const getState = () => {
if (document.visibilityState === 'hidden') {
return 'hidden';
}
if (document.hasFocus()) {
return 'active';
}
return 'passive';
};
// Stores the initial state using the `getState()` function (defined above).
let state = getState();
// Accepts a next state and, if there's been a state change, logs the
// change to the console. It also updates the `state` value defined above.
const logStateChange = (nextState) => {
const prevState = state;
if (nextState !== prevState) {
//console.log(`State change: ${prevState} >>> ${nextState}`);
state = nextState;
if(state == "terminated"){
leftThePage(13);
}
}
};
// These lifecycle events can all use the same listener to observe state
// changes (they call the `getState()` function to determine the next state).
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
window.addEventListener(type, () => logStateChange(getState()), {capture: true});
});
// The next two listeners, on the other hand, can determine the next
// state from the event itself.
window.addEventListener('freeze', () => {
// In the freeze event, the next state is always frozen.
logStateChange('frozen');
}, {capture: true});
window.addEventListener('pagehide', (event) => {
if (event.persisted) {
// If the event's persisted property is `true` the page is about
// to enter the Back-Forward Cache, which is also in the frozen state.
logStateChange('frozen');
} else {
// If the event's persisted property is not `true` the page is
// about to be unloaded.
logStateChange('terminated');
}
}, {capture: true});
//<!-- https://github.com/GoogleChromeLabs/page-lifecycle -->
lifecycle.addEventListener('statechange', function(event) {
//console.log(event.oldState, event.newState);
if(event.newState == "terminated"){
leftThePage(14);
}
});
</script>
<meta charset="UTF-8">
<title>Test onCloseTab()</title>
</head>
<body>
<div id="output"></div>
</body>
</html>

Drag 'n Drop Events firing multiple times

I am working on a webapp with drag 'n drop functionality.
Up to now I used basic HTML5 Dragging but now I switched to using the library interact.js.
I don't know if my problem is specific to this library or of more general kind:
Events when dragging and dropping usually fire multiple times (if I have watched it correctly, it also seems to always be exactly 4 times, but no guarantee on that).
I am also using Vue.js and this is my code:
<template>
<v-card
elevation="0"
:id="id"
class="board device-dropzone"
>
<slot class="row"/>
<div
Drop Card here
</div>
</v-card>
</template>
In the slot, an image and div with text get added. Also this is the script:
<script>
import interact from 'interactjs';
export default {
name: 'Devices',
props: ['id', 'acceptsDrop'],
data() {
return {
extendedHover: false,
hoverEnter: false,
timer: null,
totalTime: 2,
};
},
methods: {
resetHover() {
alert('reset');
},
drop(e) {
let wantedId = e.relatedTarget.id.split('-')[0];
console.log(wantedId);
console.warn(e.target);
e.target.classList.remove('hover-drag-over');
this.extendedHover = false;
console.log('-------------dropped');
console.warn('dropped onto device');
this.$emit('dropped-component', cardId);
e.target.classList.remove('hover-drag-over'); */
},
dragenter() {
console.log('------------dragenter');
this.hoverEnter = true;
setTimeout(() => {
this.extendedHover = true;
console.log('extended hover detected');
}, 2000);
} */
this.timerID = setTimeout(this.countdown, 3000);
},
dragover(e) {
if (this.acceptsDrop) {
e.target.classList.add('hover-drag-over');
}
},
dragleave(e) {
if (this.acceptsDrop) {
clearInterval(this.timer);
this.timer = null;
this.totalTime = 2;
e.target.classList.remove('hover-drag-over');
this.extendedHover = false;
this.hoverEnter = false;
console.log('................');
console.warn(this.extendedHover);
// this.$emit('cancel-hover');
}
},
countdown() {
console.log('!!!!!!!!!!!!!!!!!!!!');
if (this.hoverEnter === true) {
this.extendedHover = true;
console.log('-------------------');
console.warn(this);
console.warn(this.extendedHover);
this.$emit('long-hover');
}
},
},
mounted() {
// enable draggables to be dropped into this
const dropzone = this;
interact('.device-dropzone').dropzone({
overlap: 0.9,
ondragenter: dropzone.dragenter(),
ondrop: function (event) {
dropzone.drop(event);
},
})
},
};
</script>
The draggable component is this one:
<template>
<v-card
class="primary draggable-card"
:id = "id"
:draggable = "false"
#dragover.stop
ref="interactElement"
>
<slot/>
</v-card>
With the script:
<script>
import interact from 'interactjs';
export default {
props: ['id', 'draggable'],
data() {
return {
isInteractAnimating: true,
position: { x: 0, y: 0 },
};
},
methods: {
/* dragStart: (e) => {
e.stopPropagation(); // so dragStart of ParentBoard does not get triggered as well
// eslint-disable-next-line
const target = e.target;
e.dataTransfer.setData('card_id', target.id);
e.dataTransfer.setData('type', 'widget');
// for some delay
setTimeout(() => {
console.log('started dragging');
}, 0);
}, */
dragEndListener: (event) => {
console.warn('+++++++++++++++++++++++++++');
// console.warn(event.currentTarget.id);
if (document.getElementById(event.currentTarget.id)) {
event.currentTarget.parentNode.removeChild(event.currentTarget);
}
},
dragMoveListener: (event) => {
/* eslint-disable */
var target = event.target;
// keep the dragged position in the data-x/data-y attributes
const xCurrent = parseFloat(target.getAttribute('data-x')) || 0;
const yCurrent = parseFloat(target.getAttribute('data-y')) || 0;
const valX = xCurrent + event.dx;
const valY = yCurrent + event.dy;
// translate the element
event.target.style.transform =
`translate(${valX}px, ${valY}px)`
// update the postion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
/* eslint-enable */
},
mounted() {
const element = this.$refs.interactElement;
console.log(element);
// interact(element).draggable({
const component = this;
interact('.draggable-card')
.draggable({
manualStart: true,
onmove: component.dragMoveListener,
onend:component.dragEndListener,
})
.on('move', function (event) {
var interaction = event.interaction;
// if the pointer was moved while being held down
// and an interaction hasn't started yet
if (interaction.pointerIsDown && !interaction.interacting()) {
var original = event.currentTarget;
// create a clone of the currentTarget element
const clone = event.currentTarget.cloneNode(true);
clone.id = clone.id + "-clone";
clone.classname += " dragged-clone";
// insert the clone to the page
document.body.appendChild(clone);
clone.style.opacity = 0.5;
// start a drag interaction targeting the clone
interaction.start({ name: 'drag' },
event.interactable,
clone);
}
})
.on('end', function (event) {
console.error('end drag');
});
},
/* eslint-enable */
};
</script>
In general the dragging and dropping works.
But I don't get why e.g. the drop-event would trigger four times when only dropping a single card.
Can anybody help me with this?
I was facing a similar issue using the same framework and library. Since there was some logic based on the event firing, it was breaking my app when it fired multiple times.
I suspected that the issue was related to bubbling of events.
The solution in my case was therefore to add event.stopImmediatePropagation() inside my drop(event) handler.
As noted in the referenced article, one should take care when stopping event bubbling that it doesn't have unforeseen consequences elsewhere.

What is the difference between Lottie Events and Lottie EventListeners and How to use?

The documentation has both Events and EventListeners. I can get the EventListeners to fire but the Events do not have adequate documentation for me to get going. What is the difference and how do you use? Thank you.
https://github.com/airbnb/lottie-web#events
Events (Do not work, how to use?)
// From the Documentation
onComplete
onLoopComplete
onEnterFrame
onSegmentStart
you can also use addEventListener with the following events:
complete
loopComplete
enterFrame
segmentStart
config_ready (when initial config is done)
data_ready (when all parts of the animation have been loaded)
data_failed (when part of the animation can not be loaded)
loaded_images (when all image loads have either succeeded or errored)
DOMLoaded (when elements have been added to the DOM)
destroy
// End Documentation
From the standard addEventListener usage, this works...
birbSequence.addEventListener('loopComplete', (e) => {
console.log(e);
});
although 'complete' does not fire.
But to try out the stuff in Events like onEnterFrame?
var birbSequence = lottie.loadAnimation({
container: bodyMovinContainer1,
loop: true,
renderer: 'svg',
path: 'Birb Sequence 1.json',
onEnterFrame: function(e) { console.log(e); }
});
I am really new to using Lottie though so could use some help.
Just want a way to see how to use Events
Let's say we have our lottie animation:
const anim = lottie.loadAnimation({
container: '#container',
renderer: 'svg',
loop: true,
autoplay: true,
...
})
With Events:
anim.onComplete = function() {
console.log('complete')
}
anim.onLoopComplete = function() {
console.log('loopComplete')
}
With addEventListener:
anim.addEventListener('complete', function() {
console.log('complete')
})
anim.addEventListener('loopComplete', function() {
console.log('loopComplete')
})
You can use the addEventListener method to listen to all the events instead of the on* series of event hooks.
const options = {
container: '#container',
loop: false,
autoplay: false,
renderer: 'svg',
rendererSettings: {
scaleMode: 'noScale',
clearCanvas: false,
progressiveLoad: true,
hideOnTransparent: true,
},
};
try {
const anim = lottie.loadAnimation({ ...options, path: 'URL_TO_JSON' });
anim.addEventListener('complete', () => { console.log('complete'); });
anim.addEventListener('loopComplete', () => { console.log('loopComplete'); });
anim.addEventListener('data_ready ', () => { console.log('data_ready'); });
anim.addEventListener('data_failed', () => { console.log('data_failed'); });
anim.addEventListener('enterFrame', () => {
console.log('enterFrame', anim.currentFrame);
});
// etc ...
} catch (error)
console.log('error loading anim');
}
Hope that helps!

Categories

Resources