Jquery code not executing on elements that didn't exist on page load - ajax

I have a web application that loads javascript on page load:
$(function() {
$('.modal-delete').click(function() {
alert();
});
});
I have a html page with a series of buttons which alert a blank message box when they're clicked:
<button class="modal-delete btn danger"></button>
which works fine.
However, a have some AJAX calls that generate more buttons just like the ones above but NOT on page load! They can be created at any time. These buttons do not do anything but they're meant to load the alerts. They're identical but because they never existed on page load, the Jquery code doesn't work on these buttons. How do I attach the same code to these buttons too?
Many thanks :).

I think you'll want jQuery's 'live()' function:
$('.modal-delete').live('click', function() {
alert();
});
This binds to the elements which match but also rebinds when new elements are added in the future:
"Attach an event handler for all elements which match the current selector, now and in the future"

Change the ready code to this...
$(function() {
$("document").on("click", ".modal-delete", function() {
alert("click");
});
});

Related

Ajaxinate Endless scolling has stopped product Quick View from working

I am using Shopify "Streamline Theme" with quick product view and I recently added infinite scroll to products on each collection using Ajaxinate.js.
When I open a collection page it loads with some products which is supposed to do, The products already there work fine with quick view and quick add to cart and also.
The Infinite scroll works fine and it loads new product fine but the problem is raised when the new products loaded through AJAX call doesn't have work with the quick view function.
I have tried to create a callback function to activate the quick view with no success, using the theme initialisation code with no success.
function callBack(){
theme.init();
theme.initQuickShop();
};
document.addEventListener("DOMContentLoaded", function() {
var endlessClick = new Ajaxinate({
method: "scroll",
loadingText: 'Loading...',
callback: callBack
});
});
Edit -------
My problem, is that when the page is loaded only the initial loaded products quickview elements are loaded in the DOM. When the scroll more button is clicked, the newly loaded products are loaded without their respective quickview elements. Hence why the quickview does't work for them. The theme.js file comes with this initialisation code:
theme.reinitProductGridItem = function($scope) {
if (AOS) {
AOS.refreshHard();
}
if (theme.settings.currenciesEnabled) {
theme.currencySwitcher.ajaxrefresh();
}
// Reload quick shop buttons
theme.initQuickShop(true);
// Refresh reviews app
if (window.SPR) {
SPR.initDomEls();SPR.loadBadges();
}
// Re-register product templates in quick view modals.
// Will not double-register.
sections.register('product-template', theme.Product, $scope);
// Re-hook up collapsible box triggers
theme.collapsibles.init();
};
I have tried to integrate this into a callback but no success, the quickview modal doesn't seem to load for the newly loaded products:
function callBack(){
ReloadSmartWishlist();
var $container = $('#CollectionSection');
theme.reinitProductGridItem($container);
// I have tried the following init qith no success:
// theme.init();
// theme.initQuickShop(true);
// theme.initQuickShop();
// sections.register('product-template', theme.Product, $container);
// AOS.refreshHard();
};
document.addEventListener("DOMContentLoaded", function() {
var endlessClick = new Ajaxinate({
method: "click",
loadingText: 'Loading...',
offset: 0,
callback: callBack
});
});
I am missing something but what? :/
Note for other things like loading products images with the callback and the wishlist app, it works as intended...
When you load elements via AJAX and if the events are not attached to a parent element that is not removed from the DOM, those elements will not have an attached event to them.
The term used here is event delegation.
Here is an example of non-delegated event:
document.querySelectorAll('a').addEventListener('click', function(){
// Do something
})
Since you are attaching the event to the existing "a" elements if you add new 'a' via AJAX those elements will not have the event since Javascript already attached all the events and it will not reattach them if you don't specifically recall them again.
Here is an example of a delegated event:
document.querySelector('body').addEventListener('click', function(target){
let target = event.target;
if (target.tagName === 'A'){
// Do something here
}
})
Where we attach the event to the body tag ( where it's a better idea to attach it to a closer none-modified parent element of the ajax items ) and once we click we check if our target tag is an "a" and do something then.
So long story short, you will need to delegate the quick cart link so that it works after you load the items via AJAX.
Drip is correct you need to delegate your event, but for people like me it's hard to completely understand how to do that.
I'm not sure how your quickview is structured, but if you open it with a .click function and can use jquery use the [.on() function][1].
For example: I use a quickview that opens on a button click. My button is attached to my product-grid-item.liquid with this bit of code:
<div class="quick-view-button">
<a class="quick-view" data-handle="{{ product.handle }}" href="javascript:void(0);">Quick View</a>
</div>
My quickview function originally looked like this:
function quickView() {
$(".quick-view").click(function () {
//all of the quickview code
What happens is exactly like you described. The event listeners only loaded on the first product load but nothing after an AJAX load.
Using jquery's .on() binds the event listener to the element meaning when it's loaded in later it'll still have the event. Here's an example of what my code looks like after using .on()
function quickView() {
$('body').on('click','.quick-view',function(){
I really hope this helps you or someone else with this problem.
[1]: http://api.jquery.com/on/

jquery.mobile: no event triggered when loading an external page into the dom

Ok, first off do NOT confuse my use of the word "external" with the keyword external used in anchor tags. That's NOT what this is about.
I have a multiple page document and everything there works fine. I also have several other .html pages that are rarely ever used (i.e. about page) so I don't want to clutter the dom with them but rather load them as needed.
So, starting with the about.html page, when loaded, this page will (or should) give some info about the device it's running on as well as the version number of my app and whether or not there's a later version available (some people turn off automatic updates).
Before I go further, I want to put it on the record that the about.html page is working in another app when it's loaded with the rel="external" attribute set but I'm trying to move away from that.
So, inside my index.html I have a header with a nav bar and the anchor tag is straight forward:
<div data-role="popup" id="homeMenu" data-theme="b">   
     <ul data-role="listview" data-inset="true" >
        <li>About</li>
When I run the app in a simulator, the about.html gets loaded into the dom and becomes the active page so that part is working but not one event that I can figure out gets triggered.
I have tried all of the following:
$("body").on("pagecontainerbeforeshow", function( event, ui ) {
console.log("Going to: " +ui.toPage[0].id);
});
$(document).on('pagecreate', function() {
$(':mobile-pagecontainer').on('pagecontainerbeforeshow', function(event, ui) {
console.log('pagecontainerbeforeshow triggered');
console.log("Going to: " +ui.toPage[0].id);
});
});
// $( "#aboutPage" ).on("pagecontainerbeforeshow", function( event ) {
$( "#aboutPage" ).on("navigate", function( event ) {
console.log("aboutPage Ready!");
initMenu();
onAboutReady();
$('#aboutPage').on("swiperight", function () {
// I know, I know... one step at a time ;-)
window.location.href = 'index.html';
}); 
});
I would imagine that I can't attach an event handler to the about page as the about page doesn't yet exist in the dom so there must be another way to attach an event that actually gets fired.
What am I missing here?
Turns out the answer is easier than one might think! Instead of trying to trap an event for specific page that's not in the dom, simply trap the event for all pages, add in a switch statement and viola!
$("body").on("pagecontainerbeforeshow", function( event, ui ) {
console.log("pagecontainerbeforeshow -> Going to: " +ui.toPage[0].id);
switch(ui.toPage[0].id)
{
case "aboutPage": // <div id="aboutPage" data-role="page"
break;
}
});

Eventlisteners for jqm side panel on multiple pages

I am new to JQM and I'm using Phongeap with JQM for a new project.
My javascript is in one single js file and I'm loading the views from multiple html files.
As the transitions of the siede panel are poor, when I change pages via <a href="page2.html"> I tried to to use event listeners for the Menuitems.
function setPanelListeners(){
$('#menu_search').click(function() {
switchPageTo('search.html');
});
$('#menu_schedule').click(function() {
switchPageTo('program.html');
});
$('#menu_news').click(function() {
switchPageTo('news.html');
});
}
I call this function on the pagebeforeshoe event of each page. To fix the transitions to the way I need it, I use this function
// Close Panel then change page
function switchPageTo(url){
$('#menupanel').panel('close');
setTimeout(function() {
$.mobile.changePage( url, { transition: 'fade'} );
},200);
}
So here is the Problem. It actually works fine on the first page. But on the second page the Menuitems won't work, I guess the event listers are not listening for the new panel, because in the html the panel is loaded twice! And the Event listeners only listen for the first panel (from the first page) which is not displayed on the second page.
Any help is appreciated!
Are you adding panel dynamically on the second page? In JQM 1.3 you have to add panel separately to each page, although this restriction will be removed in future versions.
Use event delegation for dynamic panels:
$(document).on('click' ,'#menu_search' function() {
switchPageTo('search.html')
});

javascript not executing in (with ajax) loaded link

I'm loading page.php into a div with ajax.
page.php contains some javascript and shows when I load the page in a single window. But when I load it into my website it doesn't show the javascript. (I have added some other code to check but only the Javascript is not working)
$('#winkelZELFlink').click( function() {
alert('U komt nu bij onze webshop.');
$.get('http://www.weetzelf.nl/?page_id=147', function(winkelLINK) {
$('.content').html(winkelLINK);
});
});
Javascript events added to elements before they exist on the page doesn't work. Luckily jQuery can take care of that with the $.fn.live() function, which delegates events for existing items and items that will be added later, after the code is executed.
Your code should look something like this:
$('#winkelZELFlink').live('click', function() {
alert('U komt nu bij onze webshop.');
$.get('http://www.weetzelf.nl/?page_id=147', function(winkelLINK) {
$('.content').html(winkelLINK);
});
});

Ajaxed div hide and show hides only after div load

I have this issue. I'm working on a jquery ajaxed site. I have the main content div in the middle and on top the navigation. I need to AJAX the content, because I have flash backgound so that the flash video won't start from beginning after every page load. The only way I was able to do this was with this sort of code:
$(document).ready(function(){
$.ajaxSetup ({
cache: false
});
//For loading
var ajax_load = "<img src='img/load.gif' alt='loading...' /><p>";
// Var
var loadPage1 = "page1.html";
// Load page
$("#page1").click(function(){
$("#content").hide(2000);
$("#content").html(ajax_load).load(loadPage1);
$("#content").show(2000);
});
All other ways to get the div didn't work because there was issues on getting plugins etc. working in the ajaxed div (content).
So... everythig is working fine - but, the div loads it's content from page1.html and shows it and only after this does it hide it and show it. So it loads the page and then does the effects I want to.
Do I need to queue this some how or what's the proper jquery way? I tried delay, stop etc.. but can't seem to solve this out. It's propably very simple.
Thanks.
Show the element in the load callback handler.
i.e:
$("#page1").click(function(){
$("#content").hide();
$("#content").html(ajax_load).load(loadPage1, function(){
$("#content").show(2000)
});
});
.load() takes 2 arguments, the URI and a callback to fire after load.
API is found here: http://api.jquery.com/load/
function() {
$("#content").hide(2000);
$("#content").html(ajax_load).load(loadPage1, function() {
$("#content").show(2000);
});
}

Resources