In jQuery how can you attached change events to regular objects - javascript

How can you bind a change (or add/remove) event to a object or collection of objects to see see if it has changed using jQuery. I have looked around but can't seem to find much on the subject, yet it seems like a fairly standard use case.

You can bind an event handler for any event you like to any element you like, but it will only be called if the event actually is triggered. As there is no change event defined for anything other than form fields, nothing will happen unless you trigger the event yourself.

As Guffa pointed out, there is no change event in regular object, but input, textarea, and select. So you have to make your own content-change event. This article has how-to. http://james.padolsey.com/javascript/monitoring-dom-properties/ Read the last part.

Related

Understanding JavaScript events and applying jQuery events/plugins?

I have a bunch of jQuery functions that use the .on event because I want to prevent reapplying the event to the same element.
However some people created plugins (e.g. Owl Carousel) and I don't know how to prevent this event from reapplying.
Currently I am using the plugin as following:
HTML:
<div class="init-owl"></div>
JS:
$('.init-owl').owlCarrousel();
$('.init-owl').removeClass('init-owl');
Whenever a second element gets loaded in the page using e.g. AJAX, I want to only apply the event to the newly added element.
Question: What I dont understand is how the event stays stuck to the DOM?
To better grip what is happening, I was wondering how an event in general gets connected to the DOM?
Is there a better way to prevent events applying to the same DOM elements?
If I wish to write my own plugins, I would need to know how javascript works, right?
Question: What I dont understand is how the event stays stuck to the DOM?
Once an event is bound to an object, it gets removed when the object gets garbaged collected. So if a DOM element is really gone and there are no references to it, then the event will get swept up as well.
To better grip what is happening, I was wondering how an event in general gets connected to the DOM?
I'm not sure how far you want to dive into this. Maybe it would help if you stop thinking about the DOM and events and look more at just regular events bound to objects. Basically an object does something, or something is done to it and some underlying code (in the browser's code in this case) triggers an event on that object. The implementations between browsers may differ, but basically you will have a key or string (the event name) that maps to a collection of functions. When you add an event listener, you add another function to this collection. Then when something triggers that event, it iterates through the functions and executes them. That's a real basic explanation, but I hope it makes things a little more clear.
Is there a better way to prevent events applying to the same DOM elements?
Make sure you don't add the events again by writing better code. I don't believe you can dive down into an element and look to see if it has events bound to it. You can however change your jQuery selector to only target newly added elements. If you have to, mark the elements that you have added events to with a class or something. Then you could target your elements by doing $('.init-owl:not(.already-bound)'). There is a better solution to your problem, I can assure you, but we might need more context and code to see a better way to help you.
EDIT:
You can look into jQuery's off() function to remove events. That may help you too.

How jQuery's .on/.live works? [duplicate]

I'm curious to know the differences between the bind and live functions.
To me they seem to be almost identical.
I read the benefits of live/bind methods, but it didn't tell me about the differences...
Thanks!
In short: .bind() will only apply to the items you currently have selected in your jQuery object. .live() will apply to all current matching elements, as well as any you might add in the future.
The underlying difference between them is that live() makes use of event bubbling. That is, when you click on a button, that button might exist in a <p>, in a <div>, in a <body> element; so in effect, you're actually clicking on all of those elements at the same time.
live() works by attaching your event handler to the document, not to the element. When you click on that button, as illustrated before, the document receives the same click event. It then looks back up the line of elements targeted by the event and checks to see if any of them match your query.
The outcome of this is twofold: firstly, it means that you don't have to continue reapplying events to new elements, since they'll be implicitly added when the event happens. However, more importantly (depending on your situation), it means that your code is much much lighter! If you have 50 <img> tags on the page and you run this code:
$('img').click(function() { /* doSomething */ });
...then that function is copied into each of those elements. However, if you had this code:
$('img').live('click', function() { /* doSomething */ });
...then that function is stored only in one place (on the document), and is applied to whatever matches your query at event time.
Because of this bubbling behaviour though, not all events can be handled this way. As Ichiban noted, these supported events are click, dblclick mousedown, mouseup, mousemove, mouseover, mouseout, keydown, keypress, keyup.
.bind() attacheds events to elements that exist or match the selector at the time the call is made. Any elements created afterwards or that match going forward because the class was changed, will not fire the bound event.
.live() works for existing and future matching elements. Before jQuery 1.4 this was limited to the following events: click, dblclick mousedown, mouseup, mousemove, mouseover, mouseout, keydown, keypress, keyup
Bind will bind events to the specified pattern, for all matches in the current DOM at the time you call it. Live will bind events to the specified pattern for the current DOM and to future matches in the DOM, even if it changes.
For example, if you bind $("div").bind("hover", ...) it will apply to all "div"s in the DOM at the time. If you then manipulate the DOM and add an extra "div", it won't have that hover event bound. Using live instead of bind would dispatch the event to the new div as well.
Nice read on this: http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/
Is nowadays (since jQuery 1.7) deprecated using the .on() function - http://api.jquery.com/on/
imagine this scenario:
i have several <img> elements.
$('img').bind('click', function(){...});
add some extra images (using get(), or html(), anything)
the new images don't have any binding!!
of course, since the new images didn't exist when you did the $('img')... at step 2, it didn't bind the event handler to them.
now, if you do this:
i have several <img> elements.
$('img').live('click', function(){...});
add some extra images (using get(), or html(), anything)
the new images do have the binding!!
magic? just a little. in fact jQuery binds a generic event handler to another element higher in the DOM tree (body? document? no idea) and lets the event bubble up. when it gets to the generic handler, it checks if it matches your live() events and if so, they're fired, no matter if the element was created before or after the live() call.
In adition to what they said, I think it's best to try to stick to bind when/where you can and use live only when you must.
All these jQuery methods are used for attaching events to selectors or elements. But they all are different from each other.
.bind(): This is the easiest and quick method to bind events. But the issue with bind() is that it doesn’t work for elements added dynamically that matches the same selector. bind() only attach events to the current elements not future element. Above that it also has performance issues when dealing with a large selection.
.live(): This method overcomes the disadvantage of bind(). It works for dynamically added elements or future elements. Because of its poor performance on large pages, this method is deprecated as of jQuery 1.7 and you should stop using it. Chaining is not properly supported using this method.
Find out more here
I wanted to add to this after having to debug a bit due to my own silliness. I applied .live() to a class of button on my page, assuming that it would just render out the correct ID I was trying to pass on the query string and do what I wanted to do with the ajax call. My app has dynamically added buttons associated with an inventory item. For instance, drill down categories to the 'COKE' button to add a coke to your order. Drill down from the top again, and add 'BUDLITE' - each time I wanted those items to be entered into a table via an AJAX call.
However, since I bound .live() to the entire class of buttons, it would remember each ajax call I had made and re-fire it for each subsequent button! It was a little tricky because I wasn't exactly clear on the difference between bind and live (and the answer above is crystal about it), so I figured I'd put this here just in case somebody was doing a search on this stuff.
There is a way to get the live effect but its kind of nasty.
$(this).unbind('mouseout').bind('mouseout',function(){
});
this will clear the previous and reset the new. It has seemed to work fine for me over time.
Difference between live and livequery is discussed here .

jQuery design mistake or historical reason?

Today is jQuery day. I found this in the documentation:
blur() Returns: jQuery Triggers the blur event of each matched element.
blur(fn) Returns: jQuery Bind a function to the blur event of each matched
element.
In other words, the behavior of the function is totally different depending if it accepts or not an argument.
Is this a design mistake or there's a historical reason for this ?
Keep into account that I know nothing about javascript nor jQuery, and I am trying to get a feeling of it.
That's how jQuery is designed, it's the same for all events. To add a handler to an element you use e.blur(function(){...}), and to trigger the event, you use e.blur(). It kind of makes sense, you just have to get used to it.
Definitely not a design mistake, because it goes for multiple events, such as click, however you should be using .trigger('blur')
It makes sense because .blur() or .click() by nature invokes the event handlers attached to the specific event, and all .blur(fn) does is bind it to .bind('event') where behind the scenes it registers the event handlers.

which HTML element lost focus?

in javascript, when I receive a focus event, how can I work out which element has lost focus? I'm trying to avoid having to put an onblur event handler on all elements within my web page.
#pbrodka: the target/srcElement property would refer to the element with focus for onfocus events
offhand I can't see a way to get this short of onblur, or if the set of objects you care about all have focus methods you could store a reference to that object instead. It's also possible event bubbling could get you out of jail
this all feels like a bit of a code smell though - perhaps you need to describe the problem in more detail
Difficult this. You cannot use event delegation to find out which control last produced a blur as focus/blur do not bubble up. There have been some attempts to 'fix' this but they are buggy and not resiliant cross browser.
Could I ask you why do you need this information as maybe there is an alternative solution.
Unfortunately, the onblur event doesn't bubble, otherwise you could have handled it at the window level to always know when an element lost focus.
As things are, I do believe it will be hard to do without, as you say, adding an onblur event handler to all elements (a truly nasty solution ;-).
It is possible to delegate the focus and blur events, if you follow PPK's advice, here:
http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
The most simple solution is to write a function that walks all forms and then all elements within the form and installs an onblur handler for each (which will probably call some global function). This handler will get an event and this event will contain the info you seek.
This way, you just have to call this method once in body.onload and it will work no matter how complex your document is.
The only drawback is that you will need to call it if you dynamically add forms to your current document. In this case, you must make sure not to install the handler again (or you will get spurious duplicate events).

JQuery detecting Programatic change event

If i do jQuery(expr).change( function), then I can get an event function to fire when the user makes a change to the value.
Is it possible to get this to fire if it's changed programatically, ie if I call jQuery(expr).val("moo").
or if some Plain old JavaScript changes it's value?
Thanks for any help.
After you've changed the value, you can fire the event yourself, and thus calling all the 'onchange' handlers.
jQuery('#element').change();
Changing the value directly in JS doesn't hook into anything which jQuery can listen for to trigger the change event. Like Sander says, you can fire the event handler yourself. If you don't have control over other code modifying these values and that isn't an option, you're kind of out of luck. The only other option which might work would be to have an observer watch the value on an interval using setTimeout, which is really messy and probably not a good idea.
jQuery v1+ supports the programmatic triggering of handlers - I have used this method as opposed to the .change() method as it allows for multiple other handlers to be fired if needed (e.g. some custom handlers). API Documentation is at: http://api.jquery.com/trigger/

Categories