Javascript Event Listener at Interval - javascript

I'm listening for motion data on devices, using the ondevicemotion API. For example:
window.ondevicemotion = function(event) {
// do something with the event
}
I want to run this function when I call it; however, because it is based on an event, it triggers when the event does (which, depending on the device, can be often).
How can I adjust the function so it only listens for the event when I call it, rather than continuously?

You can add and remove the event listener as desired:
function processMotion(e) {
// your code here to process devicemotion events
}
function addMotionListener() {
window.addEventListener("devicemotion", processMotion);
}
function removeMotionLisener() {
window.removeEventListener("devicemotion", processMotion);
}
So, just call addMotionListener() when you want to start listening to motion. Then call removeMotionListener() when you want to stop listening to motion.
You can't really call processMotion() yourself because you need the system to create the system event with all the motion data in it. Instead, you register the event handler and the system calls you when there's data to be shared.

Related

How would I detect clicks in javascript?

I'm building a little web game in node.js, and I've been using event listeners for input, and it's worked fine for things like key presses and mouse movement.
window.addEventListener("keydown", onKeyDown);
window.addEventListener("keyup", onKeyUp);
window.removeEventListener("mousemove", onMouseInput);
(all of these have worked perfectly)
But when I tried using the mouseup/mousedown events (and also pointerup/pointerdown), they won't register. Is there something I'm doing wrong? Does it have to click on something?
window.addEventListener("pointerdown", changeShooting(true));
window.addEventListener("pointerup", changeShooting(false));
(doesn't work)
You have to pass a function to addEventListener, while you are passing the result of the call to changeShooting (which I assume does not return a function).
In order to do that, you can define an inline function like:
window.addEventListener("pointerdown", function() {
changeShooting(true)
});
If you need to remove the listener later, you have to define it explicitly:
function onPointerDown() {
changeShooting(true);
}
window.addEventListener("pointerdown", onPointerDown);
// later somewhere
window.removeEventListener("pointerdown", onPointerDown);

2 event listeners, run function once

I have two event listeners, one for a Click and a Touch event. They both should run the same function, but only once. If they are both true on some devices it runs the function twice.
I want to be able to click a button and listen for two event listeners but only run the function once if either of them is triggered.
window.addEventListener("click", function(event) {
myFunction();
});
window.addEventListener("touchstart", function(event) {
myFunction();
});
function myFunction() {
console.log("Clicked");
}
See MDN's article on Supporting both TouchEvent and MouseEvent
:
If the browser fires both touch and mouse events because of a single
user input, the browser must fire a touchstart before any mouse
events. Consequently, if an application does not want mouse events
fired on a specific touch target element, the element's touch event
handlers should call preventDefault() and no additional mouse events
will be dispatched.
Here is a code snippet of the touchmove event handler calling
preventDefault().
// touchmove handler
function process_touchmove(ev) {
// Call preventDefault() to prevent any further handling
ev.preventDefault();
}
Assuming the two events are fired almost simultaneously, you can prevent myFunction from executing twice within a pre-defined threshold using the following approach:
// threshold to reset allowing the execution
const _msThreshold = 200;
// date at which the function is last executed
let _myFnExecutedAt = new Date(0);
// your function
function myFunction() {
console.log("Clicked");
}
// executer that checks if the threshold is exceeded
// to allow your function call and reset the timer
function execute() {
if (new Date() - _myFnExecutedAt > _msThreshold) {
myFunction();
_myFnExecutedAt = new Date();
}
}
window.addEventListener("click", execute);
window.addEventListener("touchstart", execute);
Bear in mind that you'll have to experiment a bit with the threshold value:
If you set it too low, it might be exceeded before the second event registers so both will trigger.
If you set it too high, subsequent real clicks/touches might not register.

Why are Angular Keystrokes not run synchronously? Or how can I make them run synchronously?

How can I make Angular 4/2 keystroke events run synchronously?
When I run this code the keys are not always run in order of firing.
Template
<div
contenteditable="true"
(keydown)="divKeyDown($event)"
(keyup)="divKeyUp($event)">
</div>
Component
divKeyDown(event) {
console.log('Keydown');
// OFTEN GETS FIRED BEFORE KEYUP OF PREVIOUS STROKE
}
divKeyUp(event) {
console.log('Keyup');
}
Keyup is only fired when the key has literally become up and has no concern of other keystrokes.
Keypress would be a better event to use in this scenario as it is always fired directly after keydown, and never before another keystroke.
This is default behavior and not related directly to Angular.
Even in vanilla JS, the same behavior is observed:
document.getElementById('main').addEventListener('keydown', event => {
console.log('keydown'); // FIRED ONCE
});
document.getElementById('main').addEventListener('keypress', event => {
console.log('keypress'); // FIRED AFTER KEYDOWN
});
document.getElementById('main').addEventListener('keyup', event => {
console.log('keyup'); // FIRED WHEN THE KEY HAS LITERALLY BEEN RELEASED
});
(In this scenario I have used Angular's 'ngAfterViewChecked' lifecycle hook to handle the changes in state directly after the 'keydown' event has completed)

Should I / how do I clear a mousemove JQuery event listener?

When I use
$(".page").mousemove(function(event){});
As soon as the mouseup event comes, I no longer need this listener. Since I'll be applying the listener repetitively for different actions, it seems to me that these listeners might stick around and build up (needlessly wasting CPU) as the user activates the function many times. I'm not really sure how this works internally, that's just my guess.
Should I / how do I clear a mousemove JQuery event listener?
Here is the code:
$('.page').off('mousemove');
But please note that the following approach turns off all functions firing on mousemove. If you want to turn off a prticular function then you should do the following:
// Define function that fires on mousemove
function anyFunctionName () {
// Some code
}
// Set listener
$('.page').on('mousemove', anyFunctionName);
// Turn off only function called funcionName
$('.page').off('mousemove', anyFunctionName);
Another way for turning off a particular function would is defining a name for the event:
// Define function that fires on mousemove
function anyFunctionName () {
// Some code
}
// Set listener
$('.page').on('mousemove.anyEventName', anyFunctionName);
// Turn off only function fired on event called anyEventName
$('.page').off('mousemove.anyEventName');
I was able to get a working example using the more general .on and .off JQuery functions instead of their explicit handlers. Here is the code I used:
$('.page').on('mousedown', function() {
$(this).on('mousemove', function(event) {
// Do something meaningful
});
});
$('.page').on('mouseup', function() {
$(this).off('mousemove');
});
Here is a JFiddle Demo of it.

How to change all onClick events to TouchStart on iOS?

OnClick event has a timeout ~400ms before executing on iOS-browser (demo). And I want to change it to TouchStart event for all DOM-elements who have onClick. How can i make it?
I use jQuery and i tried check all elements for click function:
$('*').each(function() {
if($(this).click != null) {
// BUT all elements in DOM has click
}
})
I don't have an exact answer, but I think you should be able to make this do what you want.
For every element on your page that has an OnClick, add a class - say TouchTarget. Then use this in your startup function.
$('.TouchTarget').bind('touchstart', function (e) {
e.preventDefault();
touchStart(e, this);
});
Create a handler function that looks like this:
function touchStart(pEvent, pElement) {
//Do something with the touch.
}
If you only want to register if touch is available, then you can protect the bind call with
if (Modernizr.touch) {
}
I believe the reason for the delay in OnClick is because Safari is waiting to see if the touch is really a click or a drag, or some other gesture. This will recognize a simple touch quickly. I normally bind both touchstart and touchend when I need quick touches so that touchstart provides visual feedback and then touchend does something with the "click". This method does not have a delay built in.
Use a product like http://www.jqtouch.com/ or the code snipped provided here: http://cubiq.org/remove-onclick-delay-on-webkit-for-iphone.

Categories

Resources