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/
Related
I have a form element with an ng-change handler. I want to programmatically trigger the handler, but without direct inspection of scope. I want to do this because I'm writing a Chrome extension so I can't easily access '$scope' to get the handler.
I have tried the obvious choice of
$(element).triggerHandler('change')
but that doesn't seem to work. See example here: https://plnkr.co/edit/iaz7trxVT09XWBktGhE9?p=preview (in this example I'm logging some lines to console when the change handler runs, but clicking the button doesn't log those lines).
I tried a few other methods found in various threads here, such as trigger() or manual construction of event and fire with dispatchEvent but to no avail. I don't quite understand why the event handler isn't triggering. Can anyone help?
Well, apparently (according to docs), the model change will not be triggered when the value is not changed. An ugly (yet effective) workaround would be to actually change the value briefly:
var v = $('#testField1').val();
$('#testField1').val(0)
$('#testField1').triggerHandler('change');
$('#testField1').val(v)
$('#testField1').triggerHandler('change');
Of course this will trigger the event twice, if this is a problem you could for example use a known "magic value" (e.g. min negative integer) and ignore it.
Alternatively, I'm afraid there is no simple solution: you might need to access the scope / controller to invoke the function you want directly or meddle with angular's event handling.
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.
Is there a way to temporarily disable an event listener?
In my case, I have a third party library (not jQuery centric) that creates mouseover/mouseout events on an element using addEventListener/attachEvent.
Under certain circumstances another event fires on a different element and I need to disable those event listeners. My solution thus far has been to simply unbind the mouseover/mouseout. This usually works fine because that event generally causes the page to refresh.
However, every now and again an error can occur (think validation error) that results in the page not refreshing, and I need to re-attach the mouseover/mouseout event listeners.
Helpful information
It's probably worth mentioning that because the mouseover/mouseout event listeners are created and attached within a third party library I cannot simply assign the event to a variable and bind/unbind it in that manner (which AFIK is the best way to do this).
Update
I had originally asked
Is there a way in jQuery to get the event listeners already assigned to an object?
I have since found out it is impossible to access events assigned by addEventListener/attachEvent: Access events added with attachEvent() / addEventListener() in JavaScript
jQuery uses data to store events internally, so you can use it to get all of the event handlers for an object:
$("#foo").data("events")
You can then remove a specific handler by using unbind:
$("#foo").unbind('click', $("#foo").data("events").click[42]);
Unfortunately, you can't access them. At best, you can remove event listeners using W3C's removeEventListener (docs) and/or Microsofts detachEvent (docs). Once the listener is removed, however, it's gone for good.
There's one caveat with removeEventListener, in that if the event was registered twice, once indicating to capture, and once indicating not to capture, you must remove it twice; once for each case.
To learn more about capturing and not capturing, see the W3C spec.
If you want to temporarily disable an event handler being run, why not just add escape code to the function?
like so:
$('#button').click(function(){
var clicked_element = $(this);
if(elem.hasClass('event-click-disabled'))
{
// logging code so we know exactly what events are being skipped
console.info(
'The click event on following element was skipped',
clicked_element
);
return;
}
alert('Button clicked');
});
Then if you want to disable an event on a specific element, just call
element.addClass('event-click-disabled');
The event handler is still run, but it will return immediately.
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.
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).