JavaScript is loading 3 times on Rails application - javascript

I have an ajax function that is being called multiple times on click when it should just be firing once.
$(document).on('click', '.newGameItem', function() {
console.log('start click event');
var apiUrl = $(this).attr('data-api-string');
var callType = $(this).attr('data-api-post-call');
var apiKey = $(this).attr('data-api-key');
var dataType = $(this).attr('data-api-data-type');
var returnValue = $(this).attr('data-return-value');
var currentGameWrapper = $(this).parent().parent().parent();
console.log('before api call');
getNewItem(apiUrl, callType, apiKey, dataType, returnValue, currentGameWrapper);
console.log('after api call');
});
This click event is inside a turbolinks load event:
$(document).on('turbolinks:load', function() { ... }
I put in a console.log at the top of the turbolinks load event and can confirm that the JavaScript in this file is running 3 times. I've noticed this happens when I am on this page, click a link to another page and then hit the back button to this page but it also happens when I click to the page from somewhere else in the app.
This file is being compiled through the asset pipeline and we have data-no-turbolink on the body tag (which has actually never seemed to do anything.
Any ideas why this is happening or ways to get around it? Taking turbolinks out of my app completely is not an option for me at this time.
Thank you

That click event has to be outside the 'turbolinks:load' event, that's the point of attaching it to $(document) as opposed to the element. If you have it inside it will create it every time a page loads. Your javascript should look like this:
$(document).on('click', '.newGameItem', function() {
// ...
});
$(document).on('turbolinks:load', function() {
// ...
});

Related

My Dynamic Ajax site is overloaded with multiple getScript calls

I have a dynamic website where all links grab new sections via an ajax request from other pages and replace the current section.
My problem comes in two forms. When I load a new div from an Ajax get request. Some sections need js files too. For example, one uses a particles.js as a canvas background. After I complete the ajax request I then getScript"js file" and it works. However if you move onto other sections that getScript is still running and now unbinded because that section is gone. If I go back to that section again I need to getScript again and now I'm running it twice. This can be very CPU and GPU intensive and slows down my site.
Things like css files are easy because I can create an if statement to load if its not already loaded, script tags are different because the Dom only loads once. Appending/removing the script to the head is useless because the site is entirely Ajaxed.
here is example of a script
//pricing.html
$(".link-pricing").click(function (e) {
e.preventDefault();
$("#togglenav").collapse("hide");
$("#main").load("../../damonmedek/home/pricing.html #main-pricing");
$(document).ajaxComplete(function (event, xhr, settings) {
if (settings.url === "../../damonmedek/home/pricing.html") {
//Add CSS
if (!$("link[href='../assets/css/home%20css/pricing%20css/particles-js.css']").length)
$('<link href="../assets/css/home%20css/pricing%20css/particles-js.css" rel="stylesheet">').appendTo("head");
//Remove CSS
$('link[rel=stylesheet][href*="../assets/css/home%20css/best-carousel-slide.css"]').remove();
//Add JS
$.getScript("../assets/js/home/pricing%20js/modal%20popup.js", function () {});
**$.getScript("../assets/js/home/pricing%20js/particles.js", function () {});**
$.getScript("../assets/js/home/pricing%20js/pricing-animated%20heading.js", function () {});
$.getScript("../assets/js/members%20js/ajax%20members-only.js", function () {});
$.getScript("../assets/js/home/pricing%20js/app.js", function () {});
$.getScript("../assets/js/members%20js/ajax%20members-only.js", function () {});
}
});
});
How can I rebind page to js file, or stop getScript, or some smarter way to fix this problem?
Its not just cpu problems, duplicate getScripts can cause problems like posting twice on submit and weird stuff like that.
So this answer isn't as simple as I thought. Its involves event propagation which I encourage you too look up.
In order to grab the script just once its can't be through jquery but something like this.
function loadJSFile() {
if ($('script[src="' + jsFile + '"]').length > 0) {
//script exists
} else {
function loadScript(url, callback) {
// adding the script tag to the head as suggested before
var body = document.getElementsByTagName("body")[0];
var script = document.createElement("script");
script.classList.add("example");
script.type = "text/javascript";
script.src = url;
// then bind the event to the callback function
// there are several events for cross browser compatibility
script.onreadystatechange = callback;
script.onload = callback;
// fire the loading
body.appendChild(script);
}
var myPrettyCode = function () {
// here, do what ever you want
};
loadScript(jsFile, myPrettyCode);
}}```
Then you need to use a bubbling method to click on things. like a div that is flown in and out and flown in and out. the js file is only loaded once but you are clicking through the main div that is loaded on first page load. And into the div you flying in, that contains the ids and classes you have inside that div. kinda confusing I know.
```$("#home-div").on('click', '#ajaxedInDiv', function (e) {
$("#ajaxedInDiv").attr("something");
}

Invoke a javascript function after page loading is finished?

I use CookieBot in our html pages. CookieBot javascript doesn't load in test environment and throws a net::ERR_ABORTED 404 error.
When this happens, the loading spinner in the page keeps displaying after the page loading has been completed.
I tried following options to invoke a listener after page loading is completed. But none of them works:
document.addEventListener("load", (e) => {
console.log("document load");
});
document.addEventListener("DOMContentLoaded", function(event) {
console.log("DOMContentLoaded");
});
$(document).ready(function() {
console.log("ready!");
});
$(document).ready(function() {
console.log("document is ready");
});
$(window).on("load", function(){
console.log("window load!");
});
window.onload = function () {
console.log("window onload!");
};
I guess CookieBot script overrides my listeners. Here is an example where listener is not invoked. When you remove the CookieBot script it runs: https://jsfiddle.net/hkarakose/4by26Lr3/1/
How can I invoke a function after page loading is finished?
You can invoke a function after page loading with:
window.onload = function() {
//here you can write your function and invoke it.
}
Edit:
Maybe I didn't understand your request, but now I'm reading more carefully.
The problem is in the script, right? If you insert the script on HEAD, it will be loaded first.
You could insert the type of the script in this way:
type = "text / plain" with a data-attribute: data-attribute = "script-cookie".
Then change the type once everything has been loaded, like this:
window.onload = function () {
       var allPrefScript = document.querySelectorAll ("script [data-attribute =" script-cookie "]");
allPrefScript [0] .setAttribute ("type", "text / javascript");
}
Although #davilink92's answer works, I solved this issue in a more practical way.
I attached external script loading to window load event:
window.addEventListener('load', function () {
$.getScript("https://consent.cookiebot.com/uc.js?cbid=d180eb7a-8f13-4549-bacc-6d4a6dfb5da8&culture=en");
$("#global-loader").fadeOut("slow");
});
In this way, the script couldn't prevent the window load event listener to be invoked by the browser. And thus, I was able to remove the loading spinner after page is loaded.
I have the habit to use document.addEventListener("load", (e) => {console.log("loaded"); })
Can you show us more code to see if your problem is here? I think all of yours tests are correct and I dont understand why it isnt working.

How to wait to finish loading page on button click using JavaScript/JQuery?

I am having an Anchor link, on click of Anchor link, I am registering new JavaScript file html page.
On registering the JavaScript file dynamically, document is reloaded partially (As I see reload icon in browser for some time).
I want to call my JavaScript function once the script got registered (Obviously when reload icon get stopped in the browser). But the function MyJavaScriptFunction got called while document is still reloading.
Using setTimeOut resolves the issue but I don't want to use it as page loading time is not fixed. Please help.
The code I am using is as follow:
function addScriptDynamically(src, callback) {
var s = document.createElement('script');
s.setAttribute('src', src);
s.onload = callback;
document.body.appendChild(s);
}
addScriptDynamically('URL Of JS File',function(){
MyJavaScriptFunction();
})
What I tried so far...
Option-1:
addScriptDynamically('URL Of JS File',function(){
$(document).ready(function(){
MyJavaScriptFunction();
});
})
Option-2:
addScriptDynamically('URL Of JS File',function(){
$(window).load(function(){
MyJavaScriptFunction();
});
})
jquery has a function for this purpose.
Using jquery
$(function () {
//write your function code here.
})
This function is called only when the content of the page are first loaded.
2)
Using Javascript
window.onload = function(){
//write your function code here.
}

issue with window.onload in included file

I have a php page that runs standalone without any issue.
When I open the page it includes a js file with some functions. What I am interested in is that the JS contains a
window.onload = function() {
//my js stuffs here
}
that fires when the php opens.
Next step was to move the php inside my framework loading it in a div of an existing page.
So in the framework I did
$('#destinatario').change(function(){
var hk = $(this).val();
$('#sotto').html('');
$('#sotto').load('../websocket/index.php?hk='+hk);
});
my page keeps loading fine without any inconvenient but the window.onload never gets fired. What am I doing wrong?
Yes, you could workaround this doing:
$('#destinatario').change(function(){
var hk = $(this).val();
$('#sotto').html('');
$('#sotto').load('../websocket/index.php?hk='+hk, function (){
window.onload();
});
});
if it does not work create a function on index.php something like loaded() and then in the callback to when the index.php is loaded call that function.

Ajax links inside ajax loaded content

i am having trouble getting ajax loaded links to load other ajax content.
Basically this is my ajax code:
$(function () {
var api = $("#content").jScrollPane().data('jsp');
var reinitialiseScrollPane = function()
{
api.reinitialise();
}
// attaching click handler to links
$("#contentcontainer a[href]").click(function (e) {
// cancel the default behaviour
e.preventDefault();
// get the address of the link
var href = $(this).attr('href');
// getting the desired element for working with it later
var $wrap = $('#content');
$wrap
// removing old data
api.getContentPane()
// load the remote page
.load(href, reinitialiseScrollPane , function (){
}
);
});
});
Basically the links inside the navigation work fine since they are loaded when page is loaded, but links inside the ajax content (wich are supposed to load pages in the same place the navigation links load content) dont work, my understanding is that there needs some sort of ".live" function called as the js does not rescan the code once ajax loads content.
I found some solutions but none i could relate to the code im using.
The first part of the code is not ajax but for a scrollbar plugin, i did not remove it because id like to avoid it getting voided by a solution that dosent keep it into count.
Thanks.
Try using the .on() method (see jQuery documentation) when attaching the click handler:
$(document).on('click', '#contentcontainer a[href]', function (e) {
// Rest of your code here
});

Categories