Javascript functions are cutting in and out [duplicate] - javascript

This question already has an answer here:
What are passive event listeners?
(1 answer)
Closed last year.
I have one issue that is a recurring thing every time I work in Javascript, which is that my code seems to be cutting in and out, depending on whether I scroll, resize the screen, reload, etc. It even seems like the speed of which I scroll seems to be a factor (even though I am, in this situation, trying to create a scroll effect, which does work as long as I scroll slowly). I have tried to figure out work arounds almost constantly since starting coding JS, but I can’t even figure out why any of this is happening, and I don’t even know what to good to find the answers.
Generally, when I create functions, I try to use the following structure
document.addEventListener("click", function functionName() {
/* function content */
});
However, this really only seems to work with click effects, and maybe hover. for scroll effects, because resizing the screen will cause weird things to happen, I have tried using the following structure
function functionName() { /* function content */ };
document.addEventListener('scroll', functionName);
window.addEventListener('load', functionName);
window.addEventListener('resize', functionName);
This generally works better, and generally prevents screen resizing from interfering too much with scroll effects. However, it makes the code what I am seeing very jumpy and glitchy.
Is there a better way to do this, so that I am a scroll effect will always appear how it should, regardless of whether the screen resizes loads or scrolls, etc.? also, it there a way to make the code work better without having three separate event listeners to activate a single function?

The challenge you are running into for other events is that they can be called 10s or 100s of times per second. What you need is to throttle the functions you are calling, especially if they are expensive.
I suggest you look at makeThrottleFn in my xuu library. You might just install it and test like so:
const throttleFn = xuu._makeThrottleFn_({
_fn_ : onResizeFn, _delay_ms_: 250
});
// And now use this for windowresize
window.addEventListener('resize', throttleFn);
Of course there are many other libraries that offer throttling, so feel free to go shopping.

Using document.addEventListener("click") is going to run the function anytime the screen is clicked or touched. And applies to the whole document. Meaning anywhere you click the event listener is going to run.
Using the scroll event is running the block of code multiple times. This will create undesired results unless you put in something to stop it.
So using multiple document.addEventListeners with "click" and "scroll" will most likely overlap in some cases causing wierd things to happen with both functions running multiple time or randomly.

Related

How does one implement scroll hijacking (scrolljacking) in the browser (react or vanilla js)?

I've been trying to implement something like what Typeform does (Example https://www.typeform.com/templates/t/online-quote-form/?preview=template) where the user can't scroll the page, and instead any scroll trigger just advances to the next question.
So far I've figured out that it's insufficient to add a handler to the scroll event. It seems like I need to add handlers to wheel, keydown, swipe, and maybe other things, to implement the different scrolling behavior.
But I can't seem to work out all of the kinks. In particular, a wheel scroll will have the expected behavior and then continue scrolling, and I can't seem to cancel that behavior.
(I'm aware that this is a UX antipattern; I'm doing it anyway.)
At the moment I don't have a reasonable code sample but I'll add one if nobody has a solution offhand.

Touchpad scroll detection in JS, no library

I'm making my own little Javascript library that makes it easy to replace the default scrollbars for your Website (and mine) with custom ones. Part of that means giving the BODY element an "overflow:hidden" style to hide the normal scrollbars. However, this prevents all scrolling except for that which is done in code.
I have everything working in terms of showing the bar and having it scroll when you click/drag it. However, many touchpads (like on the computer I'm testing this with) have a feature where you can scroll by sliding a finger along the right side of the pad. I need the library not to break that, so I need some way of detecting when the user tries to scroll this way.
I thought it would be interpreted by the browser as a mouse wheel, so I set up an onmousewheel event, but that doesn't seem to capture it at all. For the record, I'm testing with Firefox 25.0.1.
Is there any way to capture the trackpack scrolling, preferably without an external library? I'm trying to keep this as self-contained and lightweight as possible, but if I absolutely need to, I guess I can use jQuery and its mousewheel extension...
Some browsers use the onwheel event instead of onmousewheel. So, it's usually a good idea to listen for both events.
See this MDN article for more about onwheel.

Questions about Request Animation Frame

I'm trying to build a parallax site, which will move few elements while scrolling the site.
But instead of using a scroll event listener I'm using requestAnimationFrame, after reading this post by Paul Irish, and this video which said that scroll listener is a bit buggy. My questions are:
It looks quite smooth in Chrome, but it's flickering badly in Firefox. Did I do something wrong here?
Does my code actually taking up more resources than using normal scroll event listener? I can hear my laptop fan blazing every time I'm playing with this code.
My file is located at http://www.socialbuzz.com.au/index.html, and please scroll to the bottom of the page to see the element that's being manipulated from javascript.
You should have a the scroll event trigger a requestAnimationFrame loop. Do not have requestAnimationFrame triggered by the scroll event itself. You should have something like a var scrolling = true; While this is happening run your requestAnimationFrame loop which references event data from the scroll event. You'll need to debounce the scroll event to turn to loop off once you are finished, it's a chore but the results are worth it. Hope this helps.
You are not performing an animation; that is, you are not modifying your graphics continuously without user interaction. Your manipulation of the page happens only when the user scrolls and does not continue after the user stops scrolling. Therefore, there is no benefit to using requestAnimationFrame, and you should stick to a simple event handler.
The purpose of requestAnimationFrame is to provide optimal behavior for continuous animation; none of its advantages apply here. A looped requestAnimationFrame which does nothing inside the loop, as you currently have, is entirely appropriate if each step of the loop updates the graphics in some way, but since here nothing changes when the user is not scrolling, the loop does nothing but waste CPU time.
An example of when you should use requestAnimationFrame is if you had elements which deliberately lagged behind the scrolling and caught up after a moment. The catch-up animation should be done in a requestAnimationFrame loop which is started from the scroll event handler, and that loop should stop itself when the catch-up finishes.
I have had a similar experience and after much playing around with mouse move listeners and setInterval to increase the frequency of the animation steps, I have gone back to just using onscroll and find that on FF10 and FF 15 it is working great.
Maybe my requirements are not the same as yours - it is an element that tracks the scrollbar so onscroll was the cue to change the position of the box. It lagged behind and was jerky on FF, but worked fine on WebKit and IE. What I found was that onscroll did not fire as often on FF as on Chrome/IE.
When I initially tried this it would be on FF 5 or 6 though. Using a mouse move listener or a frequent interval, I was able to increase the frequency with which my handle scroll function go called - but this actually had the effect of making the positioning appear choppier. Just using onscroll seems to be working for me now on 10 ESR and 15, maybe they fixed something.

Safari jittering/jumping (bug?) on first "focus" event of page load

I'm currently fighting a very frustrating bug on Safari, and I'm not sure where else to turn.
It seems most elements (but not all, and I can't discern the differentiating factor) that will trigger a focus event will cause all elements on the page that are transitioned or animated to jump ~2px to the top and left. And this only occurs on the first focus event after the page loads.
It's a little annoying to see the bug, as it's in the logged-in portion of droplr.com, and I have been completely unable to distill down a simpler case on JSFiddle.
If you have/create an account and log-in, click on this edit icon for a drop:
You'll see that on the first focus of the page, things jitter. Here's the timeline when there's a single drop on the page and I trigger focus on an offending element:
With more drops, it's just more of the same, but it seems to max out around 40 paints. And the profiler doesn't suggest anything nefarious. Just a trip through jQuery internals.
If instead of laying elements out via a translate3d or matix3d, I simply use top and left, this bug goes away. After hours and hours of debugging this, I'm at a complete loss.
Hoping someone has seen something similar, could take a look, or could give me advice on debugging next steps.
Thanks so much!
Update: Dave Desandro suggested it was the 3d acceleration kicking in, so I tried it out with a translate instead, and sure enough, that did not cause the jitter. I have no idea why the hardware acceleration would be firing up with a focus event though, and only once.
I've tried setting a transformZ of 0 on page load to go ahead and ramp-up the hardware, but no luck there, either. Any more ideas are welcomed.
I've had this issue a while back and honestly I don't remember what exactly was the cause but here are some of the steps I followed:
Check that you don't have hide() and show() for the same element in the next line or vice versa.
Example:
el.show()
el.hide()
Change Custom fonts to "Arial"
For the elements you don't want focus events add this code at the bottom of your scripts:
noFocusElem.off('focus');
This will make sure to remove any focus handlers you might have added by mistake
Finally place your css before any scripts. It's a know fact that adding css rules after an inline style has been applied may cause jitter especially if you're using line-hieght property
Hope this helps :)
I've had this happen when using custom font kits. Could this be the issue? Some events cause custom fonts to re-draw, which can cause a ever so slight "jitter" in page display.
Sometimes, manually setting heights and widths on all the parent HTML elements can reduce the flicker.
I know this question was posted a while ago and this is a bit of a long shot but here goes:
Maybe as a starting point go back to chrome and look at the composite layering:
Hit this into the address bar:
about:flags
You will be able to enable composite borders from within there. The red borders generally indicate a rendering issue:
http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
What I have found from time to time is that although there are rendering issues in Chrome the browser copes pretty well with hiding them from me. In other webkit based browsers however the result can be more noticable (i.e. android).
I've also seen flickering occur when z-indexes are being used in conjunction with content that is being transformed.
Either way it would be great to know how you resolved this issue (if you did). Post an answer to your own question perhaps?
A way to avoid spending time fixing load time twitches; you could set the page to hidden then make elements visible with the load. If your page is slow to load, you may want to have a spinner default to visible, then have load hide it. Then you could come back to the issue when you have nothing better to do.
Just my 2c worth.
The first thing I would try:
First in chrome, whack in 'about:flags' (yes I know you're not using Chrome). Find the 'Composited render layer borders' and turn it on. Once this feature is switched on you'll get a rough idea of what is being rendered/hardware accelerated.
See: http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
and look for any rendering problems. These are normally caused by z-indexes. Play around with any z-indexes and hide/show certain elements until the rendering issues are resolved. Then work from there. translate-z hacks and opacity can also cause problems.
From experience I've found rendering problems in other webkit browsers can be diagnosed using chrome. Flickering is a common occurrence on the stock android browser.
Secondly: take a look at the focus event itself and try things like preventing the default behaviour. Seems like a long shot to me but give it a go.
I haven't tested this, so I will be very surprised if it works... but here's an idea:
$(document).ready(function() {
$(document).focus(function(e) {
e.preventDefault();
});
$(document).click(function() {
$(document).unbind();
});
});
I've been running into the same issue recently and found something that fixed it in my case.
Check for anything that's hidden offscreen like:
text-indent: -9999px;
left: -9999px;
Removing any instance of these from the 3d accelerated elements (including children) stopped the content jump on focus for me.

Jquery animate problem

I have the weirdest of problems.
I have a jQuery function that animates the result bars of a poll.
function displayResults() {
$(".q_answers1 div").each(function(){
var percentage = $(this).next().text();
$(this).css({width: "0%"}).animate({
width: percentage}, 'slow');
});
}
As you can see it is a simple animation that elongates a couple of divs. It works OK until I embed it on my main page. The problem seems to be that there is too much OTHER content that breaks the beauty of the smooth animation. I was thinking of me being lame in implementing the JavaScript, CSS etc. but after a couple of tests and reverse engineering I found out that THE MORE CONTENT (images, text, video) I HAVE ON THE PAGE, THE WORSE THE QUALITY OF THE ANIMATION IS. I can only guess what the reason is... I really like my animation :)! Appreciate the help!
This demo shows how it should look like. I get it to work like this when the page has less content on it. By bad quality I mean not smooth flow of the bars. The worst case is when the bars appear in their final width in an instant.Tested it on Mozilla and Chrome and IE7 - no difference.
Edit: It seems that without the actual examples your hands are tied so here is something to work on. Just look for the red border, pick one answer and click the button. The language is Bulgarian if you are wondering.
A desirable behavior here
I can live with that here
Starting to look weird here
I don't get this here
If all of them look the same to you then my computer is to blame and I don't have to worry about this particular problem anymore, which already took 2 much effort. Use Mozilla if possible.
Edit 2: I found this SO answer that answers some of my questions about the animate() function and how it works, but the problem remains unsolved, at least for my computer.
How much content are we talking here?
If the page is large enough, the browser engine may simply not have enough power to re-render the contents quickly enough to provide a smooth display.
The way jQuery does it's animation is that it periodically updates inline CSS attributes. If the elements you're changing style's of are floated or have other complex interactions with the other elements on the page then the animation wont be smooth.
In short, put less stuff on your page. You might also attempt some sort of iFrame solution or switch to using flash to display the results.
This is just a limitation of the system, unfortunately.

Categories