Why does jQuery alls Alert() more times? - javascript

I currently have a quite big issue here, which I've been trying to figure out since yesterday, but I really don't know what could be the problem here.
So I basically made a jQuery Ajax call in my code, something like this:
var ajaxCall = function(id, token)
{
var datap = { "id": id, "token": token };
$.ajax({
type: "POST",
url: "ajax.php",
data: datap,
dataType: "json",
beforeSend:function()
{
// loading image
},
success: function(data)
{
setting(data);
},
error: function()
{
alert('error');
}
});
As for the success function you can see the setting function, which looks like this:
var setting = function(data)
{
$('#testDiv').html(data.country);
}
Basically, this ajax call is made, once someone clicks on an item like:
$('#popup').on("click", function(){
ajaxCall();
});
So when someone clicks in the popup button, they will have a popup window open with the loaded Ajax content.
This is actually working flawlessly. My only problem happens, if I want to make another event within the Popup window (like: on click).
var load = function()
{
$('#testDiv #button').on("click", function(){
alert(1);
}
}
So if I place it in the above Ajax call function, it looks like the following:
$('#popup').on("click", function(){
ajaxCall();
load();
});
Problem:
When I click on the opoup button, to load the popup window, it loads the Ajax content. When I try to click on #button within the popup window at the first time, after loading the page, it gives me the alert box with 1.
However! If I just close the opoup window and click on it again, to load the popup, than click on the #button again, now I got the alert(1) 2 times! If I do the above again, I got it 3 times, 4 times, and so on.
So basically I've found out, that if I use the on Click function (within the popup window, after ajax has loaded), the contents within the on Click function got called more times, if I load the popup window more times (without refreshing the page - after refresh, everything strats from the beginning).
So the first popup load and click is normal, but the others seems to get called more times. I have also checked that the Ajax call is called multiple times, but it's NOT. I have placed an increment number inside each part of the code and I only got it incremented multiple times when the #button was clicked.
I know that this is quite hard to understand, but I would really need someone's help here, as I'm completely lost. Any solutions would be really appreciated.

I suggest you to do this:
Bind your click event outside of that function and put it in doc ready:
$('#testDiv #button').on("click", function(){
alert(1);
});
and do this in the #popup click event:
$('#popup').on("click", function(){
ajaxCall();
$('#testDiv #button').trigger('click');
});

You are binding the click event whenever load is called, to fire it once, you should bind it once. Either unbind it every time you call load before binding it or use on for event delegation. If you have to bind event with ids then you should directly bind as id are supposed to be using do not use descendant selector.
var load = function()
{
$('#testDiv #button').off("click");
$('#testDiv #button').on("click", function(){
alert(1);
}
}
I would recommend you to use event delegation for dynamically added elements
$(document).on("click", '#testDiv #button',function(){
alert(1);
});
Delegated events
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time. By
picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers, jQuery docs.
Edit based on comments
As both elements are present in dom and not loaded dynamically you simply need click event. As ids are supposed to be unique do not use parent child selector
$('#testDiv').on("click", function(){
alert(1);
});

Related

How to call a jquery method from PHP page loaded through ajax

I have a page where I am loading a series of buttons into a div using jquery/ajax. This is a script for loading every time the user user scrolls the page. Each of the buttons are clickable and run a jquery function after being clicked. The problem is when I switched to loading the buttons from a different page the now don't call any method. If I switch the buttons to calling a pure javascript function it works just fine but I need the button to call a jquery function as the rest of the script, which is quite long, has been done in jquery.
Here is what I am talking about:
Page A:
$(document).ready(function() {
var track_load = 0; //total loaded record group(s)
var loading = false; //to prevents multipal ajax loads
var total_groups = '<?php echo $total_groups; ?>';
$('#results').load("testshareload.php", {'group_no':track_load}, function(result) {
track_load++;
}); //load first group
$(window).scroll(function() { //detect page scroll
});
$('#testerino').on('click', function () {
console.log("CALLED");
});
PAGE B: (testshareload.php)
<?php
echo "<input type='button' value='Button' id='testerino'>";
?>
It also will not work for me to do this due to the existing code:
function testerino() {
$(document).ready(function() {
});
}
What else can I do to solve this problem?
You're creating a click handler for an element that doesn't exist, and this will fail in jQuery. What you need to do is create a DELEGATED handler for the item:
$(document).on('click','#testerino', function () {
console.log("CALLED");
});
The document accepts the handler being registered, and later when it gets a click event from an element matching the selector #testerino it will fire off the handler.
Your problem is that you're binding an event to an element that doesn't exist yet.
As per the docs:
Event handlers are bound only to the currently selected elements; they
must exist at the time your code makes the call to .on()
You have two options:
Create the bind in your .load function instead.
Or as per the docs again:
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time. By
picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers.
Use $(document).on('click', '#testerino', function() { ...

Send click event on button loaded dynamically

So this is slightly different than all the posts I have found on the subject. I have a button that gets loaded dynamically via Jquery, I save the selector of this button and later on in my code I need to send a click event (Emulate someone clicking on the button) Now normally I would just use $('#myID').click();
and this casts a click. But Since my button is loaded dynamically this does not work. Now I do NOT need to handle the onclick event. I could use
$(document).on('click', '#myId',function(e){});
for that. I need to actually send the click event. I have tried
.click();
.on('click);
.onClick();
.trigger('click');
Any ideas?
You could also breakout the code that you want to happen when you click on the button into a function if it's simple enough and instead of trying to fire a click event just fire the function the button normally fires.
By using setTimeout() to call the function again and again you are essentially polling the element, untill it actually exists, which is when you fire the click event.
// Wait for everything in the document to be loaded
jQuery(document).ready(function() {
// Make the initial call to the function
fire_click('#myID');
// This function tries to find the button, and if it can't
// find it, it calls itself again in 50 ms.
function fire_click(selector) {
elem = jQuery(selector);
if (elem.length == 0)
setTimeout(fire_click, 50);
else
elem.click();
}
});
A better solution would be to have a callback function that is fired when the button is loaded. This callback function can then fire the click event on the button, since the callback function is only called when the button is actually there. Generally it's a good idea to avoid polling for information when you can, so therefore this would be considered a better solution.

jQuery load() dynamic content with clicks get fired as many times as loaded

I load content via jQuery load() but for each time I load a given page, the clicks on the pages gets fired multiple times. Why??
Se the fiddle here:
http://jsfiddle.net/ZUZ3L/ph3tH/2/
Simply put your click hander outsie of load:
$(document).ready(function() {
function loadContent() {
$(".ajaxContainer").load("http://fiddle.jshell.net/ #actions", function() {
alert("Done");
});
}
$(".load").click(loadContent);
loadContent();
});​
Updated Fiddle
Each time you load content, you execute this line:
$(".load").click(loadContent);
which adds a new event handler to the list of event handlers to execute whenever .load is clicked. You execute your function three times, now you have three identical handlers all triggering for each click.
It's because you're adding the click event multiple times.
Every time your code runs, the click function is re-defined. When a click is redefined it won't replace the previous one, but instead will be added to the stack to be executed each time the "click" event occurs. This is applied to all events in jQuery.
As you are loading via AJAX the vars and events in the document are still persisted. Meaning that you are just adding layer on top of layer of function calls to be executed each time you run your ajax call
because you are calling the function 2 times, try this:
$(document).ready(function() {
function loadContent() {
$(".ajaxContainer").load("http://fiddle.jshell.net/ #actions", function() {
alert("Done");
});
}
loadContent();
$(".load").click(loadContent);
});
http://jsfiddle.net/ph3tH/4/

JavaScript mouseup Event Being Fired Multiple Times On Single Click

Can someone tell me why the javascript code below causes renewSession() to be called 7 times after a single click?
$(document).ready(function () {
$("*").mouseup(function () {
renewSession();
});
});
function renewSession() {
$.ajax({
url: "/Account/RenewSession",
type: "POST"
});
}
Probably it's because the mouseup event propagates up through the DOM tree, and you're applying the handler to every element in the document. So it'll fire on the first element, and then the parent and so on until it gets to the html (or the body, I can never quite remember without checking every time).
You could use:
$(document).ready(function () {
$("*").mouseup(function (e) {
e.stopPropagation();
renewSession();
});
});
To prevent the multiple calls.
Edited to address comment from thiag0:
Thanks for the quick response...what I am trying to do is call renewSession() every time the user clicks on the site to keep the session alive. This solution prevents the renewSession from getting called multiple times in a single click but prevents the actual intent of the user's click from firing. Anyway to get around this?
You could just target the body element; so long as events are allowed to propagate through the DOM tree (so long as you're not calling event.stopPropagation() on elements between the element clicked on (or 'mouseup'-ed) then the event(s) will propagate to the body. So I'd suggest using:
$(document).ready(function () {
$("body").mouseup(function () {
renewSession();
});
});
The * selctor matches 7 elements...
Events in html bubble up the DOM tree, unless explicitly told to stop, and hence the event will be triggered for each element going up the tree that matches the selector (in this case all of them!).
If this is not your intended behaviour either use a more specific selector, or call the stopPropagation method.

How does jQuery handle nested functions and timing of events?

There are a couple of things that really trouble me with regards to how jQuery handles nested functions (not to the point that I can't sleep but it's getting there) and I wish a jQuery expert could explain how things work to bring me piece of mind.
Let's say you have the below HTML code:
<button id="first">click me first</button>
<button id="second">click me next</button>
And the following jQuery code:
$(document).ready(function() {
$('#first').click(function() {
$('#second').click(function() {
alert('test');
});
});
});
A dialog box will popup if you click the first button and then the second button.
I understand jQuery instantiates the $('#first').click() function when the DOM is ready and calls it when someone clicks on the first button.
However what I am puzzled with is the following:
[Q1] is the $('#second').click() function also instantiated on DOM ready or only when $('#one').click() is called?
Now, when you look at the jQuery code, there is nothing that "keeps us" in the $('#first').click() function, that is once the user clicks on the first button, the $('#second').click() function should be instantiated and we should exit the $('#one').click() function straight away. However after clicking the first button, jquery must somehow keep $('#second').click() indefinitely in memory in case the user clicks on the second button.
[Q2] how does jquery know to keep the $('#second').click() function in memory until the user clicks on the second button after clicking the first button?
Finally let's say you wanted to modify your code so that the user had to click the second button within 10 seconds of clicking the first button for the dialog box to appear:
[Q3] how would you implement this so that jQuery would know to stop listening for click events on the second button after 10 seconds?
Q1 - JS will simply load function definitions. It won't run it unless they are explicitly triggered/called. In this case, it will simply attach the event handler to #first and wait until someone clicks the button to fire the event. This will make the second function attach itself to the second button.
Q2 Again, it's not jQuery, it's JavaScript doing all the work. The method is simply attached to the DOM element and is triggered on the event it is attached to. JS is like any programming language and will keep all methods and variables in its memory.
The second click function isn't actually attached to the second button until after someone clicks on the first button. This is because, when the first button is clicked, JS knows to trigger the first method which does all the work of attaching the second method to the second button.
Q3 You could use setTimeout to unbind that method from the DOM element.
$(document).ready(function() {
$('#first').click(function() {
$('#second').click(function() {
alert('test');
setTimeout(function(){$('#second').unbind('click');}, 10000);
});
});
});
Note This unbinds all click event handlers from this DOM element. You can also unbind that particular method by passing it as a parameter. Check out the API docs for usage.
setTimeout : https://developer.mozilla.org/en/DOM/window.setTimeout
unbind : http://api.jquery.com/unbind/
[A1] The second function is only instantiated when #first is clicked as it is part of the execution of the first method. This also means that if you click #first n times you should get n alerts for every click on #second.
[A2] The function is rooted by the #second element. So long as that element is alive javascript knows to keep the function around.
[A3] You would need to save off the function pointer and do a setTimeout to clear it.
$(document).ready(function() {
$('#first').click(function() {
var secondFunction = function() {
alert('test');
};
$('#second').click(secondFunction);
setTimeout(function(){ $('#second').unbind('click', secondFunction); }, 10000);
});
});
A better implementation is probably something like:
$(document).ready(function() {
var enabled = false;
$('#first').click(function() {
enabled = true;
setTimeout(function(){ enabled = false; }, 10000);
});
$('#second').click(function() {
if(enabled) {
alert('test');
};
});
});
The answer to your first question: Yes, the second button will bind to click event only when a user clicks on the first button.
The second question: I'm not sure what you're asking.
The third one: Assuming the button one has nothing to do except bind the event to second button once clicked, you can set a timeout on document ready for 10 seconds. Now when the timer expires it must unbind the button one's click event hence blocking second button's event. I guess you understand now. e.g.
$(document).ready(function(){
setTimeout(removeEvent, 10000);
$('#first').click(function() {
$('#second').click(function() {
alert('test');
});
});
});
function removeEvent(){
$('#first').unbind('click');
}

Categories

Resources