JQuery dropping click events - javascript

I'm currently experiencing click events intermittently not firing. Anyone else ever had this problem?
Code is simple:
<ul class="iconButtons ui-widget ui-helper-clearfix">
<li class="ui-state-default ui-corner-all" title="Save">
<span class="btnSave ui-icon ui-icon-disk"></span>
</li>
</ul>
$(document).ready(function() {
$(".btnSave").click(function() {
alert("Sometimes I never get called!");
});
});
Occurs frequently in all browsers. Using live demonstrates the same behaviour.

I would venture to say that there is some other complication going on to prevent what you are doing.
Here are some possibilities:
Unless you give that empty span display:block; then on some browsers it will have a width and height of 0px and be unclickable. Keep in mind just adding width and height to a span won't actually work on inline elements.
You are ajax'ing content in, and not rebinding the click handler. You can check at any time by doing $(".btnSave").data("events") in your firebug or chrome console to see the number of events to that element.
Another event is usurping your event, using the technique in #2 may help reveal this.
Your click handle is being called, but not returning the right result causing to believe it wasn't being called. Have you tried adding an alert('called') to the very top of the click handler?
Are you certain the element exists in the DOM prior to appending the click element to it? You can check by doing an alert($(".btnSave").length) at the line JUST before you bind the click handler.

I would suggest you use an anchor instead of a span for your button it will fire for sure.
Put
$(".btnSave").click(function(event){
event.preventDefault();
alert("Clicked");
});
In IE, you also have to have content inside an anchor for it to work: background image / background color/ text (maybe also with big negative text-indent)

Your code will hook up event handlers to all elements with that class that already exist when the code is called. If you add more later, they won't get the handler because, well, you haven't asked that they do. :-) Options:
You could use live instead, if you add and remove these elements dynamically. live (and the related delegate) use event delegation to watch for events rather than actually attaching the handlers to the elements in question. live uses the document itself. Since click bubbles, document sees all clicks (that aren't cancelled), and so jQuery's document-wide handler can see if the click was on a .btnSave element and fire your handler if so.
You could put your script at the bottom of the page (just before the closing </body> element), so that all of the elements are there when you hook up your handler.
You could use jQuery's ready function to ensure the DOM is ready before you hook up your handlers.
Alternately, as quoted your span is pretty darned hard to click on (what with being completely empty) unless there's some CSS giving it dimensions you haven't shown... ;-)
Update: You've said the span has dimensions, and that the handler is being hooked up fine (you didn't say how you know that). The only thing left is if something is hooking the click event on those elements and cancelling them (e.g., via stopImmediatePropagation, like this), and it happens that they're earlier in the event handler list than your handler is. It seems more likely that there's an issue hooking things up, though.

There may be many different reasons for that, eg.:
the JS code you are referring to is not executed correctly (does not bind the event in the correct moment in time), try executing it when the DOM is ready:
jQuery(function(){
// your code goes here
});
you may be creating this element dynamically (if you bind it first, then create element, then this element will not have the specific event). The solution is to use .delegate() or .live() jQuery functions.
the event may be unbound somewhere in your code. Try searching for usage of .unbind() jQuery's function within JS code (or even HTML).

It turns out the span which the click event was being added to only occupied the central part of the button's graphic. Clicking directly on the glyph always fired the event, but clicking slightly outside (although seemingly still inside the button) would not raise the event.
I hope this helps anyone else using mini JQuery buttons in the same way they are presented on the JQuery UI ThemeRoller page.

I'm running jquery-ui-1.10.3 and I'm having the same intermittent issue with .toggle buttons -- they just aren't very responsive. I think it's inherent in jquery-ui because even on their demo page the toggle button feels less-than-awesome in terms of tactile response. If I click very slowly and deliberately I can usually get the button to toggle on and off but fast clicking is very hit or miss. I've tried all the tips to speed up jquery-ui but none have worked.

Related

javascript how to determine what is cancelling an event

I have jquery, bootstrap included in a page I'm writing. It's a complex page. The problem I'm having is with Internet Explorer not seeing mousedown event. Chrome and FF both see the event just fine but not IE.
I wrote a test page with the event and it worked just fine in IE. So my question is...
Is there a way through the developer tools to determine what is cancelling an event?
I have a suspicion that one of the many .js files I've included is cancelling the mousedown event and IE isn't seeing it anymore. Chrome and FF does though. So I'm not 100% that it's being cancelled but it's my only guess I can come up with.
Code is really irrelevant since it's all of jquery and bootstrap. However, I am playing with divs that are draggable and resizeable. That's why I need to use jquery. The bootstrap is used because I also have a wysiwyg editor on the page.
Please don't recommend click. I need mousedown. When the mouse is down the border around the draggable and resizeable div turns red and I have some code that selects that div to capture top, left, width, and height as it's being moved and resized.
If click was selected as the event, the user would have to click the div box first then click and hold to move it. That's not a user friendly interface.
Any help is greatly appreciated.
What do you exactly mean as cancel, .preventDefault() or .stopPropagation? If we are talking about preventDefault - you should still be able to add event listener to parent container and then see your event object - it might have some data to traceback. Alternative would to override jQuery .on method and see who actually subscribes to the event.
After little more thinking - add another listener BEFORE the malicious one, to do that insert document-ready handler with event binding right after jquery loading code. In your new mousedown handler try to override problematic method of the event.
UPDATE:
you should try to check all events attached to your element one by one. To do that - check this post jQuery find events handlers registered with an object
In short - try using jQuery._data( elem, "events" ); to see attached event listeners and inspect their code in your code base. After you find the reason it will be much easier to reach the desired functionality. Before that it is just a guesswork.

Trouble with"onmouseover" event using native Javascript

I am attempting to add an onmouseout function to the names in the following widget. The onmouseover works fine but the onmouseout fires almost immediately on rollover. Not sure why.
http://jsfiddle.net/A8fmg/
I think it may have something to do "bubbling" and I have been trying to read about the subject but don't quite understand the implications.
Any help is appreciated.
Your mouseover handler is destroying the <a> which the handlers are attached to. Adjust your code so that the handlers are attached to a permanent element, either by attaching to a different element or not destroying the one you are using.

can I trigger click event onload

I am having anchor tag in my page. I like to trigger click event onload . Which means I wanna open this page "http://XXXXX.com" with new tab. Because I don't wanna popup blockers. Is there anyway to do this?
anchor attrs are given bellow
id="add_redirect"
href="http://XXXXX.com"
target="_blank"
Yeah, you can use a click event called onLoad(). Just use the setTimeout() method in jquery. It will call a click function without clicking it. Here is an example:
$("document").ready(function() {
setTimeout(function() {
$("#add_redirect").trigger('click');
},10);
});
This will work for you when the page start to load and the time delay is 10ms which is negligible.
Syntax has been corrected.
Try adding the following code in the page load
document.getElementById('add_redirect').click();
Using JQuery you can do that pretty easy. The earlier posted solution also work of course.
$(document).ready(function(){
$("#add_redirect").trigger('click');
});
TRY DEMO
If your goal is to bypass pop-up blockers on page load, triggering the click event synthetically probably won't work. Browsers are smart enough to know when a click is user-generated vs. when you've called the click function on the DOM element (on those browsers were that even works). Examples: http://jsbin.com/avibi3/3, http://jsbin.com/avibi3/4
Using jQuery's trigger mechanism certainly won't do it, because it doesn't really trigger a click event at all; it just fires the handlers that jQuery hooked up (edit: and, apparently, ones defined via an onclick attribute — see Sukhi's answer — but not ones attached via addEventListener). If that's what you want to do, Sukhi's answer shows you how, although I always say: If you want code to be run from two different places, put it in a function, and call that function from two different places (rather than putting it in a click handler and then simulating a click just to run the code). There are valid use cases for trigger (mostly relating to integrating with third-party scripts), but for running your own code from two different places, it's a symptom of a design problem.

Why doesn't jQuery 1.3.3. live() support all events?

I've just been pondering the jQuery live() event binder, which seems like a really useful function.
http://docs.jquery.com/Events/live
One thing I note is that it doesn't support all events:
"Currently not supported: blur, focus,
mouseenter, mouseleave, change, submit"
My (very simple) mind reasons that surely if it were implemented for one event, it would be easy to do it for all others?
Clearly its wasn't that simple, so I wondered if anyone knows why it was so difficult to do it for all others?
This is because it uses event delegation. The problem is that event delegation based on event bubbling. And events are bubbling not for all events.
you can read more here: JavaScript Event Delegation is Easier than You Think
As I understand it:
When you use live() an event handler is attached to the document.
Why?
Given this snippet:
<html>
<body>
<ul>
<li>my link</li>
</ul>
</body>
</html>
When you click or move the mouse on the <a> tag, you have to remember that your <a> is sitting inside an <li> which is inside a <ul> in a <body> in <html> which is inside the document. No matter what HTML structure you have, every element exists within the document.
So, when you click the link, you're actually also clicking all those other elements too, it's just that the link is sitting on top* of that stack. This is called bubbling - the click event starts on the link and bubbles up through each of its parents finally reaching the document. Any time you click any element you're also clicking the document.
Therefore, if you place an event listener on the document to handle clicks, it can check where else was clicked in that same event before it bubbled to the document. The live() function simply stores the query string you provided and compares that against all clicked (or mousemoved, etc) elements and fires your function if it gets a hit.
The others: blur, focus, mouseenter, mouseleave, change, submit are all events which don't bubble, therefore they can't be used with live().
Why don't they bubble?
Because if you think about it, it doesn't make sense. If you focus an element, you are only focusing one element, not its parents and ancestors. Similarly with the others - the events never reach the document so you can't use this technique.
*: as with many "tree" metaphors in computing, terms like "up" and "top" can be a bit confusing. Though your link is visually rendered at the top, it's probably more helpful to think of it as at the bottom. The events bubble upwards through parents and reach the top level element which is the "root". :-/

Why do registered events disappear when an element is removed from DOM?

This jQuery 1.3.2 code adds an element to the page, registers a "click" event, then removes and reattaches the element:
var button = $('<button>Click me!</button>')
.click(function(){ alert("Hello") })
.appendTo('body');
$('body').html('');
button.appendTo('body');
The button appears on the page as expected, but clicking on it does nothing. I would like to know why the event handlers were removed from the object.
Note: I am aware of solutions such as jQuery.live() or clone(true) or using appendTo without a removal. What I'm looking for is an explanation, not a solution or workaround.
EDIT: I suppose this could be an arbitrary and counter-intuitive design decision of the DOM. An explanation like "Because that's the way section X of specification Y wants it to be" would be fine.
When you remove an element from the DOM using jQuery, all data (including event handlers) held by jQuery on that element will be destroyed. This is done to avoid memory-leaks.
This isn't a feature (or bug) of the DOM API. It's just jQuery.
If you want your registered events to stay on your element use .detach() instead of .remove(). Use it the same way you'd use .remove(), it will keep your events on your element.

Categories