JQuery How to make condition not to run only once. - javascript

I have a little problem with conditions and its triggering. I have 2 object in my HTML (div and img), that I am trying to constantly align by JS. By constantly I mean so that when window size changes, they realign (since one is aligned to the center - and no :), I can't center-align the second one as well, because I also need to match the size, which definitely requires JS).
I made a little function that aligns them and sets proper dimensions to it and I am triggering the function on every window.onresize event (as well as on document ready). But I found out, that it does not trigger on zoom action and besides that it would be more suitable for me not to be dependent on window.onresize.
So I thought there would be a posibility to write a condition like
if (div.width() != img.widht()) {
// do something to match it again
}
But it turned out to only run this condition on the ready event (resp. load event, since I have a picture). So my question is, if there is any way, so that the condition would be checking its state just continuosly? I know, I can probably set Interval to take care of that, but a) I guess that like 99% of all executions would be pointless and b) unless I set it to like very quick repetition, it would not even fix the div's and img's mismatch problem immediately.
Thank you very much.

You can certainly define you own custom event and execute the aligning code when it occurs, but you still need a way to fire the event at appropriate time.
That can only happen during the ordinary execution flow of the program (not an option here) or in the handler for one of the existing events: if none of those events is consistently fired when the trigger condition occurs, then you're only left with timers.
I'd be happy to be wrong on this, tho'.
Consider requestAnimationFrame as an alternative to setInterval.

Related

How to check for the end of animate:flip in svelte

Does anybody know whether there is a way to check for the end of an animate:flip animation in a svelte component?
I don't see any events listed for it, no transition events work for it either.
I need to run a function once the flip animation completes to measure the containing element. Because the elements are animated, running the function before the animation completes leads to wrong size. I want to avoid "hackish" solutions with timeouts, etc. because I would need to run them in some afterUpdate which may be fired by other "updates" (not necessarily by adding/removing an element in the each block which is using flip), but it seems like there is no other way. Or is there? Thanks for reading.

Javascript addEventListener, skip to the latest event (of the same type, 'mousemove') only and handle the latest event only

I was wondering whether it's possible to jump to and handle the latest event, when you have several other events of the same type in the event loop in Javascript. I'm asking this because, I have made a Javascript program, which reports the 'mousemove' event every time the mouse pointer moves. The issue is that, for some reason, the event handling is not as fast as it should be, and my PC or code certainly isn't the problem.
I think that the issue is that web browsers limit the amount of 'mousemove' events that can be handled every frame. So, instead of handling all the events in a queue, I would like to just jump to the latest one and handle it and discard all the older events, instead of executing all of them one-by-one.
I'm not sure whether this is possible with Javascript, so that's why I'm asking for help.
Any help would be much appreciated... :-)
Here is my app. The problem is that if you try to move the window's title bar area up or down too fast, you will then lose the handle on the window itself. Now, that shouldn't happen in a modern GUI.
UPDATE on 'Debouncing' answer:
So, some people suggested that I should use a debouncing function. That wouldn't solve my problem. At its best, it would only delay what needs to be done. So, for example, if I have a pixel at (4,0) and if I then try to move it 3 pixels to the left, to (1,0), it would appear that in the normal fashion, but just a bit delayed. That is, if one assumes that (I'm making this up) a new 'mousemove' event on the queue is handled every 1 ms and the time it takes for the code to run for this example, is 0 ms, and in the code, we set the function with the code to execute 2 ms after the new event has been handled. This will then mean that indeed, only the latest event will be handled and the code will then run 2 ms after the latest event's listener function has started to run. So, to move a pixel 3 pixels to the left, this will still take 5 ms. That is still too slow. I actually need to update my Web app with coordinates of the mouse pointer, from where it actually is.
My solution:
Every time a 'mousemove' event's listener has started to execute, I should take the coordinates from the mouse pointer, but not from the event's .clientX and .clientY properties. I should take them from where they actually are on the page and not from where they were, once the 'mousemove' event has been registered and the event object that has been created at that time (which also doesn't have the up-to-date coordinates of the mouse pointer). I've searched for a solution on how to get the actual mouse pointer's coordinates without the actual event object, but so far, I have only read the responses about it being impossible.
This person has had the exact same problem as me. I'm now recording the global (the document's) position of the mouse, but the behavior of the app is still the same.
My solution to this problem:
I have moved the 'mousemove' and 'mouseup' events from the dragged object to the document itself.

jQuery updates DOM element and calculations simultaneously

So I have this page where on a button click, an image is added embellishments after performing various calculations on its meta-data which is stored as data-attributes.
Since the calculations can take a few seconds, I want to show an overlay on the image. So I do:
$(selectedImageId).addClass('loading');
//perform series of calculations here...
$(selectedImageId).removeClass('loading').addClass('calculated-embellishments');
I would imagine the script to first show the loading overlay on the image, then perform the lengthy calculations, then replace the overlay with the selected embellishment class. However it seems like the DOM is updated only at the end such that I never see the loading class, it just directly jumps from the plain image to the embellishment class after a few seconds.
If I add an alert('test') just before the last line which adds the embellishment then I can see the loading overlay on the image, but not otherwise.
How can I make this work the way I want it to, as I explained above?
Any pointers are very welcome!
What probably happens is that your "lengthy calculations" make the browser "hang" for processing, not having a chance to re-paint your image to reflect the newly added loading class.
Then once the calculations are done, your last instruction replaces the loading class by calculated-embellishments class, and now the browser has time to re-paint. But the loading class is already gone.
You have at least 3 workarounds to let the browser actually display your loading class before your calculations keep it busy:
Use a setTimeout as proposed by #csum, which is a bet on how much time the browser would need before doing the re-paint that will show your image with loading class. Hence the need to "test" different timeout values, but still without any guarantee as the result will depend on each client current performance (CPU, memory, current CPU load!).
Start your calculations in a callback of the "load" event of your overlay (if it is an image). But I am not sure if "load" event is a guarantee of the image (overlay) being painted (shown on screen).
Use 2 nested requestAnimationFrame to make sure at least 1 re-paint has occured, before you start your calculations.
You probably want to execute your calculations using setTimeout.
var WAIT = 10; // experiment with small values here
$(selectedImageId).addClass('loading');
setTimeout(function () {
//perform series of calculations here...
$(selectedImageId).removeClass('loading').addClass('calculated-embellishments');
}, WAIT);
If you want to play around with the timeout length, here is a jsfiddle with a demo using a similar situation: https://jsfiddle.net/v2n19w4d/1/ I find that a timeout length close to zero was not working.
This is really an issue with getting the DOM to update before it is blocked while doing your calculations. See jQuery append in loop - DOM does not update until the end, for example.

Why is the asyncQueue processed before watchers?

I have a situation in my AngularJS-based app where the visibility of element A results in element B being bigger or smaller in width (just due to how the element CSS styles are set up). The visibility of element A is toggled by binding to a boolean on the scope using ng-show="showRail". For reasons I don't need to go into here, when the visibility of element A is toggled, I need to get element B's new width. If I use $timeout to evaluate element B's width I get an accurate reading but it's too late (the next frame) and causes a flicker due to some rendering that must be done as a result. I understand that $evalAsync is intended to be best for executing some logic after the DOM has been updated but before the browser has rendered. So on the handler where I'm toggling the showRail boolean I'm running a scope.$evalAsync but it appears it's too early and element B has still not received its new width.
I went searching through Angular's $digest method and found that the asyncQueue is processed before watchers. This seems backward to me and seems to explain why element A's visibility hasn't changed before I try to retrieve element B's new width. I'm hoping someone can explain why this is the case and maybe it will lead me to a solution to my specific problem. Thanks.
Take a look at setImmediate:
https://github.com/YuzuJS/setImmediate
It's almost tailor-made for this kind of thing. There's nothing in Angular's core that lets you control the order in which these operations are performed, and the answer to "why" isn't going to help you solve your problem. But setImmediate can help you avoid the flicker and could be a 5-minute solution if it works...

Is it okay to use if-else inside jQuery .scroll() event handler?

I want to know if the use of if-else inside the jQuery .scroll() to compare positions with functions like:
offset = $(window).scrollTop()
and:
nameVar = $("#divID").offset()
These comparisons also adds css styles, inside the .scroll(), I have like four if-else statements.I am trying to find out if I will get performance issues when comparing DIVs' positions.
In my first tests the page load okay, but if I leave the page open I noticed that it is getting pretty laggy.
So:
Is it a better way to use if-else inside scroll()?
Am I using if-else wrong?
Is there another way to do it right?
The issue is that .scroll() events can be called very rapidly during a scroll operation. You either need to respond to a given event very quickly OR you need to defer handling of the scroll events (usually with a timer) until the user pauses with the scroll bar and stops moving it. Either one of those behaviors will prevent the laggy behavior.
A couple if statements take almost no time. But doing heavy duty selector queries or particularly making page changes that cause relayout and repainting can take significant CPU.
There is no right or wrong description for what exactly you can and can't do in a scroll handler and not see laggy behavior because it depends upon exactly what you're doing, what computer you're running it on, how much repaint and relayout operations you might cause by your actions, etc... The best you can do is either just decide to take the deferred route so you don't make your changes live until the user pauses the scroll or you have to test your code on all relevant platforms (particularly lower horsepower platforms) to see if your scroll handler is responsive enough.
You can see this post: More efficient way to handle $(window).scroll functions in jquery? for a couple methods of deferring the scroll processing until the user pauses including a jQuery plugin that makes this automatic.
Generally speaking finding the divs on the page will be much more computationally expensive that a couple if statements. So long as you cache lookups like so (outside of the scroll handler):
var $myDivOfAwesome = $('#awesomeDiv');
$(document).scroll(function() {
if ($myDivOfAwesome.position().top > 1337) {
// do stuff...
}
});
You should be fine.
If you still want to compare different snippets of code to determine what's faster, check out JSperf

Categories

Resources