Event bubbling jQuery .delegate() or .live() after click event - javascript

I've tried so many different possibilities to achieve what I feel like should be a simple code execution. I am loading DOM objects from the server via .load(). One of the loaded items is an input text box with a date in it. I want to load the jdpicker (a plugin datepicker) when I click on the input box. Due to the behavior of .live() and .delegate(), even when I use .die() or .undelegate() respectively, I can't get the popup datepicker to behave normally. It either pops up, allows me to click one object in the window and then immediately closes (I cannot navigate through the months, years without the window closing), or the window pops up and every subsequent click re-executes the code producing multiple instances of the datepicker.
I've tried different combinations of .live(), .delegate(), .one() with no luck. I've tested the datepicker in the main window and know that it works fine there. I could post code, but am not sure which of the ten different attempts I've made would be the best example. I can show my latest attempt.
Does anyone have a suitable example for this? Thanks!
Update
I've edited the code to read as follows:
$("#edit-entry").load("/edit/", { id:id }, function(){
$('.jdpicker').one('click', function(){
$(this).jdPicker();
});
});
This is hinging on becoming the complete answer. The datepicker is no longer calling multiple instances, which is good, but I still can't navigate it's controls (month, year selection). If I click the next month, it will load and close. The next time I click it, it re-opens on the next month. So, it does work, but is certainly not desirable. Any suggestions?

You just can't do that with "live" or "delegate". The fact of the matter is that you'll need to apply your plugin initialization explicitly after ".load()" succeeds.
edit — the change you've made is probably not going to work. Here's your code in English:
"Fetch content from the URL '/edit/' and deposit it into the element with id 'edit-entry'. When that content has been received, then bind a one-time event handler to the "click" function of all elements with class 'jdpicker'. In that event handler, set up the 'jdPicker' functionality for the element."
Instead, what you should be doing is just calling the jdPicker setup directly instead of setting it up so that the user has to click on the elements first.
$("#edit-entry").load("/edit/", { id:id }, function(){
$('.jdpicker').each(function(){
$(this).jdPicker();
});
});

Related

Make event fire first... alternative to using $._data in jQuery

I want to create a "confirm plugin" that will fire first and ask the user if "they are sure". Just to be clear, I will be using a custom made confirm box, not a the default Window confirm() Method.
If yes then it will fire all the other events that have been bound to it. If no then it will do nothing.
A use case would be a delete button that has a separate click event bound to it, which when pressed will delete an element.
If I attach my plugin to the button then it will bind another click event and by using the events info inside $._data I can send my even to the top of the list (making it fire first), I then stop propagation (this stops the other binding firing which deletes the element). If the user clicks ok on my confirm box, I trigger a click again this time just bypass the stop stuff and it will then fire the original events
I am using a slightly modified version of https://github.com/private-face/jquery.bind-first
The only way it can access this info on an element is by using:
$._data($(this)[0]).events
I want to know how "future proof" this is as I know this changed already since 1.7. Are there any plans to officially support a similar thing.
If all else fails, I know I can just make sure that the plugin and the bindings happen first in the code, but this is not really the most flexible solution.
Using $._data is a smelly solution, hence this post. Maybe there are some fancy custom event things I can do?
The short and simple answer is not at all. Using, or more importantly relying on undocumented features is never a good idea.
It sounds like you have an XY Problem here. There are likely many other ways to achieve what you're trying to do here, and using $._data is almost certainly not the best solution.

Animate jQuery toggle only once per call

I have a pretty complex system with a few AJAX calls which render different templates into other templates in PHP.
One of these templates is a edit form for my entity. This form is rendered hidden into my website until a button was clicked, which will then fire a jQuery toggle() to switch out a part of my site for this edit form.
This works fine until the user is using the jQuery UI slider on my site.
What happens if the user navigates within the slider is that parts of my site will be reloaded with AJAX.
When the button for the toggle() then will be clicked the animation goes of as often as the slider was used (so if the slider was used 4 times the toggle will animate an switch out the 2 elements 4 times).
I debugged through it and couldn't find the mistake, i can't provide a jsFiddle which could rebuild the situation nor can i give access to the site. The click function will be fired only once, so i really can't explain why this is happening.
To mention is that i have 3 buttons which will trigger this event:
#poi_edit_ajax will be shown when the slider was used in the template which will be rendered per AJAX.
#poi_edit_first will be shown by first access to the site and nothing has been reloaded per AJAX.
#poi_edit_last will be shown so the user can come back from the edit view
The Javascript is the following:
$("#poi_edit_ajax").click(function(){
$(".toggle_edit").toggle('slow');
});
$("#poi_edit_first").click(function(){
$(".toggle_edit").toggle('slow');
});
$("#poi_edit_last").click(function(){
$(".toggle_edit").toggle('slow');
});
I don't think that somebody can give me a solution with just this information, but that's everything i can provide now, so my Question now is simply if it is possible to tell the toggle() function from jQuery to only run the animation ONCE PER CLICK.
I don't think that jQuery one() can be used for this, because so the click event could only be used once per pagevisit.
EDIT
According to the comment, i tried out if multiple event handlers will be registered within the AJAX calls, which is true.
The code to fix this is simple:
$("#comment_first").unbind("click").click(function(){
$('.toggle_information').toggle('slow');
});
$("#comment_last").unbind("click").click(function(){
$('.toggle_information').toggle('slow');
});
$("#comment_ajax").unbind("click").click(function(){
$('.toggle_information').toggle('slow');
});
I just need to unbind the Lister before bind it again, else they're gonna stuck and multiple Listeners will react to the click event!
You are probably binding the Click event multiple times (by loading javascript through the AJAX calls). Make sure you bind the Click handler (which triggers the toggle()) only once.
Take a look at this answer: https://stackoverflow.com/a/969011
A (slightly modified) quote from that answer, for quick reference:
function alertEvent() { alert("test"); }
$(".ajax").bind("click", alertEvent);
//When you want to ensure it won't happen twice...
$(".ajax").unbind("click", alertEvent);
$(".ajax").bind("click", alertEvent);
This method will only remove the event you specify

JQuery dropping click events

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.

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.

Binding JQuery events

JQuery events are annoying me. The thing is that I very often use
javascript (after ajax requests, etc.) to draw up new elements
(buttons, divs, etc.). I've got a list of elements
which you can press on an edit button so you can manipulate the one
linked to the selected edit button.
Now if someone submits a form to make a new element like the ones who
existed before, and I submit it with ajax and then I append or prepend
the new element into the list. After that the new edit button for the
new element isn't linked to JQuery's event system since the DOM hasn't
been reloaded after the edit button was made. If I call the same
javascript file with the events in it, then the edit button works but
then when people click other edit buttons the event happens twice for
them since they're bound twice. I've also used .bind() but that only
binds (I think) the same event twice as before. I don't remember at
the moment how I tested it. I haven't tested .one() but I would rather
not use it since some events must be called more than once.
I just wanted to ask you guys what approach you use when dealing with
the events?
P.S. I'm binding the JQuery event to the class attribute that all the elements have. If I was going to bind this to each element based on ID, then this wouldn't be a problem because then I would just use .bind(). By writing this I suddenly though of using .unbind() and then .bind() to link the elements to the events system. What do you think of that? Would you do it in another way?
Thanks in advance.
Kristinn.
You're looking to use $.fn.live:
$('a').live('click', function(e) {
e.preventDefault();
alert('im attached even if the DOM has been updated!');
});
http://docs.jquery.com/Events/live
Your question is a bit general, but I have a feeling that what you're looking for is jquery live
http://www.thewebsqueeze.com/tips-and-tricks/tip-for-jquery-live-event.html
http://simpable.com/code/jquery-live-events/
http://www.thefutureoftheweb.com/blog/jquery-live-events
http://kylefox.ca/blog/2009/feb/09/live-event-binding-jquery-13/

Categories