What is the documented range for TouchEvent#touches? - javascript

I'm looking at the TouchEvent#touches documentation from MDN web docs, and the code sample provided only supports up to 3 touches.
someElement.addEventListener('touchstart', (e) => {
// Invoke the appropriate handler depending on the
// number of touch points.
switch (e.touches.length) {
case 1: handle_one_touch(e); break;
case 2: handle_two_touches(e); break;
case 3: handle_three_touches(e); break;
default: console.log("Not supported"); break;
}
}, false);
That being said, I'm pretty sure that there are 3+ finger touches, but I was wondering if there was a min/max range for these touches (e.g. can there be "0" touches in any scenario?)

Practically speaking, the W3C standard for TouchEvent does not define a maximum number of touches. Instead, the maximum is going to be the maximum number of consecutive touch points supported by the device's touch screen. In a virtual environment, this could presumably be infinite. Older devices seem to have been less than 20 consecutive touch points, however this could have increased with more modern technology.
Technically speaking, the spec defines the TouchList#length property as an unsigned long, so the absolute maximum within the spec will be 4,294,967,295 consecutive touch points:
interface TouchList {
readonly attribute unsigned long length;
getter Touch? item (unsigned long index);
};
As for the minimum, the spec does not say that there must be at least one item in the list of active touches. However, if you are listening to the touchstart event, then the received TouchList will always contain the touch which triggered the event:
touches of type TouchList, readonly
a list of Touches for every point of contact currently touching the surface.
and:
changedTouches of type TouchList, readonly
a list of Touches for every point of contact which contributed to the event.
For the touchstart event this must be a list of the touch points that just became active with the current event. [...]

Related

Can't get correct values for touch.rotationAngle or touch.force on Surface Pro 4

I am testing a project on my Surface Pro 4 and I am using the Touch interface in javascript. According to MDN, the rotationAngle and force properties should return [0 - 90] and [0.0 - 1.0] respectively.
But no matter how I touch the display, I get fixed values for either of them. In Chrome (81) it is always 0 and 0.5. In Firefox (76), 0 and 0 are returned.
The code is simple:
element.addEventListener('touchstart', function(evt) {
// Prevent the mouse click
evt.preventDefault();
//-- Log the touch information
var touch = evt.changedTouches.item(0);
console.log(touch.radiusX);
console.log(touch.radiusY);
console.log(touch.rotationAngle);
console.log(touch.force);
});
Now, about the force property, MDN specifies that if the value is unknown for some reason (e.g. the device doesn't support it), 0.0 is returned. But nothing is mentioned about a constant 0.5 for this property or 0 for the rotationAngle.
Am I missing something? Or does the Surface Pro 4 indeed not support these values and I can not do anything about it?

Dealing with bizarrely inverted wheel event deltaX in Microsoft Edge browser?

Today I've discovered some very bizarre behavior in Microsoft's Edge browser, where the deltaX values for wheel events is apparently inverted! This was particularly surprising because this is not consistent with every other browser I've ever tested, including Internet Explorer 11 which returns the expected values.
Seeing this issue in action is rather simple, just run the following code, and use your mouse wheel or trackpad.
window.addEventListener('wheel', function(e) {
console.log(e.deltaX, e.deltaY);
});
For your convenience, I've created a full-page example (snippets are tricky for this):
Fullpage Working Example
Wheeling down gives a positive value and wheeling up gives a negative value as expected in Edge, IE, and other browsers. However, in Edge wheeling left gives a positive value, and right a negative value, the exact opposite of every other browser (IE11 and below included).
I made some GIF videos to show off the issue too, linked for file sizes.
IE11
Edge
The question:
Why is it like this, and is there a solution for handling the browser compatibility issues? Is there a way to feature-detect this? Is this behavior a bug, or is it documented somewhere?
The spec strongly suggests this is in-fact incorrect behavior:
If a user agent scrolls as the default action of the wheel event then the sign of the delta SHOULD be given by a right-hand coordinate system where positive X, Y, and Z axes are directed towards the right-most edge, bottom-most edge, and farthest depth (away from the user) of the document, respectively.
Notes:
I've tested this in both a Windows 10 VM and a native laptop, behavior was the same for both.
I'm reasonably sure this is not related to "natural"/inverted scrolling (off on all systems and VM hosts tested, and only happening on one axis).
On a side note, I don't know if deltaZ is inverted or even supported to begin with, I lack such an input device.
Bug Report:
I've reported the bug to Microsoft here. It has been assigned to someone, so hopefully it will be fixed.
While we await an official response from Microsoft, hopefully in the form of an update that resolves the issue, I have found a way to check if the browser is reporting an incorrectly inverted deltaX.
Edge also added support for the non-standard wheelDeltaX, wheelDeltaY, and wheelDelta properties also found in Chrome. Unlike deltaX, these values are correct, but instead refer to the actual wheel change and not the computed result. While their actual values are of little interest, we can infer the correct sign value from them.
In Chrome, deltaX and wheelDeltaX correctly have different sign values, so when one is negative, the other is positive. This means that if both values are negative or both are positive, the deltaX is incorrectly signed as it is presently in Edge. Therefore we can use this property to detect the incorrectly inverted value and un-invert it.
Here is a wrapper function I created to resolve the issue.
function wheelDeltaX(e) {
// Get the reported deltaX.
var r = e.deltaX;
// In Edge, the deltaX incorrectly matches wheelDeltaX sign.
// If both value signs match then uninvert it.
var wheelDeltaX;
if (
r &&
(wheelDeltaX = e.wheelDeltaX) &&
(
(r < 0 && wheelDeltaX < 0) ||
(r > 0 && wheelDeltaX > 0)
)
) {
r = -r;
}
return r;
}
So long as Edge retains the correct signing for wheelDeltaX when they hopefully fix the issue, this should be future-proof.

Get device orientation (alpha, beta, gamma) without using listener?

I'm using window.DeviceOrientationEvent to listen for changes in the device orientation. However, I want to calibrate my application to report orientation changes relative to the original orientation. In order to do this I have come up with the following solution:
originalOrientation.freeze = false;
window.addEventListener('deviceorientation', function(e){
var orientation = {g: Math.round(e.gamma), b: Math.round(e.beta), a: Math.round(e.alpha), o: window.orientation || 0};
if(!originalOrientation.freeze){
originalOrientation = orientation;
originalOrientation.freeze = true;
}
});
This essentially takes the first value returned by the deviceorientation listener and "freezes" it so it doesn't keep updating. I don't like this method because I'd rather do the calibration elsewhere in my code, instead of the place where the actual orientation is gathered. I also don't want to attach the listener twice because the value returned in the callback will be lost.
TLDR;
Is there a way I can call something like window.getDeviceOrientation() to return the alpha, beta, and gamma values synchronously instead of attaching a callback?
I think the full-tilt library would achieve this for you.
There's a simple example on the github page that shows how you initialise their promises based library, then in your logic, you just check that the device orientation object exists (IE the promise was fulfilled) before calling a method such as deviceOrientation.getScreenAdjustedEuler().
You don't have to be using an animation loop like in their example.
As an aside, you could have added and removed the event listeners without losing your data. I definitely would have done that rather than disable the listener with the freeze. I was adding and removing listeners as required for a while to get the initial state to compare with later when constant updates were needed (or more accurately not subscribing to the event when they weren't needed). I'd still go with full-tilt though. I used it because it provides normalised data across devices but it does pretty much what you want and would probably make your code a little neater.
If you're still working on it 5 months later that is, yeah this is probably of more use to someone hunting around now.

While multi-threading in JS -- time latency shows up in fluent message dispatching

I'm using multi-threading in my web-application to render some geometric
diagrams involving (very) long loops.
During early (and raw) implementations, I found that reducing the number of
parameters being passed from the multi-threader to the related
listener really sped up the whole loop. It also let the web application dispatch the events queue with fluency, so that the onclick event halts as I click the mouse button down. It works great, as it's expected to in these cases.
Now I am programming a new situation involving parsing user-defined formulas. Say 'z^2-z+1' for example, inside the same long loops as mentioned before.
I expected the parser to slow down the dispatching of messages from the multi-tasker to the listener, but I can't figure out the reason why the same onclick event is being processed quite later after the mouse button has been pushed.
It seems that the parser itself is out of sync with the multi-threader dispatch process, causing long time intervals of latency delays, where events can't be processed immediately as usual.
Increasing the number of messages sent from the multi-tasker to the listener
didn't work as well as decreasing the number of messages. In the first case, I failed to guarantee a frequent exchange of messages due to the counter-effect of making the loop running quite slower and due to the high number of messages sent to the listener.
On the contrary, decreasing such number affected the communication from multi-tasker to listener because few events are sent and so they are then processed a long later.
Naturally, according to my early success, the number of parameters passed to the listener remained the same.
It seems I'm facing a different aspect of the same problem and I guess I should find the way to forward some stopping command to the parser.
Any trick to keep the events queue dispatching fluently again ?
Thank you
It's hard to represent it through a specific example. But I'll try.
Say you have a loop in multi-threader object (this code works nice as expected):
var _glob_stop = 0 ;
for ( var _i = 0 ; _i < 10000 ; _i++ )
{
// plot points on a canvas
if ( _glob_stop ) break ;
}
In the case above, the state of _glob_stop changes IMMEDIATELY due to an onclick event fired by the user.
Now in this new situation:
for ( var _i = 0 ; _i < 10000 ; _i++ )
{
// parse a user-defined formula, say 'z^2-z+1'
// plot the resulting point on a canvas
if ( _glob_stop ) break ;
}
Now the response from firing the onclick event is caught later, long after, from the dispatcher.

Transitionend based transition loop breaks in Chrome

I have very basic promise based self-calling function that:
takes collection of divs with certain class
checks whether they have just been moved left or right
based on result makes choice to move (transform: translate) them
with classList.add() / classList.remove()
and on transitionend - calls itself
here is function:
function transitionTest(){
console.log('called --- transitionTest() ');
var dummies = document.getElementsByClassName('dummy'),
count = dummies.length;
if(window.cache==='right'){
var transitionCollection=0;
for(var i = 0; i < dummies.length; i++){
dummies[i].classList.remove('right');
dummies[i].addEventListener('transitionend', function(){
transitionCollection++;
if( transitionCollection === dummies.length ){
transitionTest();
}
});
}
window.cache='';
} else {
var transitionCollection=0;
for(var i = 0; i < dummies.length; i++){
dummies[i].classList.add('right');
dummies[i].addEventListener('transitionend', function(){
transitionCollection++;
if( transitionCollection === dummies.length ){
transitionTest();
}
});
}
window.cache='right';
}
and here is working fiddle
So, what is wrong?
Nothing, if you are accessing via modern browser but not latest versions
of Chrome on Windows
Nothing, if you are accessing via latest versions of Chrome on Windows but refrain from causing any mouse events such as mouseenter/leave, click, even window focus event (e.g. if you stand still)
If you do such, infinite left - right movement of dummy div will occasionally break, under unclear circumstances
What gets wrong:
Dummy div, which is moving left-right infinitely, on mouseenter, mouseleave, click, sometimes and sometimes not (exact conditions are unclear) will:
go to end CSS value without transition and resumes normal operation after a while
stop entirely and resumes normal operation after a while
slow down (!? yeah, I wish I was kidding ) and stop/go to end CSS value
These errors are occurring in Chrome 45 (Win 7) and, less intensively Chrome 42 (Win XP) - which are platforms that I was able to test by now. Just to note, upper code does not need to be cross browser, I'm fully aware of implications.

Categories