jQuery event fires multiple times - php

I have a problem with jQuery events.
First let me explain the setup of the page:
The main-page.php is consisted of:
a) a header (where the logo is)
b) a navbar (where the various selections are)
c) a dynamic content area (Where the content of the clicked element on the navbar will be loaded)
d) Footer
Lets say that the navbar is consisted of | HOME | MESSAGES | ABOUT US | ...
The content of HOME is a separate PHP file, with a separate CSS and JS file. The same goes for all selections.
As soon as I select HOME (for example), i remove any content from the DYNAMIC CONTENT area and I place the content of HOME using AJAX. At the same time I remove any CSS/JS files associated with the previous content and I link the CSS/JS files associated with the one loaded. This part is working perfectly.
Now, if I switch from one selection to other selections (lets say from HOME --> MESSAGES --> ABOUT US and then back to HOME), if I click on a button inside HOME it will fire the event multiple times. This is even worse if that event is causing an AJAX call to the server (imagine calling the server 5 times instead of 1).
**The reason I use the on() event on the element with radio-element class is because is a future DOM element. Initially this element is not on the page.
A sample of JS code:
$(document).on('click', '.radio-element', function(){
$.ajax({
url: "js/ajax/ajaxcall.php",
success: function(output){
$('#ajaxcall-container').html(output);
}
});
});
What I do is, as soon as I click an element with the class of radio-element, I go in the server and i fetch the output of ajaxcall.php script.
Watching the NETWORK tab inside INSPECT ELEMENT, I see that the click event is executing the AJAX call multiple times. Sometimes 2, other 3 or even 5.
What I did to solve the problem (non of them is working 100%):
A) unbind the event before binding it using "off"
$(document).off('click','.radio-element').on('click', '.radio-element', function(){ .... });
B) Use event.stopImmediatePropagation()
$(document).on('click', '.radio-element', function(event){
event.stopImmediatePropagation();
//rest of code
});
Below is a solution that I haven't tried yet since I read in an article that it will not stop event binding process, it will just prevent multiple event execution (don't know if this will cause other problems).
$(document).on('click', '.radio-element', function(event){
if(event.handled !== true)
{
//Code goes here
event.handled = true;
}
});
The problem with multiple event firing is that there are AJAX calls that perform actions that are not supposed to be executed more than once (eg. send email to clients).
Also, this behavior (multiple event firing) is not something i can predict. Sometimes it works fine, some others it fires the event 5 times in a row.
I have been searching the web for a week now, but everything i tried did not solve the problem. Any solution will be much appreciated :)
Thanks!

Based upon what I am reading here - I would guess you are bringing on the js file with the click bind event more than once. If you are using custom routing or single page app and not refreshing the page, it is very likely based on what you are saying.
You could test this theory by adding a console.log inside the click event (above the ajax) and fool around with it and check the logs. If you are clicking it and it is logging whatever you logged more than once, then you know that this is the issue. I don't think it is the ajax.

I have also encountered the same problem quite a while. I solved this by unbinding all the events associated with the element before executing new event handlers.
Use like this:
$('#element').unbind().click()
{
//write something here
}
This will unbind previous event handlers before creating a new one. I think this will works well for you.
If you are using jquery version 1.7+
you can use off() like this
$('#element').Off().click()
{
//write something here
}

My guess based on your description is that you are not removing the event listeners. So every time you switch tab/page the same event will be added over and over again. Even though you have tried to do it, something is not going right. I doubt it has anything to do with Ajax.

Related

stop click action from mousedown event

Im building an application which is intended for speed, and Im thinking to process actual page loads on mousedown event than click event, so the gap between the mousedown and click saves me some milliseconds(about 100ms), my app can load pages with in that 100ms time, so it just runs instant.
$(document).on('mousedown','a.magic_links',function(e) {
$(this).click().off("click");
});
I tried this code, but not preventing the default click action, any suggestions to achieve this?
You want to prevent the default behavior of the event (or cancel it).
What you are currently trying to do is remove an event handler that was never created in the first place
$(document).on('mousedown','a.magic_links',function(e) {
e.preventDefault();
// code here to do your loading
});
Personally I think you should rethink this over-optimization strategy as it may not be optimal for all devices

How can I delay appearance of DOM elements created with php until document is ready

I have a program with two files, a program.js and a program.php. The js one uses jQuery and wraps everything inside $(document).ready , so everything happens after DOM is loaded.
program.php is writing a few elements in the way of:
printf( "<table>"> );
How can I delay the elements that I create through php until DOM has loaded? They generate before the jQuery created elements, and I have some conflict.
Should I wrap the php items in a function and set a delay to it?
Is there a more ideal way? It doesn't feel proper to do
printf("<script>$document.ready(function(){");
//and the rest of elements that I want to delay
EDIT: The original conflict that made me think of this, was that the jQuery file is doing:
$("#create-booking").button().on("click", function() {
dialog.dialog("open");
});
While the php is doing:
printf("<button id='create-booking'>Create</button>");
So the event is not being applied. My suspicion is that the php element loads much faster and when it's created, the jQuery handler didn't have time to appear yet.
If your issue is just one of display and you just want everything to show at the same time, then you can hide the PHP generated elements (the one's in the HTML source of the page) with CSS and then show them in your $(document).ready() handler and then all content will show at the same time.
For example, if the PHP generated content was in a parent div like this:
<div id="container">
<!-- PHP generated content -->
<table>
...
</table>
</div>
Then, you could add a default CSS style rule like this:
#container {display: none;}
And, then add this Javascript:
$(document).ready(function() {
// do other scripting things here first
// then show your content, now that everything else is in place
$("#container").show();
});
If your issue is something else (you mention "conflict" without explaining what that is), then you need to describe what the actual conflict problem is so we can help you fix the root problem, not just add a bandaid around it. See XY Problem for an understanding of why it's better to describe your actual problem rather than your attempted solution.
EDIT:
From your comments, it sounds like your only concern is that the PHP content may be visible a little bit before your event handlers are in place. Unless you have some unusual delay in loading the web page, that generally does not cause a problem for web pages because the time gap is very small between display and event handler installation and the consequences of the problem are very small (a very quick click might be missed in which case the user would probably just click again). So, usually people do not worry about that issue. But, if you want to address it, you can just not make the content visible until after the event handlers are installed. There are many different ways to do that, but I've shown one above.
You should understand that there is a strict sequence of events here. All PHP generated content comes first. The PHP runs on the server and creates the HTML of the page. That finished HTML is then sent down to the browser. The browser starts to load and parse that HTML. Then, when the browser encounters a <script> tag as part of that page, it will run that script in the order the script tag appears in the page. Any <body> content (from your PHP server) that comes before that script tag will be already in the page and visible. Any <body> content that comes after that script tag will not yet be available to the script.
Further Edit:
OK, now you've explained that you're adding content to the page dynamically via Javacript/Ajax. That will likely finish after $(document).ready() so yes you would have a problem adding event handlers.
You have two choices to fix that:
You can delay the adding of event handlers until AFTER your ajax calls have finished adding content. You would have to hook into the completion callbacks for your ajax calls and then call a function from there that would add the event handlers.
You can switch to using delegated event handling which allows you to add the event handlers to an existing parent element BEFORE the actual child content has been added to the page. Here are some references on how to use delegated event handling:
JQuery Event Handlers - What's the "Best" method
Does jQuery.on() work for elements that are added after the event handler is created?
jQuery .live() vs .on() method for adding a click event after loading dynamic html
Should all jquery events be bound to $(document)?

Inadvertent multiple posts through jquery

This is my first post so I hope I am not violating any rules. I have searched quite extensively, but possibly may have not looked for the correct terms that I am looking to resolve.
At any rate, my problem is this:
I have a table generated with a list of items, the left-most column has a button when clicked calls an ajax Post and or load function to query the history of the item and list it below the table. This works in its true sense of the expected result, however, reviewing the console through FireBug, subsequent clicks on buttons in the list result in the doubling of posts. ie. 1st click shows 1 console event, 2nd click shows 2 console events, 3rd click shows 4 console events, and so on. this continues until I select a different location and the count resets.
The below is what I see in the console. This presents a problem with timing as each subsequent post takes longer.
clicking the hist-tag button 5365
>GET http://localhost/digipens/query.php?rec_id=5365
clicking the hist-tag button 5365
>GET http://localhost/digipens/query.php?rec_id=5365
clicking the hist-tag button 5365
>GET http://localhost/digipens/query.php?rec_id=5365
clicking the hist-tag button 5365
>GET http://localhost/digipens/query.php?rec_id=5365
code:
$('.hist-tag').click(function(){
var ID=$(this).closest('tr').attr('id')
itemid = $("#itemid_input_"+ID).val();
dataString = '?rec_id='+ID;
$('#item_hist').load('query.php' + dataString);
});
Any ideas or different ways to accomplish the same goal would be excellent.
Thanks!
It sounds as if you are adding a click handler as a result of your click. Do you call $('.hist-tag').click() after the table updates? If so, you are adding new click handlers each time, which means the click is handled twice, and then 4 times, and then 8 times, etc.
I can only guess, because I don't see the relevant code here.
If so, the correct solution is to only add your click handler once, and do it via an .on() call. This way, the clicks are handled for current and future elements:
$('#mytable').on('click', '.hist-tag', function(){
var ID=$(this).closest('tr').attr('id');
itemid=$("#itemid_input_"+ID).val();
dataString = '?rec_id='+ID;
$('#item_hist').load('query.php' + dataString);
});
This attaches a handler to an element that you know will always exist #mytable, or whatever the ID of your table is, and then watches for clicks on children that propagate to the table and filters them on the selector you provide, i.e. .hist-tag.
Again, I am guessing, but that's what it seems like is happening from the evidence I have.
I suspect your click event is somehow being re-bound on each return.
Perhaps the same script is included in the response from your load call?
Try this:
$('.hist-tag').off('click');
$('.hist-tag').on('click', function(){
var ID=$(this).closest('tr').attr('id');
itemid=$("#itemid_input_"+ID).val();
dataString = '?rec_id='+ID;
$('#item_hist').load('query.php' + dataString);
return false; // prevents bubbling the click to the container
});

Ajax breaks jQuery scripts on page

I'm currently working on a website that you'll find here: http://steadfastdesignfirm.com/rgw/. I used an ajax effect that I found online at CSS-Tricks to dynamically load content from another php page and animate it (fade in and fade out) when a navigation tab is clicked.
I have managed to get this working fine, as you will see (please note the only two working pages are "Home" and "Experience RGW"), however, all of the jQuery scripts in my document that apply to elements within the div that reloads are broken when the content is dynamically generated.
As a quick example, take a look at the text resize tool beneath the image rotator on the home page and try changing the font size. Now, click on the "Experience RGW" tab and scroll down to the text resize tool again. Notice that now that we've loaded in experience.php dynamically within the "#ajax" div, the script doesn't work. Also, if you click on the "Home" link now, you will also notice that the image rotator doesn't work.
I've looked high and low online and through multiple forums to try and figure out how to fix this, and I believe I have to incorporate the jQuery .live function, to apply the script to any element, whether it's currently visible or not. Otherwise, document.ready only runs the scripts once after the DOM loads and will not affect the ajax loaded content. Is that correct? If so, how do I apply that to multiple jQuery files executed on my page?
Well, this is totally driving me crazy and I've tried hard to get it, but I just can't quite figure it out. I'm fairly new to jQuery, but am trying to learn fast. I would post some of the code here, but there is a lot involved in this question. :)
If anyone would be willing to shoot out a quick answer, or a few lines of code, I'd greatly appreciate it.
FYI: The script that runs the ajax effect is in ./scripts/page.js. Also, please remember that I currently have only the Home page and Experience RGW page working correctly, so please don't waste time trying to diagnose problems on the other pages. I haven't gotten to them yet. :)
Here is a link to some of the code on jsfiddle: http://jsfiddle.net/taylortsantles/R33YV/.
Thanks,
Taylor
I'm behind a proxy and can't see your page, but it sounds like the events are not being re-attached to the content created through ajax.
I'll try to explain, when your page loads the first time, you are attaching jQuery events to DOM objects on document.ready(), this function will be called only once.
Every time you drop DOM objects and create new ones with the ajax response, these new objects never get jQuery events attached again, since the document.ready() function didn't fire.
You can try putting your event-attaching code in a different function and invoke that function on document.ready() AND after every DOM modification (your ajax call to change the tab content).
Hope it helps.
The problem is a breakdown in the order of executing code.
page loads
load event fires and sets up elements
click event
ajax loads the new page
The new page doesn't have any events set to it. Two solutions
use "live" links in the window.load event callback
use run the page load code again.
Solution 1 is nice but if you have an specific plugin used then it won't be the total solution.
Solution 2 can be implemented by pulling out your code in window.load and wrapping in another function. Just all it onload and then in the callback when the ajax loads.
I know how frustrating is can be. I hope this helps.
You need to rebind any events after dynamically loading in elements to a page, as Javascript sees these as totally new DOM elements.
You can achieve this by modifying the code you use to update the page:
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
$mainContent
.find("#ajax")
.fadeOut(200, function() {
$mainContent.hide().load(newHash + " #ajax", function() {
$mainContent.fadeIn(200, function() {
$pageWrap.animate({
height: baseHeight + $mainContent.height() + "px"
});
});
$("nav li").removeClass("on");
$("nav a[href='"+newHash+"']").parent().addClass("on");
// Rebind any events
documenttextsizer.setup("text-resize");
});
});
};
});
This applies to any events that happen WITHIN the updated elements in the page. So after the comment "//Rebind any events" you can add others as they are required! Hope that helps :)

Jquery Ajax calls fail after first call success?

I'm build jquery to build a custom email system (left pane list of messages - right pane the selected or current message) ....
After an Ajax call is made (for example - the message is deleted and the left pane is reloaded using .load to update the list), calls from there fails from there (its as if the reloaded content doesnt see the ajax on the page anymore... and nothing happens)
Below is an example of the jquery that deletes the mail. The deleteMail script also echos the updated list..
$('#leftmail').html(loading).load('/pages/mail/async/deleteMail.php',{'id' : id });
Does anyone have any ideas why this would happen? It is a .load things specifically?
Please help! Thanks!
F
Binding events to elements only happens once. When you load the pane via AJAX, those events are lost and not recreated on the newly fetched elements.
The jQuery live() function is designed for this. Instead of $('element').click(function() {}), you'd do $('element').live('click', function() {}) to have those click events work on content loaded after the initial domready event.

Categories