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).
Related
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.
I want a generic (cross browser) way to get the browser to execute the default action for an object for a specified event preferably without getting any attached listeners to fire.
This kind of question has been asked before but in the context of already being in an event, &/or strictly talking about synchronously holding off the default action before letting it happen later.
Basically, let's say you have an DOM element (you don't know which) variable, and you want to invoke a click, such that if it were an anchor, it'd follow its href, if it were an input[type="submit"] it would submit the form.
But without firing that element's listeners for the click event (which may be prone preventDefault()s in the listeners).
For those that need a reason to answer questions; you may want to do it if you're implementing something like dispatchEvent() for browsers that only have fireEvent().
Both functions return true if the default wasn't 'prevented', but only dispatchEvent() actually follows through and invokes the default.
As a side question, jQuery's trigger() is meant to do this (although after firing the listeners) and be cross-browser, maybe the solution is there? As nice as jQuery is I'd like to know the vanilla methods it is calling (if it [this particular feature] indeed works on things like IE8).
It appears that, at least for the click event, you can call .click() on the element in these browsers.
This will have the element enact the default (as well as calling all listeners and the .onclick value, if defined).
I don't know of any other defaults on DOM elements, would scroll need to be accounted for? Keypress? Maybe those exist as functions too, but I haven't tested.
When I did test .click(), I noticed it obeyed any of the listeners returning false and did not fire the default, and the event did bubble (a listener I had on document fired too!).
There may be no other alternative (I.e. calling the default directly, avoiding the listeners). And as for passing it an event object, the browser in question has the single global event thing going on, so maybe you can manipulate that and it wont have changed when executing .click().
Adding as I find more information in my travels :)
Furthermore, there is an doScroll() function, but I think it would be really hard to translate a given event into the string accepted by this method
I have a click event created by plugin and after I load $.ajax and only replaced(update) the area where contain the click event, the event will lost.
<span ref='B'><span ref='A'></span></span>
//click event is on A, but I replaced the html inside of B to <span ref='A'></span>;
its update, so the replaced html are the same.
I read many related problems, I found the solution are
.live() // will not work
.delegate(), // work
.on(), // work
The solution is I should bind the event on B instead of A like B.on('click', A, function(){})....
However, my structure is very hard to change, I rather want to find a solution that can prevent lose events while replacing or alternative.
Please advice, thank you very much.
Solved by using detach()
Since event bindings exist within the context of DOM elements, when you start removing or replacing DOM elements, you need some mechanism to re-establish the event bindings.
A good approach is to use delegation via a parent element (as you have stated - B.on('click', A, function(){}).... ).
The other alternative is to always re-establish the bindings at the point at which the DOM elements in question are removed or replaced (so in your scenario, it sounds like this would have to be in the Ajax callback/completion handler) however this is generally a poorer approach and is much less elegant than the delegation method.
If you are concerned about applying the on event to a certain element on the page. Then I would recommend just binding the event to the document.
$(document).on('click', '#id-of-a', function(){
});
Read this blog post for more information concerning this.
I found a solution. This is possible with using .detach()! tested.
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.
I'm using jQuery in an app which registers user clicks to perform a given action through the .click() binding, and I want this functionality to be available only through a user mousedown. One of my friends pointed out today that it's possible to run $(element).click() from a javascript terminal in Firebug (or something similar), and achieve the same functionality as clicking on the element -- something I'd like to prevent. Any ideas on how to go about doing this? Thanks for your input.
Short answer: No, you can't really prevent it.
Long answer: Any event like a click event is bound to such called Event handlers. Those handlers are functions which are executed when a given event occurs. So if you click on an element, your browser checks if any event handlers are bound to it, if so it fires them. If not, the browser will try to bubble up the event to the parent elements, again checks if there are any event handlers bound for that kind of event .. and so forth.
jQuerys .trigger() method (which is what you actually call if calling .click() for instance) just does the same thing. It calls the event handlers which are bound to a specific element, for a specific event.
EDIT
There might some simple ways to somekind of soft detect a real click, for instance you might check for the toElement property within an event object. That property is not set when triggered. But then again, you can easily fake that aswell with .trigger(). Example:
$(document).ready(function() {
$('#invalid2').bind('click', function(e){
alert('click\nevent.target: ' + e.toElement.id);
console.log(e);
});
$('#invalid1').bind('click', function(){
$('#invalid2').trigger({
type: 'click',
toElement: {id: 'Fake'}
});
});
});
Working example: http://www.jsfiddle.net/v4wkv/1/
If you would just call $('#invalid2').trigger('click') the toElement property would not be there and therefore fail. But as you can see, you can add like anything into the event object.
What are you trying to prevent? Someone messing with your client side script? You can do things like obfuscate your code but not much other than that. But even doing this is just making it more hassle than it's worth in my opinion.
If you don't want people doing certain things move the functionality to the server.
Sorry to be bearer of bad news.
You cannot really do anything against it, it would also be possible to write the complete function and then fire it.
But why is this a problem? If somebody is changing something client side it only affects him. Or are you trying to check some data? This MUST always be done in the backend, because you can never be sure what is really sent to it.
You can check event object (which is passed as first argument to handler) originalEvent.
It will be undefined if event is simulated by .click()
But it's completely useless. You cannot use javascript for security - client has full control over it (and firebug console is just most obvious tool). Client-side security checks should be only hint for user and protection against errors, malicious input can be stopped on server-side only.