jQuery not loading javascripts - javascript

So I'm stuck behind this problem
I'm using AJAX to refresh my website and when I also need to add scripts to my newly loaded div. Foe this I'm using this piece of code
$.getScript('scripts/shBrushJava.js');
$.getScript('scripts/shCore.js');
setTimeout(function(){
$(".left-content").load(document.location.hash.substr(1));
}, 10);
Sometimes this works and sometimes not as shown on pictures below
This is the working 2 pictures (Website and Firebug console)
These are the images from the time it's not working (95%)
As you can see, when the JS is not loaded properly, they are shown in console. How to fix this?

As mentioned, ajax is asynchronous. So you are not guaranteed that the script files is loaded at any given time. You've set a timeout for 10 milliseconds. Some times, the files may have been loaded and parsed, sometimes not.
Here is an example on how you can guarantee that the scripts are loaded, but there is a tons of third party libraries available for this already. For example RequireJS.
Simple example:
var getAllScripts = function (scripts, callback) {
var i, count = scripts.length;
// Start loading all files
for (i = 0; i < scripts.length; i += 1) {
$.getScript(scripts[i], function () {
// When loaded, decrease count
count -= 1;
// If all is loaded, call the callbacl
if (count === 0) {
callback();
}
});
};
};
getAllScripts([
'scripts/shBrushJava.js',
'scripts/shCore.js'
],
function () {
// Here all files is loaded, do your magic here
alert('All is loaded');
}
);
Here is a fiddle to try it out
Or you can just put:
<script src="scripts/shCore.js" type="text/javascript"></script>
<script src="scripts/shBrushJava.js" type="text/javascript"></script>
In your <head> in your html. Then it's guaranteed to be loaded in the whole <body>.

Related

jQuery iframe load function not woking properly

I am using below code
<script type="text/javascript">
var counter = 0;
$('iframe').load(function() {
counter++;
alert("counter : "+counter);
alert("iframe len : "+$('iframe').length);
if (counter == $('iframe').length) {
doRedirect();
}
});
function doRedirect() {
alert("Inside doRedirect");
}
</script>
You can see I put some alert inside the above code.
First it gives me the alert counter : 1 and iframe len : 4 after that
alert counter : 2 and iframe len : 4 then it will proceed for other action they will not showing the alert counter : 3 and 4 as per the code and it is also not come to doRedirect function.
And in my console they gives me the below error
Load denied by X-Frame-Options: https://demo.testlab.local does not permit cross-origin framing.
So please help me what is wrong with this code.
Each time you run $('iframe'), a new query takes place.
You should cache the $('iframe') query, because the way you're doing it now is susceptible to just the sort of thing you're reporting. Starting here in your code, I'll explain...
$('iframe').load( ...
$('iframe') is a collection of <iframe> tags in the DOM when this line runs, and therefore you're attaching to all iframe tags in that collection, and only to those in that collection.
Later in the function body, you're comparing a static counter to the number of <iframe> tags in the DOM at a later time, via $('iframe').length. Calling $('iframe') creates a new collection based on the current state of the DOM, which could be different from the original collection.
So this is the most likely source of your trouble. Why? Because between the time you attached the load event handler and the time when this callback fires, anything in the DOM could have changed, including the number of iframe tags; e.g., if you have other scripts doing other things.
Suggested fix.
<script type="text/javascript">
var $iframes = $('iframe'),
counter = 0;
$iframes.load(function() {
counter++;
alert("counter : "+counter);
alert("iframe len : "+$iframes.length);
if (counter == $iframes.length) {
doRedirect();
}
});
function doRedirect() {
alert("Inside doRedirect");
}
</script>

Sometimes, jQuery only updates elements on first page load

I'm learning javascript by creating a program which requests an API and dispays various properties (price in this example) to html. I have a few questions about my code and some problems I've been facing.
1). I have a bunch of $.getJSON functions corresponding to each value that I want to retrieve. I put them all in a a single 2 min. timer. When the page FIRST loads, however, some of the html elements fail to load at all. But if I refresh the page, they sometimes do load. If I refresh again, they might not load at all again. Every time I refresh, there's like a 10% chance of that particular function not inserting the content in the element. If it does load and I leave the page open, it will correctly function (update its value and html element every 2 mins and add/remove the green and red classes). If it doesn't load and I leave the page open, it will correctly function in 2 mins when the 2nd api request is made. I have already tested that the variables have some value (are not null) before and after each $('#price').text('$' + price);.
Here's an example of a function that does that:
var tempPrice;
var myVar = setInterval(myTimer, 1200000);
myTimer();
function myTimer() {
$.getJSON(link, function (json) {
$.each(json, function (index, value) {
if (value.id == "price") {
var price = value.price_eur;
if (!tempPrice) {
$('#price').text('$' + price);
tempPrice = parseFloat(price);
}
if (parseFloat(price) !== tempPrice) {
$('#price').text('$' + price).removeClass();
if (parseFloat(price) > tempPrice) {
setTimeout(function () {
$('#price').addClass("green");
}, 1);
} else {
setTimeout(function () {
$('#price').addClass("red");
}, 1);
}
tempPrice = parseFloat(price);
}
}
});
});
// Many more $.getJSON functions below...
}
If I run this function alone on either jsfiddle or my dev server (flask), it works fine. It only breaks down when I use it in conjunction with more api requests. If I remember correctly, I didn't have this problem before when I used to have a separate timer for each $.getJSON function and put each in its own <script> tag directly in html.
2) I know I can loop through the json instead of using $.each. How else can I improve the code?
1
As for the problem you're having with the inconsistent behavior of the initial page loading, it's because you are executing JavaScript before giving the browser the time to load the page fully first. You can solve this simply by waiting for the page the load, and then executing your code.
Example in jQuery:
$(document).ready(function() {
// Page is loaded, execute code...
});
2
To help you improve the way you're handling the supplied JSON data, a sample of the data would be useful.

How can I defer or async javascript in OpenCart

I have OpenCart application. Javascripts are loaded in settings.php inside path '/catalog/controller//settings.php with similar codes as:
$this->document->addScript('catalog/view/theme/<theme>/lib/lazy/jquery.lazy.1.6.min.js');
$this->journal2->minifier->addScript('catalog/view/theme/<theme>/lib/actual/jquery.actual.min.js', 'header');
$this->journal2->minifier->addScript('catalog/view/theme/<theme>/lib/hover-intent/jquery.hoverIntent.min.js', 'footer');
Here, 'theme' means theme name that is installed. I want to defer or async these javascript loading in OpenCart, how can I do it?
I know that addScript syntax has 1s parameter as file, second location, 3rd defer and 4th async where defer and async can be boolean.
I have tried statement as below to see defer false and async true:
$this->journal2->minifier->addScript('catalog/view/theme/<theme>/lib/hover-intent/jquery.hoverIntent.min.js', 'footer', false, true);
but I am not sure if this will work or not. Please suggest
Here is a script I've been using for quite some time, in the head element.
With this you get good control of your loading of files, and can start loading anything after all the DOM is loaded, just make sure the files is not required anywhere in the DOM upon load.
<head>
<title></title>
<link rel='stylesheet' type='text/css' href='css.css' />
<script type='text/javascript'>
var DomLoaded = {
done: false, onload: [],
loaded: function () {
if (DomLoaded.done) return;
DomLoaded.done = true;
if (document.removeEventListener) { document.removeEventListener('DOMContentLoaded', DomLoaded.loaded, false); }
for (i = 0; i < DomLoaded.onload.length; i++) DomLoaded.onload[i]();
},
load: function (fireThis) {
this.onload.push(fireThis);
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', DomLoaded.loaded, false);
} else {
/*IE<=8*/
if (/MSIE/i.test(navigator.userAgent) && !window.opera) {
(function () {
try { document.body.doScroll('up'); return DomLoaded.loaded(); } catch (e) { }
if (/loaded|complete/.test(document.readyState)) return DomLoaded.loaded();
if (!DomLoaded.done) setTimeout(arguments.callee, 10);
})();
}
}
/* fallback */
window.onload = DomLoaded.loaded;
}
};
DomLoaded.load(function () {
var d = document;
var h = d.getElementsByTagName('head')[0];
var s = d.createElement('script');
s.setAttribute('type', 'text/javascript');
s.setAttribute('async', true);
s.setAttribute('defer', true);
s.setAttribute('src', '/path/to/scripts.js');
h.appendChild(s);
});
</script>
</head>
And here is a good article which describes a few more ways to speed things up, and one of them is combining your js files into 1, or 2-3-4, based on which one needs which. The benefit is less http request.
http://exisweb.net/web-site-optimization-making-javascript-load-faster
And google is filled with articles
https://www.google.com/search?q=speed%20up%20loading%20javascript%20files&rct=j
For reducing page load times, you must do two mainly things
Reduce number of requests
Reduce package sizes
For reducing number of requests, you may merge all javascripts & css to one file. You should also applying lazy load images (This helps reduce package size too)
If you are running a VPS, you may try to install mod_pagespeed (developed by google) - It will help decrease a lot page load time.
I am not sure if you have used gtmetrix.com or http://www.webpagetest.org/
for reviewing your site speed yet.
For my experience, lazy load JavaScript will not help you much

Loading external Javascript Sequentially

I am working on a javascript that sequentially loads a list of other external javascript.
The code I have so far:
function loadJavascript(url){
var js = document.createElement("script");
js.setAttribute("type", "text/javascript");
js.setAttribute("src", url);
if(typeof js!="undefined"){
document.getElementsByTagName("head")[0].appendChild(js)
}
}
loadJavascript("Jquery.js");
loadJavascript("second.js");
loadJavascript("third.js");
The problem I ran into is that sometimes the other js files loads before the Jquery file completes its loading. This gives me some errors.
Is it possible to make it so that the next JS file is only initiated when the previous file is finished loading.
Thanks in advance
Sure there is, but there's entire libraries written around doing this. Stop reinventing the wheel and use something that already works. Try out yepnope.js or if you're using Modernizr it's already available as Modernizr.load
loadJavascript("Jquery.js");
$(function(){
$.getScript('second.js', function(data, textStatus){
$.getScript('third.js', function(data, textStatus){
console.log("loaded");
});
});
}
Also, consider using the Google or Microsoft CDN for the jQuery, it will save you bandwidth and hopefully your visitors will already have it cached.
Actually, it's not necessary to load jquery within a js function. But if you insist, you can callback to make sure other js loaded after jquery.
Still, I recommend you load jquery just before </body> then use $.getScript to load other .js
You could do a check to see if jQuery is loaded, not the best way to do it, but if you really have to wait until jQuery is loaded before loading the other scripts, this is how I would do it, by checking for $ :
loadJavascript("Jquery.js");
T=0;
CheckIfLoaded();
function CheckIfLoaded() {
if (typeof $ == 'undefined') {
if (T <= 3000) {
alert("jQuery not loaded within 3 sec");
} else {
T=T+200;
setTimeout(CheckIfLoaded, 200);
} else {
loadJavascript("second.js");
loadJavascript("third.js");
}
}
In technical terms: Browsers have a funny way of deciding I which order to execute/eval dynamically loaded JS, so after suffering the same pain and checking a lot of posts, libraries, plugins, etc. I came up with this solution, self contained, small, no jquery needed, IE friendly, etc. The code is extensively commented:
lazyLoader = {
load: function (scripts) {
// The queue for the scripts to be loaded
lazyLoader.queue = scripts;
lazyLoader.pendingScripts = [];
// There will always be a script in the document, at least this very same script...
// ...this script will be used to identify available properties, thus assess correct way to proceed
var firstScript = document.scripts[0];
// We will loop thru the scripts on the queue
for (i = 0; i < lazyLoader.queue.length; ++i) {
// Evaluates if the async property is used by the browser
if ('async' in firstScript ) {
// Since src has to be defined after onreadystate change for IE, we organize all "element" steps together...
var element = document.createElement("script");
element.type = "text/javascript"
//... two more line of code than necessary but we add order and clarity
// Define async as false, thus the scripts order will be respected
element.async = false;
element.src = lazyLoader.queue[i];
document.head.appendChild(element);
}
// Somebody who hates developers invented IE, so we deal with it as follows:
// ... In IE<11 script objects (and other objects) have a property called readyState...
// ... check the script object has said property (readyState) ...
// ... if true, Bingo! We have and IE!
else if (firstScript.readyState) {
// How it works: IE will load the script even if not injected to the DOM...
// ... we create an event listener, we then inject the scripts in sequential order
// Create an script element
var element = document.createElement("script");
element.type = "text/javascript"
// Add the scripts from the queue to the pending list in order
lazyLoader.pendingScripts.push(element)
// Set an event listener for the script element
element.onreadystatechange = function() {
var pending;
// When the next script on the pending list has loaded proceed
if (lazyLoader.pendingScripts[0].readyState == "loaded" || lazyLoader.pendingScripts[0].readyState == "complete" ) {
// Remove the script we just loaded from the pending list
pending = lazyLoader.pendingScripts.shift()
// Clear the listener
element.onreadystatechange = null;
// Inject the script to the DOM, we don't use appendChild as it might break on IE
firstScript.parentNode.insertBefore(pending, firstScript);
}
}
// Once we have set the listener we set the script object's src
element.src = lazyLoader.queue[i];
}
}
}
}
Of course you can also use the minified version:
smallLoader={load:function(d){smallLoader.b=d;smallLoader.a=[];var b=document.scripts[0];for(i=0;i<smallLoader.b.length;++i)if("async"in b){var a=document.createElement("script");a.type="text/javascript";a.async=!1;a.src=smallLoader.b[i];document.head.appendChild(a)}else b.readyState&&(a=document.createElement("script"),a.type="text/javascript",smallLoader.a.push(a),a.onreadystatechange=function(){var c;if("loaded"==smallLoader.a[0].readyState||"complete"==smallLoader.a[0].readyState)c=smallLoader.a.shift(),
a.onreadystatechange=null,b.parentNode.insertBefore(c,b)},a.src=smallLoader.b[i])}};

How to make sure Google Analytics loads even if user navigates away from page?

I'm not sure what happens when a page containing the asynchronous version of Google Analytics hasn't fully loaded but the user either closes the browser or navigates to another page.
If the analytics doesn't get recorded like I assume, then what methods are available to ensure that it does?
If it does, how does it work?
This is probably impossible. You can kind of reverse-engineer google analytics stuff by tracking the resources they add to the page, like this:
var googleAnalyticsDidTheThing = false;
// ga_src is the src to a script that Google dynamically adds to your page
// this is your asynchronous code
var ga_src = "something.google.com/ga.js";
var ga_script;
var id = setInterval(function () {
var scripts = document.getElementsByTagName("script");
for (var i=0, len=scripts.length; i<len; i++) {
var script = scripts[i];
if (script.src === ga_src) { ga_script = script; break; }
}
var cb = function () {
googleAnalyticsDidTheThing = true;
};
ga_script.onload = cb;
// This one's for IE
ga_script.onreadystatechange = function () {
if (this.readystate === "complete") cb();
}
}, 50);
But the problem is that only gets you halfway there. You can check to see if it's done by using window.onunload as #nidhin mentioned. However, since javascript is single-threaded, only one process can be taking place at a time. So, I see no way for you to block the user from exiting the page without also blocking ga_script's ability to run in the background. Hence, you can check to see if Google has finished doing their thing, but you can't actually make sure Google can finish.
You could, however, send some info to your own server (the page could leave, but the data would still get sent) and gather statistics on how many users actually do this, to get a feel for what your margin of error is. You could even attempt to do some of the tracking yourself, if you are really determined.
You can check Google analytics is loaded before window is closed like this
<script type="text/javascript">
window.onunload = checkIfAnalyticsLoaded;
function checkIfAnalyticsLoaded() {
if (window._gat && window._gat._getTrackerByName()) {
// Do tracking with new-style analytics
} else if (window.urchinTracker) {
// Do tracking with old-style analytics
} else {
// Probably want to cap the total number of times you call this.
setTimeout(500, checkIfAnalyticsLoaded();
}
}
</script>

Categories