jQuery .on() not binding to all future events - javascript

I am trying to figure out why jQuery is not binding to all future 'click' events on my page. It only works the first time I do this. The AJAX request fires, and displays adds the correct data to the DOM, however any subsequent attempts do not fire. When I select a button 'View All Dealerships', the AJAX requests returns JSON array of the dealerships and displays them on the page.
$(function(){
$("body").on("click", "#all-dealerships", function(e){
let path = $(this).attr("href");
$.ajax({
url: path,
dataType: 'json',
success: function(response){
var source = $("#dealerships-template").html()
var template = Handlebars.compile(source)
var result = template(response)
var a = () => document.getElementsByTagName("body")[0].innerHTML = ""
a()
document.getElementsByTagName("body")[0].innerHTML += result
}
})
e.preventDefault()
})
})
The variable names and structure is just for testing.
Body is a static element that does not change. I tried wrapping the button in a div and using that as the parent object that binds the event, however I get the same result. The page loads just not with AJAX. The event only gets bound when I do a full page refresh. Navigating to other pages on the site does not fix the problem.
The button that triggers the AJAX request is not present when the new elements are added to the DOM. It gets removed. The action of navigating back to that button does not re-trigger the click event.

What you are doing is
You are binding an event and in ajax call you are removing all elements inside the body, however it may be possible that dummy 'div' element can be present in DOM.
So due to this and you binded an event on id (which binds event only on one element) your click is not triggered
So what you have to do is,
Insted of
document.getElementsByTagName("body")[0].innerHTML = ""
AND
document.getElementsByTagName("body")[0].innerHTML += result
Do this
$('body').empty();
AND
$("body").html(result);
this will make sure that all elements inside the the body will be removed.

What ended up fixing my problem was changing the event bind to $(document).on(...) instead of $('body').on(...)
When the new HTML content was appended to the DOM the button that triggered the AJAX request was no longer available. Navigating back to the page where the button existed did not trigger the event bound to the body element. Targeting the document ensured that the event would re-fire each time.
Does AJAX loaded content get a "document.ready"?

Related

Attach event listener with e.stopPropagation() to dynamic elements in javascript

I'm trying to insert html elements dynamically to a list that is already created, but the new elements that I'm attach them event listener
$(".").click(function(e){} they don't get the event.
the process :
get more ads(posts) when the user scrolls down (Infinite Scroll Pagination)
getting data with ajax request from the controller
the controller renders the new elements and returns html to the ajax
the html with the new posts appends to the web
in the end - every ad(post) that inserts dynamically needs to trigger popup function
I tried to use $(".").on(click,function(e){}, but I also need to use e.stopPropagation(); but this event doesn't support that method.
Solution would be really appreciated.
images:
1) get more ads(posts) when the user scroll down(Infinite Scroll Pagination) gettin data with ajax request from the controller and then appends him
2) the controller render the new elements and return html to the ajax
3)the html that render in the controller
4) the open and close popup event listener that i cant attech to the new dinamic elements
[]
I succeeded!
i used onclick="get_images(); event.stopPropagation();"
inside my html
another option is onclick="get_images(event);"
and inside the function
function get_images(e){
e.stopPropagation();
}
and then all the dynamic elments gets the function with e.stopPropagation()

anchor tag onlick event called automatically in jquery

I have question regarding this jquery code block. What I am doing is, onclick on anchor tag, I am creating a anchor tag element and appending it to 'currentFilters' div element.
While debugging through firebug, I can see that anchor element is getting added to the div, then jquery automatically calls onclick again so my anchor tag gets created twice.
Not sure how onclick event is triggered again automatically.
Also, on page load, this functionality works as expected.. But then I am doing ajax call to the server and creates more elements in the same page. then it doesnot work,,
$(document).ready(function() {
$(".matchTypeCheckbox").click(function() {
var parent = "parent_" + $(this).attr('id');
$('#' + parent).removeClass("").addClass("active");
var newElement =
"<a tagid='"+ $(this).attr('id')
+ "' tagtype='mt' href='#' class='rTag'><span class='rTag'>X</span>"
+ $(this).text();
+"</a>";
$('.currentFilters').append(newElement);
});
});
it works fine on page load, only doesnt work after ajax call
and
But then I am doing ajax call to the server and creates more elements in the same page. then it does not work
When you call
$(".class").click(function() ...
it binds that anonymous/inline function to all elements with class "class" (in this example) - that exist at the time the click() is called.
This is why we use $(function() { (or $(document).ready, same thing), so that the click event is wired up after the DOM elements have been created and they already exist (to have the event attached).
If you then create new elements
$('.currentFilters').append(newElement);
the previous call on document ready has already been called so is not applied to the new elements.
There are two ways around this:
After calling append, also attach the click event handler (this works best with a separate function rather than anon/inline), something like (untested, ottomh) :
$(function() {
$(".class").click(clickHandler);
});
$('.currentFilters').append(newElement);
newElement.click(clickHandler)
or using event delegation, something like:
$(function() {
$(document).on("click", ".class", clickHandler);
});

onclick element for an element that is not created yet

I am using the google search API and I want that when you click on an image, this image will be copied to a different location.
I created a fiddle here: http://fiddle.jshell.net/wjewg062/
It works this way: The user types in a term in the input field and images will be displayed. When he/she clicks on one twice it will displayed in the image div.
I put the onClick event listener on to the searchresults div, hence the extra click in the beginning. However, I want it to be displayed on the first click.
Now, if I comment this out
var searchresults = document.getElementById('searchresults');
searchresults.addEventListener("click", function(event){
event.preventDefault();
imageing();
});
it doesn't work. The images will be links. I believe the reason for this is that the results are displayed in gs-image-box and not created yet. I tried calling the imaging function in different other functions like the searchImg or the OnLoad but nothing work.
I thought of using a check if element is clicked function described here Detect if I'm clicking an element within an element
but I think there must be an easier way.
I'm running out of ideas, can anyone give an idea or hint?
Thanks !
The images are dynamically created right? Check out this post Event binding on dynamically created elements?
In short, events are attached to elements upon pageload. so a newly created dynamic element such as the ones that google creates, aren't attached to the event. so google probably has a way to circumvent the whole "you need to load the page to attach events to elements" thing but it requires an extra click. Using the syntax found in the post should help you.
By the way. Using Jquery doesn't really show down your site because it's usually cached in the client's browser.
The info you need is already in your searchresults eventListener. The target of this event will be the image you click, even if you add the event on a div higher in the structure.
A javascript event will by default be dispatched from the top element (window) all the way through the element that received the click, then will go back to the top. Any element that is an ancestor of the element that was clicked will receive the event info, so you can listen on any ancestor, but the target remains the element that was actually clicked.
In your case, by simply passing the target to your imageing() function, you can apply the behaviors you want without any extra manipulations.
One problem you might face, is if user clicks on searchresult but not on an img element. Then you'll have a bug, so you should handle these cases.
Something like this:
var searchresults = document.getElementById('searchresults');
searchresults.addEventListener("click", function (event) {
console.log(event.target, this);
event.preventDefault();
if(event.target.tagName == 'IMG'){
imageing(event.target);
}
});
function imageing(targetImg) {
var imageresult = document.getElementsByClassName('gs-image-box');
var xu = document.getElementById('companylogo');
var imgsrc = targetImg.src;
xu.src = imgsrc;
}
http://fiddle.jshell.net/pwjLrfnt/3/

Why does jQuery alls Alert() more times?

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);
});

Can a page event be persisted across a page load?

I have a page which, when a user clicks an icon, launches a second window to update some database entries. When the child window is opened, I'd like to attach an event to fire a callback function and update a field on the parent screen. At the moment, the javascript is similar to:
var child = window.open(URL);
child.name = reference; // used to store parameters about which field to update
$(child).on('unload', function() {
var w = this.name.split(':');
fieldUpdate(w[1],w[0]);
});
// also tried ...
// child.onbeforeunload = function...
// child.onunload = function...
// child.onclose = function...
The problem is that the child page, which is used elsewhere and cannot be changed, used an <input type="submit"...> to initiate the postback and update the database. The controller method then reloads the view, which, obviously, clears all the events. So the callback only gets called on the first update.
From my testing, the onbeforeunload gets called before the controller postback, the onunload gets called after, and the onclose doesn't get called at all when using the submit. In all cases, the child.name property persists into the reloaded page, but all events are cleared.
Is there any way that the parent window could set up an event (or reinstate it) so that the callback fired whenever the submit action occurred? I've tried playing around with setting a timeout callback, but there seem to be problems with getting/retaining the child window parameter.
Update:
For information, the method I wish to call is similar to (actual code has more error checking etc.):
fieldUpdate: function(fieldName, id) {
$.post(
baseURL + 'getField',
$.param({id: id, name: name}, true),
function(json) {
$('#' + json.Values.name + json.Values.id).val(json.Values.count);
}
);
}
This is in answer to Julian's comment about using AJAX. As you can see, I already do, but it's how to trigger the call from the clicking of a 'submit' button in the child page that I'm having trouble with.
If I could modify the child page, this would be fairly easy, but, unfortunately, that's not an option as it would break too much other code.

Categories

Resources