Firefox, touch events and "smooth" scroll behaviour – results in no scrolling - javascript

I'm at a loss as to what is going on here.
Please refer to the CodePen: https://codepen.io/ilmiont/pen/jJjgPw?editors=1111
Swiping with a touchscreen should smoothly transition the screens up and down, using the "smooth" scroll behaviour.
This does work exactly as intended with Chrome.
Firefox... just doesn't scroll. Yet the touch events are being fired, and "Next" / "Previous" is being logged to the console. But the scrollIntoView(...) call does nothing when invoked with {behavior: "smooth"}.
If you click the button, the scroll behaviour is changed to auto (no smooth scrolling)... and this works without any issues in Firefox.
What have I missed? Why is Firefox not scrolling at all when smooth scroll behaviour is used, even though it seems the swipes are being detected correctly?
A further oddity: the demo doesn't work in Chrome in CodePen either. Copy the HTML/CSS/JS into a new document (right-click CodePen viewer, "view frame source") and run directly in the browser, and it works exactly as intended, with smooth scrolling within the pages.
I think I must have missed something, and the CodePen issues in Chrome are interesting, but I just can't see what right now.
Chrome... just works... except in CodePen.
Firefox... everything looks like it should work, but the scrolling never occurs.

This has taken me far too long to figure out, but here's the solution which finally works:
Use passive event listeners!
In the original pen, I was doing {passive: false} and then calling preventDefault(...) on the touchstart and touchmove events.
It turns out, that this isn't necessary to achieve the desired effect.
Using the passive listeners results in everything working as intended in Firefox.
I still consider the original behaviour is odd; further investigation revealed there seems to be a timing issue in Firefox. In the swipe(...) method, adding a 250ms timeout to the dispatchEvent(...) call results in everything working as intended also – it seems as though the touch handlers can continue to block/throttle scroll events past when they should have been removed.
Will keep investigating but I have a solution for now.
(Edit – forgot to mention, when using passive listeners, also set touch-action: none on the target.)

Related

Delay on resize event on virtual keyboard on iOS Safari

I'm working on an a webapp, where I need to adapt the contents of the screen when the virtual keyboard is expanded. Luckily, someone has already created an example of this here:
https://pmusaraj.github.io/ios15-bottom-bar2.html
When tapping on the text area, it correctly resizes. However, there is a small delay between the tap and when the resize happens in iOS 15.5. This is because the resize event doesn't seem to fire fully until after the keyboard is expanded. In iOS Chrome, interestingly, this does not happen and it works correctly.
Are there any workarounds to get Safari to fire the event sooner? Or alternative approaches to achieving a similar effect?
As of today there are no real solutions for this.
The only "workaround" that I found is to detect when the keyboard opens and closes with regular events like focus and blur. But you can't guess the final visualViewport sizes because there are different keyboards so this wasn't an option for me.
My "solution" to this issue was extend the modal and its background fade beyond the viewport with after elements (see here). That way there is still a jump between opening and closing the keyboard, but at least the look is a bit more consistent.

Relative positioned div jitters while scrolling in Safari

In the following fiddle, there is significant jitter while scrolling. The jitter is noticed only in Safari on Mac, while Chrome and Firefox scrolls the page smoothly.
https://jsfiddle.net/saptarshi17/akxuLL9x/
The jitter is a result of applying parallax effect on the first paragraph. The parallax is implemented by dynamically calculating the top css property triggered by scroll events. I am noticing this on Mac OSX El Capitan, not sure about Windows.
So far, I tried:
Added a mousewheel event-listener in addition to scroll as per this accepted answer on SO.
Tried wrapping the css("top", ...) function call within requestAnimationFrame()
Changed div from relative to absolute to avoid costly reflows.
Added preserve3d property to "hardware accelerate" position calculation as per some comments somewhere on SO.
Since 2 and 3 haven't helped, I assume the core issue has much to do with Safari's scroll implementation and less about frame-rate optimizations. There is a delay Safari's predictive rendering and the subsequent handler call which offsets the position. This results in 2 renders causing the jitter. While I understand Safari's intention behind the first render which works in most cases, this seems to be wrong in cases when the developer wants to override positioning. Maybe there is a way to tell Safari to disable the predictive rendering.

Mouseenter event triggered in chrome when resizing window

Very strange behaviour in Google Chrome !
I've got a grid of div , and on each of then, I add an eventListenner for mouseenter event. In my demo code, when the event is triggered the div get opacity:0.2.
$(".target_div_class").on("mouseenter", [my action ...])
Well, it's work's on every browser except in Google Chrome.
To reproduce the strange behaviour in chrome, go to my codepen demo page place the mouse pointer in front of the grid and start to resize the main browser windows quickly, you will see that some of the divs get opacity changed even if there is not mouse roll-over !
what I'm doing wrong, is an special jquery event that Chrome doesn't like ?
thank's
larry
edit -1-
I think I understand why some div receive the event.
It seem's that, when I click on a border (left or right) of the browser, Chrome keep a trace of the mouse position X and Y.
Then when slowly expand the browser width, any div that under this "start mouse position" receive the event.
It is really simple to reproduce when first the browser width is thin, and then slowly expand it, if I take a pen and place it at the mouse start position before resize, It's clear. very very strange.
edit -2-
This behaviour is only on a OS windows 8, I've just test it on a Mac , and there is not problems !
Well, I've been testing this behaviour on a couple of sites, like this one :https://devart.withgoogle.com/
made by Google professional I suppose, and the strange behaviour occurs again, I'll try to find how to contact Google Chrome team ...
I do not believe that mouseenter/mouseleave is fully supported by chrome. Chrome only simulates those functions, unlike in IE.
But, the problem only occurs when someone tries to re-size the window faster than the browser's edge actually moves and the mouse goes into the page momentarily. So, its not that unreasonable a behavior. You could always try to fix it with a
$(window).resize(function() {
//some code to reset opacity
});
See if this helps
$(".target_div_class").on("mouseenter", function(){
event.stopPropagation();
//your code
});

Scroll event on Android Browser not firing. Need workaround

I've created a website with a parallax street scene. See here for an archived version.
It works just fine on all major desktop browsers, and Safari Mobile. It works fine in Mobile Firefox and Chrome for Android Beta also. However the default Android browser has issues with the scroll event. Let me be clear. Scrolling is not the issue. The div scrolls as required. The scroll event doesn't fire. This issue I experience on Honeycomb as well as ICS.
I'm not concerned about other mobile browsers because for mobile screen sizes one usually does not see the parallax scene; mediaqueries and conditional JavaScript loading take care of that. Responsive design and all that jazz.
Basically, I've written a parallise() jQuery plugin that positions each image based on its position and 'depth'. This function is bound to the scroll event.
On Android Browser, this event only fires at the start of the next touch, instead of continuously.
OK, so I thought that perhaps if I bound the function to touchstart, touchmove, and touchend events I would solve my issue. No cigar. Other touch events are also bugged. Applying the suggested workaround causes the events to fire, but as I have to e.preventDefault(), scrolling (the whole point of the exercise) is disabled.
What if I just poll the position of the stage div relative to the window div? Turns out that the position information is only updated at the start of the next touch.
I am at the end of my tether. Any help would be much appreciated.
Even if the touch events worked correctly on the bugged versions of Android, and you were then effectively able to track the native scroll position during a drag, this would be prone to error. For example, it wouldn't account for the momentum animation which happens after the touching has finished.
iOS and Android make sacrifices to improve the performance of scrolling. On both platforms, it's not possible to get the accurate scroll position until the scroll has completed. The scroll event (on the <body>) doesn't fire until the momentum animation is finished. So while your original question is about scroll events on an overflowing <div>, fixing this might not be totally helpful for you anyway.
If you want an animation to update in time with the scroll, then you need to perform the scroll programatically rather than using the browser's native scroll. The best library to do this is iScroll. You can achieve parallax effects very easily as seen in this demo.
If you need more complex effects (the walking character, in your example), you can opt for the "probe" version of iScroll which allows pixel-perfect polling of scroll position in return for reduced performance.
However, there are many downsides to using iScroll:
You may need to change your markup and styling
It is unnecessary overhead for desktop browsers, but due to markup changes may be difficult to use only as a fallback
The scrolling will not feel perfect - on iOS, with its usually excellent scrolling performance - the slight difference in momentum calculation can feel jarring. On Android, the scrolling can become more laggy than usual.
Swipe shim that doesn't need preventdefault on touchstart: https://github.com/TNT-RoX/android-swipe-shim

Javascript Opera - Turn off document body scroll (temporarily)

I've got a pic viewer that uses the mouse wheel to zoom. Works fine except in Opera, the wheel scrolls the page first, then fires the wheel event, which is less than desirable (since now the picture has moved up or down the page).
So, I want to turn off the body scroll while the viewer is active. Shouldn't be too hard, right?
Does the JavaScript that scrolls also call event.preventDefault()? This should work, though I haven't tested it recently myself.
possibly this might work?
body {
overflow: hidden;
}

Categories