How can I both trigger and bind to an event after the page load?
The problem I am having is that in one place, on page-load I fire an event:
//producer.js
pageLoaded(){
var e = jQuery.Event("eventA");
$("body").trigger(e);
...}
and in another I bind to it:
//consumer.js
pageLoaded(){
$("body").bind("eventA", function(args){console.log("Got it!");} );
... }
The problem is that the first time event is fired (when page is loaded) - the consumer does not see it. The second time event is fired, however, everything is fine!
I am guessing this is because event is actually fired BEFORE consumer starts listening to it.
Is there a good practice to follow when creating "triggers" and "listeners" to events - that have to work both on page load, and later?
If there are no listeners when you triggered an event nothing will happen which is why you are not seeing anything on the first trigger.
Sounds like you need to control the order of document.ready() calls .. perhaps the responses to this question or this article might assist you
Using something like RequireJS will allow me to first load one javascript file, and then another.
So I can make producer.js dependent on consumer.js
Related
I don't even know where to begin. I'm using Kendo Grid to list data sourced from a server. Everything is fine on first load including when I add additional functions and dom elements in the dataBound function. Calls to the server seemingly update (sync) the Grid just fine. BUT, it seems the dataBound function is called an additional time the second time round. Performing an on click function coded in the dataBound performs it a total of 4 times. How do I test for where the issue is and what do I need to destroy to stop this infuriating behaviour?
I don't even know what code to give you save for pasting in my whole website. What is the underlying theory behind this behaviour because there's obviously something I am fundamentally missing about how javascript, and therefore Kondo, works? How do I test for this, please. Thanks!
A quick solution might be to use off() then on() in the databound e.g.
$(".cell").off("click").on("click", function(e){ ... });
this will get rid of previously attached handlers and ensure you only have one.
Even better, use event delegation outside of the Grid generating code.
$(document).on("click", ".cell", function(e) { ... });
With event delegation, the target of the event does not have to exist at the time the event handler is setup. In the example above, the click is on the document object which already exists, but the handler will only fire if an element with the class 'cell' is actually clicked. You can define this handler once in the document.ready before the grid is even created.
I have the following scenario where I need to run some "code" when entering a page for the first time or returning to it from another page.
Safari's cache feature (https://webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/) is causing that, since it is caching my page and not executing anything.
I followed their recommendation of adding an event listener to 'pageshow' event, this way I can check if that event is persisted and then run what I need.
This example is basically what I'd like to have:
first page access... attach the listener = Cool, I have that.
if I navigate out of the page and get back (using Safari) it will fire my listener on pageshow = Cool, I have that... almost.
the listener should be fired every time that I navigate back to that page = Not cool, my listener fires once.
I'm using react and componentDidMount() is where I'm preparing everything:
It works for the first time.. I'm able to navigate out of my page and get back to it + executing what I need.
The problem is: repeating the "navigate out of my page and get back" a second time won't do anything.. looks like the listener gets deleted or something.
After two days trying to find a way... my coworker asked me to try a listener on 'popstate'. I was so into trying to get the 'pageshow' listener to work that I completely forgot to test that one; it worked flawlessly:
window.addEventListener('popstate', function(event) {
I'm pushing values from website to Facebook through GTM, but I don't have access to make code changes on server side.
So every value that I need to send to Fb I have to find using Custom Javacripts in GTM.
I can get those values in console but I don't know why I can't see them in Debug mode. It's always undefined.
Here is one of the code in GTM:
function() {
var prod = document.getElementById("product_addtocart_form").elements.namedItem("product").value;
return prod;
}
So what am I doing wrong?
Assuming that line of code works in console, I suspect the code in your function is being fired too early and the elements aren't ready yet.
Make sure your code is not fired until the gtm.dom event is fired, if that still doesn't work then wait until gtm.load is fired. If that still doesn't work then have a look at when these elements are actually ready (maybe they're created using an AJAX call?).
If the gtm native events aren't late enough, when you know the elements are ready you should fire a custom event into your dataLayer which triggers your tags and repopulates the variables. Hopefully this will ensure your variables are populated correctly when your tags are fired.
If the elements are loaded using jQuery AJAX you should be able to bind to the ajaxComplete event on the document. See the jQuery docs. You would then fire a custom event into the data layer which would trigger the tags that using the data in the variables that should now be populated. You'd set up a trigger with type=custom event and the value being 'ajax_complete' (or whatever you call your event).
Your code would look something like this:
$(document).on('ajaxComplete', function(){
dataLayer.push({'event':'ajax_complete'});
});
If there's multiple AJAX events being fired on a single page then you'll have to write some logic to differentiate between calls and/or make sure you don't fire it multiple times. There's also a setting in tags in GTM to say 'only fire once per page load' so you could leverage that as well.
I am developing a jQuery Mobile and PhoneGap app. I am using this code:
$('#contact').live('pageinit', function() {
//$.mobile.loading('show');
theme();
getData('contact/list',contactList);
//$.mobile.loading('hide');
});
When accessing page for the first time, it works good. In second attempt event is firing multiple times. I tried using bind but it doesn't work.
I think it is connected with live event. It is binded each time I initialize the page, which makes it multiple. Problem is solved when linking that way: window.location.href-it recreates DOM. Unfortunately I can't use it.
Is there any way to handle pageinit in another way?
I tried to find it earlier but with no success. Also looked at: click() firing multiple times
In theory, any event that can be bound by 'live' can be bound directly. The benefit of binding directly is that it will (iirc) overwrite the previous bound handler. As such, you would only have one handler, so it wouldn't get triggered multiple times on subsequent loading.
try something like:
$("#contact").pageInit(function() {
theme();
getData('contact/list', contactList);
});
I usually use the on() method instead of live() (which is now deprecated). I give each of my page containers an id, so on the index page it might be index, then I can bind to the event like:
$(document).on("pageinit", "#index", function() {
//do stuff here
});
Works same way for page show also.
When binding events in jquery mobile, you have to be very cautious as to ensure that they will not be bound multiple times. Navigating to a new page in jquery mobile will not "reset" the bound events as it would in more traditional navigation.
The issue your facing is most probably due to the function being bound to the event every time you access the page, meaning that the more you access the page, the more times you will get that function to be executed when you do.
In order to ensure the event is only bound once, I would recommend binding in the header of your initial page. This way, the event is bound once and for all, and the function will be run whenever this page is initiated.
You can try adding data-ajax="false" to any forms you are submitting that may be creating multiple versions of the page (firing events multiple times).
I have a page which has two different event listeners picking up click events from inside the page. One listener is generic to the site, the other is specific to the page. Recently, a link was added which runs through the first handler, which processes it, opens the url in a new window and then stops the event. The problem is, the second handler then executes, stops the event again and somehow the event continues and executes.
I have stopPropagation, and cancelBubble both executing on this event. When it arrives at the second handler, it has a prevented field which is set to true, but still it carries on. The only way to stop it is to put a check in the second handler which skips its code if the event arrives with prevented set to true.
My question is, why would this happen at all? Why is stopPropagation not working? This happens in all browsers, BTW.
I suppose you try to stop event from firing on the same element. Have you tried to use stopImmediatePropagation method?
As Samuel Liew correctly commented, adding return false; to the end of your first event handler might do the trick. This is because some browsers ignore the .stopPropagation() (However, others will ignore the return)