live('click') and performance - javascript

I have a grid and there is a column which contains <a> anchor tag with some additional information in <data-..> tag and has a class name <class='myspeciallink'>. And in my unobtrusive JS script I select all the elements with that class name and apply live('click'). I need that to be live() because the grid gets generated in the runtime.
What happens inside the live('click') handler? I use that additional data and add a <div> to the page based on that data. Which in its turn used to generate jQuery UI dialog. It works great on my computer.
But! How could that work in real-world? Should I be bothered about possible performance implications? I feel that applying live() on more than a dozen elements instantaneously
would affect the performance. Especially with rather complicated handler like mine - it needs to get the data, parse the data, create a div, apply a dialog and etc.
Does that smell like a bad design? Could you suggest a different approach or my concerns are unfounded? Can I use some sort of a profiler tool to find the bottlenecks in my javascript?
UPD: Still nobody suggested any profiling tool. firebug and chrome dev tools are good, but maybe there is something even better?

live("click") is actually better up-front from a performance standpoint: Instead of binding an event handler to each matched element, you're applying a single event handler which waits for events to bubble up and then sees if the element that triggered the event matches the selector .live was called on.
Compare this to $('selector').click(...) which does loop over each element and bind a new event handler. live('click') has no additional overhead regardless of how many page elements match its selector. Depending on how many elements your selector matches, using .live can avoid a delay of up to a few seconds during the initial load of each page.
However, the event handler must check each event which bubbles up against its selector, to see if there is a match. This is going to add a small amount of overhead to every click event, but chances are very good that your users will not notice the difference.

Peter bailey also has a nice post about this: Performance difference between jQuery's .live('click', fn) and .click(fn)

Related

Alternative to Falsely Triggering an Event

TLDR Below
JS Fiddle To Demo
I've been really involved in recreating the tools that are foundations of premiere JS Libraries to better improve my skills. Currently I'm working on functional data-binding a la Angular.
The idea of data-binding is to take data and bind it to elements so that if manipulated all elements subscribed will change accordingly. I've gotten it to work but one thing I hadn't considered going into it was the issue with innerHTML vs value. Depending on the element you need to change one or the other( in the demo above you'll see that I needed to specifically single out the button element in a conditional statement because it has both, but that's kind of a fringe case )
The issue is that in order to capture a SPAN tag update I needed to trigger an event to happen, and the easiest one to manipulate for Text Boxes/Textareas was 'keyup'.
In my function then, if you pass in an element with no value property we assume you're going to be updating innerHTML, and we setup an observer to determine if the element ever mutates, and if it ever does, the observer will emit a 'keyup' event.
if (watchee.value == void(0)) {
var keyUpEvent = new Event('keyup');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
watchee.dispatchEvent(keyUpEvent);
});
});
observer.observe(watchee, {
childList: true
});
}
Now it may just be my paranoia, but it seems like I might be tunneling into a can of worms by faking 'keyup' on an element that doesn't natively have that support.
TLDR:
I'm curious if there's an alternative way to make, a.e. a span tag reactive other than faking a 'keyup'/'keydown'/'change' event? For instance, is there a way that I can make my own pure event(by pure I mean not reliant on other events) that checks if innerHTML or value has changed and then performs a function? I know that this is probably possible with a timer, but I feel like that might hinder performance.
EDIT: just an aside. In the demo the function called hookFrom works by taking a DOM node and returning a function that will take the receiving dom node and continues to return a function that will take additional receiving dom nodes. :
hookFrom(sender)(receiver);
hookFrom(sender)(receiver)(receiver2);
hookFrom(sender)(receiver)(receiver2)(receiver3)(receiver4)...(receiver999)...etc
JS Fiddle To Demo (same as above)
There is nothing inherently wrong with creating a similar event on a DOM node that doesn't natively have that functionality. In fact this happens in a lot of cases when trying to polyfill functionality for separate browsers and platforms.
The only issue with doing this sort of DOM magic is that it can cause redundancy in other events. For instance the example given in this article: https://davidwalsh.name/dont-trigger-real-event-names shows how a newly minted event using the same event name can cause problems.
The advice is useful, but negligible in this specific case. The code adds the same functionality between text boxes, divs, spans, etc... and they are all intentionally handled the same way, and if the event would bubble up to another event, it would be intentional and planned.
In short: There is a can of worms that one can tunnel into while faking already explicitly defined event names, but in this case, the code is fine!

Unbind inline javascript events from HTML elements in memory

How do I completely unbind inline javascript events from their HTML elements?
I've tried:
undelegating the event from the body element
unbinding the event from the element
and even removing the event attribute from the HTML element
To my surprise at least, only removing the onchange attribute (.removeAttr('onchange')) was able to prevent the event from firing again.
<input type="text" onchange="validateString(this)"></input>
I know this is possible with delegates and that's probably the best way to go, but just play along here. This example is purely hypothetical just for the sake of proposing the question.
So the hypothetical situation is this:
I'm writing a javascript validation library that has javascript events tied to input fields via inline HTML attributes like so:
<input type="text" onchange="validateString(this)"></input>
But, I'd like to make the library a little better by unbinding my events, so that people working with this library in a single-page application don't have to manage my event handlers and so that they don't have to clutter their code at all by wiring up input events to functions in my hypothetical validation library... whatever. None of that's true, but it seems like a decent usecase.
Here's the "sample" code of Hypothetical Validation Library.js:
http://jsfiddle.net/CoryDanielson/jwTTf/
To test, just type in the textbox and then click elsewhere to fire the change event. Do this with the web inspector open and recording on the Timeline tab. Highlight the region of the timeline that correlates to when you've fired the change event (fire the change event multiple times) and you'll see the event listeners (in the window below) increase by 100 on each change event. If managed & removed properly, each event listener would be properly removed before rendering a new input, but I have not found a way to properly do that with inline javascript events.
What that code does is this:
onChange, the input element triggers a validation function
That function validates the input and colors the border if successful
Then after 1 second (to demonstrate the memory leak) the input element is replaced with identical HTML 100 times in a row without unbinding the change event (because I don't know how to do that.. that's the problem here). This simulates changing the view within a single-page app. This creates 100 new eventListeners in the DOM, which is visible through the web inspector.
Interesting Note. $('input').removeAttr('onchange'); will actually prevent the onchange event from being fired in the future, but does not garbage collect the eventListener/DOM stuff that is visible in the web inspector.
This screenshot is after change event fires 3 times. Each time, 100 new DOM nodes are rendered with identical HTML and I've attempted to unbind the onchange event from each node before replacing the HTML.
Update: I came back to this question and just did a quick little test using the JSFiddle to make sure that the answer was valid. I ran the 'test' dozens of times and then waited -- sure enough, the GC came through and took care of business.
I don't think you have anything to worry about. Although the memory can no longer be referenced and will eventually be garbage collected, it still shows up in the Web Inspector memory window. The memory will be garbage collected when the GC decides to garbage collect it (e.g., when the browser is low on memory or after some fixed time). The details are up to the GC implementer. You can verify this by just clicking the "Collect Garbage" button at the bottom of the Web Insepctor window. I'm running Chrome 23 and after I enter text in your validation box about 5 or 6 times, the memory usage comes crashing down, apparently due to garbage collection.
This phenomenon is not specific to inline events. I saw a similar pattern just by repeatedly allocating a large array and then overwriting the reference to that large array, leaving lots of orphaned memory for GC. Memory ramps up for a while, then the GC kicks in and does its job.
My first sggestion would have been to use off('change') but it seems you've already tried that. It's possible that the reason it's not working is because the handler wasn't attached with .on('change'). I don't know too much about how jQuery handles listener like this internally, but try attaching with .on('change', function ()... or .bind('change', function ()... instead.

necessary to remove event handlers by hand?

Morning,
When using Element#observe(), is it necessary to call Element#stopObserving() to completely get rid of the event handler?
Or will some inbuilt mechanism realize that the handler is no longer necessary when the Element gets removed in any way (.update() on a parent, not just .remove()) ?
Updating large dynamic lists with several bindings per entry every now and then. Drawbacks when using something like
ul.update(''); data.each(..
ul.insert(X); X.bind(..); ..);
Thanks!
If an element is no longer part of the DOM then garbage collection will probably deal with it's handlers, but that will depend on the browser.
I would suggest you not worry about what is out of your control and look at using Event.on() instead.

Adding and removing inputs via jQuery's remove(), but page gets slow, how to free memory?

I'm dynamically adding a lot of input fields through jQuery but the page gets really slow when reaching 200+ inputs (think of the page like a html excel sheet). This is fine really because this scenario is not very common. However, when I dynamically remove the input fields from the page using jQuery's htmlObj.remove() function, the page is still slow as if there were hundreds of inputs still there. Is there any way to explicitly free memory in jQuery/javascript?
My experience with this is from using Firefox. When using Internet Explorer, the page is really slow from the start but that's a whole different story.
The technique I'm using is called event delegation as it's supposed to be the least memory resourceful approach, compared to having all handlers explicitly bound to every object on the page.
Sadly, blur and focus events do not work with event delegation and therefore I need to bind these to every input. This could possibly be the memory hog here. Also, in Firefox it seems I can't use checkboxes for 'changed' or 'key[down|up]' events in event delegation as these checkbox events do not bubble up to the document. Here binding explicitly too.
Anyone can share some experience with this? Can't really show a demo right now as the site has not been launched yet.
Thx.
read this, I'm sure it will help.

How to keyboard down or up between dropdown "options"?

I have a custom built ajax [div] based dynamic dropdown.
I have an [input] box which; onkeyup, runs an Ajax search which returns results in divs and are drawn back in using innerHTML. These divs all have highlights onmouseover so, a typical successful search yields the following structure (pardon the semi-code):
[input]
[div id=results] //this gets overwritten contantly by my AJAX function
[div id=result1 onmouseover=highlight onclick=input.value=result1]
[div id=result2 onmouseover=highlight onclick=input.value=result2]
[div id=result2 onmouseover=highlight onclick=input.value=result2]
[/div]
It works.
However, I'm missing the important functions behind regular HTML elements. I can't keyboard down or up between "options".
I know javascript handles keyboard events but; I haven't been able to find a good guide. (Of course, the follow-up question will end up being: can I use <ENTER> to trigger that onclick event?)
What you need to do is attach event listeners to the div with id="results". You can do this by adding onkeyup, onkeydown, etc. attributes to the div when you create it or you can attach these using JavaScript.
My recommendation would be that you use an AJAX library like YUI, jQuery, Prototype, etc. for two reasons:
It sounds like you are trying to create an Auto Complete control which is something most AJAX libaries should provide. If you can use an existing component you'll save yourself a lot of time.
Even if you don't want to use the control provided by a library, all libraries provide event libraries that help to hide the differences between the event APIs provided by different browsers.
Forget addEvent, use Yahoo!’s Event Utility provides a good summary of what an event library should provide for you. I'm pretty sure that the event libraries provided by jQuery, Prototype, et. al. provide similar features.
If that article goes over your head have a look at this documentation first and then re-read the original article (I found the article made much more sense after I'd used the event library).
A couple of other things:
Using JavaScript gives you much more control than writing onkeyup etc. attributes into your HTML. Unless you want to do something really simple I would use JavaScript.
If you write your own code to handle keyboard events a good key code reference is really handy.
Off the top of my head, I would think that you'd need to maintain some form of a data structure in the JavaScript that reflects the items in the current dropdown list. You'd also need a reference to the currently active/selected item.
Each time keyup or keydown is fired, update the reference to the active/selected item in the data structure. To provide highlighting information on the UI, add or remove a class name that is styled via CSS based on if the item is active/selected or not.
Also, this isn't a biggy, but innerHTML is not really standard (look into createTextNode(), createElement(), and appendChild() for standard ways of creating data). You may also want to see about attaching event handlers in the JavaScript rather than doing so in an HTML attribute.

Categories

Resources