I'm currently developing an Angular2 application and am facing an issue regarding property changes and life cycle events.
Example
Let's say that I have a simple template that is being rendered based on a property. I would like #container to stay hidden until the rendering is done, then add the visible class to it to have it show up.
<div id="container">
<p *ngFor="let value in values">
{{value}}
</p>
</div>
The problem
The problem is that .visible defines a transition, too, and the browser simply cannot handle Angular's rendering and the transition at the same time, so it quite simply stops for a moment, and then the #container just snaps in.
What I have tried
Setting a long enough time for the transition solves the problem, but I wouldn't want to change that.
I have also looked into Angular's life cycle hooks, but none of them seems to match my specific need.
Goals
I would like to be notified once Angular has finished rendering the contents of #container, so that I can add the visible class while no other work is being done, and have a smooth transition.
Any and all help is greatly appreciated.
Mark Rajcok's comment got me thinking and I have looked up different methods to take action at the next possible moment, including setTimeout, requestAnimationFrame, and finally setImmediate.
I have decided to settle for setImmediate as it seems to be the most straightforward way to defer an action to the next browser tick.
Be aware, that setImmediate is merely a proposal right now, and I am only able to use it because core-js implements it already. It might not even become a standard in the future.
https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate
Note: This method is not expected to become standard, and is only implemented by recent builds of Internet Explorer and Node.js 0.10+. It meets resistance both from Gecko (Firefox) and Webkit (Google/Apple).
Related
I have to render a lot of divs into DOM. So, what I did is I render the first 5 elements into the DOM first after that I render every 10 divs with 300ms interval period.
The problem is when I change into display: block I need to change something in the component. So, I try to use didRender hook for that.
Code is below
didRender() {
if(this.element.offsetParent) {
this.set('myvar', true);
}
}
But it's not working perfectly. Anyone please suggest me which is the best way to do this.
_Thanks in Advance.
It's hard to guess your use case from the question but I assume that it's about rendering a very large list of items without causing performance issues. The ember ecosystem provides bulletproofen addons to do so. The most established ones I'm aware of are ember-collection and ember-large-list. I would recommend to use one of these if they suit your requirements. Reimplementing something similar will be a lot of work. Rendering new items on a timeout basis would not scale well as it doesn't take workload of browser into account.
For your concrete question: Ember does not provide a way to listen to CSS changes. You should execute custom logic at the same place as in which you are mutating the property which triggers the CSS change. If it has to be run after render, you need to deal with Ember's runloop.
I am trying to improve performance of the select2 v3.4.8 library in IE8.
Essentially, I have narrowed the problem down to the call from the SingleSelect2's opening method to the parent AbstractSelect2's opening method. The method call I am speaking of is this one:
this.parent.opening.apply(this, arguments);
I have seen this call take upwards of 5 seconds to complete. In some instances, it has taken up to 10 seconds to open the dropdown in IE8.
I've made some performance improvements already. For example, rather than constantly adding the:
<div id="select2-drop-mask" class="select2-drop-mask"></div>
to the DOM programmatically, I just added it directly to the markup and set it's display:none. This saves quite a number of cycles because apparently, adding elements to the DOM in IE8 is expensive to do from Javascript.
But I still want to get more performance improvements than this. We have only increased performance by about 10-20% by making this change.
Does anyone have any suggestions for me?
We've already cached the data to display in the dropdown on the client on page load. So, there are zero server calls being made when the dropdown is opening. The performance bottleneck is entirely inside the select2 library itself.
Unfortunately, we are unable to upgrade our select2 library. Doing so would be at least an 8-Point User Story, so it's prohibitive at this time for us to undertake an upgrade.
Thanks to anyone who's able to help!
-classTemplateT
I need an efficient mechanism for detecting changes to the DOM. Preferably cross-browser, but if there's any efficient means which are not cross browser, I can implement these with a fail-safe cross browser method.
In particular, I need to detect changes that would affect the text on a page, so any new, removed or modified elements, or changes to inner text (innerHTML) would be required.
I don't have control over the changes being made (they could be due to 3rd party javascript includes, etc), so it can't be approached from this angle - I need to "monitor" for changes somehow.
Currently I've implemented a "quick'n'dirty" method which checks body.innerHTML.length at intervals. This won't of course detect changes which result in the same length being returned, but in this case is "good enough" - the chances of this happening are extremely slim, and in this project, failing to detect a change won't result in lost data.
The problem with body.innerHTML.length is that it's expensive. It can take between 1 and 5 milliseconds on a fast browser, and this can bog things down a lot - I'm also dealing with a large-ish number of iframes and it all adds up. I'm pretty sure the expensiveness of doing this is because the innerHTML text is not stored statically by browsers, and needs to be calculated from the DOM every time it is read.
The types of answers I am looking for are anything from the "precise" (for example event) to the "good enough" - perhaps something as "quick'n'dirty" as the innerHTML.length method, but that executes faster.
EDIT:
I should also point out that whilst it would be "nice" to detect the precise element that has been modified, it is not an absolute necessity - just the fact that there has been any change would be good enough. Hopefully this broadens people's responses. I'm going to investigate Mutation Events, but I still need a fallback for IE support, so any whacky, creative, outside-of-the-square ideas would be very welcome.
To bring this up to date, the DOM4 standard does away with Mutation Events and replaces them with Mutation Observers: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
http://www.quirksmode.org/js/events/DOMtree.html
jQuery now supports a way to attach events to existing and future elements corresponding to a selector: http://docs.jquery.com/Events/live#typefn
Another interesting find - http://james.padolsey.com/javascript/monitoring-dom-properties/
Mutation events are the W3 recommendation of what you are looking for..
Not sure if they are supported all around.. (IE will most likely not support them..)
You could try using the DOMNodeInserted and DOMNodeRemoved events. Acording to Quirksmode, they kind of work in most browsers, with the notable exception of IE...
http://www.quirksmode.org/dom/events/index.html
I have recently written a plugin that does exactly that - jquery.initialize
You use it the same way as .each function
$(".some-element").initialize( function(){
$(this).css("color", "blue");
});
The difference from .each is - it takes your selector, in this case .some-element and wait for new elements with this selector in the future, if such element will be added, it will be initialized too.
In our case initialize function just change element color to blue. So if we'll add new element (no matter if with ajax or even F12 inspector or anything) like:
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
Plugin will init it instantly. Also plugin makes sure one element is initialized only once. So if you add element, then .deatch() it from body and then add it again, it will not be initialized again.
$("<div/>").addClass('some-element').appendTo("body").detach()
.appendTo(".some-container");
//initialized only once
Plugin is based on MutationObserver - it will work on IE9 and 10 with dependencies as detailed on the readme page.
jQuery Mutate does this too, by default it supports like height, width, scrollHeight etc... but it also can be extended with a little bit of extra code to add new events like see if text has changed etc...
http://www.jqui.net/jquery-projects/jquery-mutate-official/
Hope it helps
This is largely a theoretical question, for which I do have a practical purpose. I first am looking for some conceptual answers before diving into practice, as perhaps the idea itself does not make sense.
Imagine a slideshow that is entirely javascript-based. Users see a large image on their screen and click to move to the next large image. Upon clicking, the next image is loaded and inserted into the DOM, replacing the previous one.
I recently learned that prefetching directives can help in speeding up the loading of resources that are very likely to be used next. Note that I said resources, not pages. The slideshow is a single page.
In an image slideshow, it is very obvious that it is likely that the next image is needed, thus if image1 is on screen, I could dynamically add this to the DOM:
<link rel="prefetch" href="http://img.mysite.com/img2.jpg">
My questions regarding this idea:
Would it work at all? Do browsers accept this directive when it is dynamically inserted in the DOM at run-time? Would it trigger the prefetch?
Is there a possibility of timing conflicts, where if prefetching would indeed work, it did not finish in time before the use does the "load" without prefetching? Obviously this can happen, but will it have unwanted side effects?
Will specific events such as image onload still work correctly, or are they never triggered in the case of a successful prefetch (assuming it works at all)?
I did a lot of searching but I am unable to find answers on this specific situation of dynamically injected prefetch hints.
onload always gets triggered, even if the image is coming from cache. You do not have to worry about timing effects or race conditions, any such behavior would be a browser bug.
As mentioned in comments, rel=prefetch is not the only way of achieving pre-fetching. It works though even when dynamically inserted into the DOM. After all, you could fetch the image without the prefetch attribute and hide it.
Showing then hiding animated indicator / spinner gifs are a good way to show a user that their action has worked and that something is happening while they wait for their action to complete - for example, if the action requires loading some data from a server(s) via AJAX.
My problem is, if the cause of the slowdown is a processor-intensive function, the gif freezes.
In most browsers, the GIF stops animating while the processor-hungry function executes. To a user, this looks like something has crashed or malfunctioned, when actually it's working.
JSBIN example
Note: the "This is slow" button will tie up the processor for a while - around 10 seconds for me, will vary depending on PC specs. You can change how much it does this with the "data-reps" attr in the HTML.
Expectation: On click, the animation runs. When the process is finished, the text changes (we'd normally hide the indicator too but the example is clearer if we leave it spinning).
Actual result: The animation starts running, then freezes until the process finishes. This gives the impression that something is broken (until it suddenly unexpectedly completes).
Is there any way to indicate that a process is running that doesn't freeze if JS is keeping the processor busy? If there's no way to have something animated, I'll resort to displaying then hiding a static text message saying Loading... or something similar, but something animated looks much more active.
If anyone is wondering why I'm using code that is processor-intensive rather than just avoiding the problem by optimising: It's a lot of necessarily complex rendering. The code is pretty efficient, but what it does is complex, so it's always going to be demanding on the processor. It only takes a few seconds, but that's long enough to frustrate a user, and there's plenty of research going back a long time to show that indicators are good for UX.
A second related problem with gif spinners for processor-heavy functions is that the spinner doesn't actually show until all the code in one synchronous set has run - meaning that it normally won't show the spinner until it's time to hide the spinner.
JSBIN example.
One easy fix I've found here (used in the other example above) is to wrap everything after showing the indicator in setTimeout( function(){ ... },50); with a very short interval, to make it asynchronous. This works (see first example above), but it's not very clean - I'm sure there's a better approach.
I'm sure there must be some standard approach to indicators for processor-intensive loading that I'm unaware of - or maybe it's normal to just use Loading... text with setTimeout? My searches have turned up nothing. I've read 6 or 7 questions about similar-sounding problems but they all turn out to be unrelated.
Edit Some great suggestions in the comments, here are a few more specifics of my exact issue:
The complex process involves processing big JSON data files (as in, JS data manipulation operations in memory after loading the files), and rendering SVG (through Raphael.js) visualisations including a complex, detailed zoomable world map, based on the results of the data processing from the JSON. So, some of it requires DOM manipulation, some doesn't.
I unfortunately do need to support IE8 BUT if necessary I can give IE8 / IE9 users a minimal fallback like Loading... text and give everyone else something modern.
Modern browsers now run CSS animations independently of the UI thread if the animation is implemented using a transform, rather than by changing properties. An article on this can be found at http://www.phpied.com/css-animations-off-the-ui-thread/.
For example, some of the CSS spinners at http://projects.lukehaas.me/css-loaders/ are implemented with transforms and will not freeze when the UI thread is busy (e.g., the last spinner on that page).
I've had similar problems in the past. Ultimately they've been fixed by optimizing or doing work in smaller chucks responding to user actions. In your case different zoom levels would trigger different rendering algorithms. You would only process what the user can see (plus maybe a buffer margin).
I believe the only simple workaround for you that would be cross-browser is to use setTimeout to give the ui thread a chance to run. Batch up your work into sets of operations and chain them together using several setTimeout calls. This will slow down the total processing time, but the user will at least be given feedback. Obviously this suggestion requires that your processing can be easily sectioned off. If that is the case you could also consider adding a progress bar for improved UX.