jQuery plugin loading before jQuery - javascript

I'm working within a platform that I do not have server side access to. That means I can't load javascript files directly into the head, only the body.
Here's how I'm doing my loads:
function loadjscssfile(filename, filetype){
//http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
}
loadjscssfile('https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js','js');
loadjscssfile('http://redacted.com/data.php?rand='+Math.random(),'js');
However, the third javascript file (a jQuery plugin) I load requires jQuery.
When I load the page I get this error (in Chrome)
Uncaught ReferenceError: jQuery is not defined
My inclination is that my plugin is loading before jQuery. Because if I refresh the page (when jQuery is cached) the error disappears. However, I need this to work even when jQuery is not cached. Thoughts?

This is not an elegant solution but it works always for me: copy/paste the content of jquery.min.js file directly to your html page
<script> ... </script>

What I do is this
if (typeof $ === 'undefined') {
document.write("<script src='//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'><\/script>");
var timeout = 0;
while (typeof $ === 'undefined' && timeout++ < 100);
}
This will wait until jquery is loaded before it moved on to do anything else. Then load your plugin.

As you're trying you have to load jQuery and run the other scripts after it loads. To do that you can use a loader library, like yepnope or headjs, remembering that as you cannot put scripts on your head you have to put the loader code along to the script.
Your code will be something like this:
yepnope( // or head.js
'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
'http://redacted.com/data.php?rand='+Math.random(),
'https://raw.github.com/aakilfernandes/jquery.inject/master/jquery.inject.js?rand='+Math.random()
);
Another thing you can do is just put the jquery script on the body and load the other scripts after it:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$.getScript('http://redacted.com/data.php?rand='+Math.random());
$.getScript('https://raw.github.com/aakilfernandes/jquery.inject/master/jquery.inject.js?rand='+Math.random());
</script>

Related

jQuery not loading when reloading window

I have a strange situation where jQuery is not loading into the window object. My app is an Electron app. My startup page does in fact load jQuery. But while the startup page is loading, I have some code that decides whether to reload the browser window with a different url. That url is another html page in the app and it contains a reference to the jQuery library in the script tag. jQuery does appear to load in this new page because I am able to open DevTools and type $ in the console and it indicates that it is loaded. However, in my javascript code, which is embedded in the page, the $ is not recognized. I am not loading any other scripts that could conflict with the jQuery script. The jQuery script is the only script loaded. What could be preventing jQuery from being attached to the window object? This only happens when I load that new page using window.location.href. If I don't load that page, but simply use jQuery in the startup page, jQuery is attached to the window object.
Here is how I am loading jQuery:
<head>
<script type="text/javascript" src="../../jquery/jquery-3.2.1.min.js"></script>
</head>
I have tried waiting for jQuery to load using:
function defer(method) {
if (window.jQuery) {
method();
} else {
setTimeout(function() { defer(method) }, 50);
}
}
defer(function () {
alert("jQuery is now loaded");
});
but window.jQuery never gets set.
In Electron, jquery isn't loaded as a script.
Use this instead (in your header):
<script>window.$ = window.jQuery = require('jquery');</script>
and install jQuery as a package with npm install --save jquery
If that doesn't work, try using
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
//put all of scripts here
<script src="path/to/jquery"></script>
<script>if (window.module) module = window.module;</script>
Or you can use:
<script>window.$ = window.jQuery = require('./path/to/jquery');</script>

How to remove and add js file completely dynamicaly after page load by jquery?

In my project ,I have to load JS and CSS file dynamically after the page load.
By using below code I am able to add and remove the js file But after adding the new file by removing the previous one,then the previous file is not shown in the header but when I run the code both js file code is executed.I don't known how to remove the file completely ,Can some body help me.
For that the code is.
In the the view page header:-
<link rel="stylesheet" id="videoCss" />
<script id="videojs"></script>
Jquery for Dynamically load JS and CSS file:-
function addRemoveJsCssFile(filename, filetype)
{
var fileref='';
if (filetype == "js") { //if filename is a external JavaScript file
document.getElementById("videojs").remove();
fileref=document.createElement('script');
fileref.setAttribute("type", "text/javascript");
fileref.setAttribute("src", filename);
fileref.setAttribute("id", "videojs");
}
else if (filetype == "css") { //if filename is an external CSS file
document.getElementById("videoCss").remove();
fileref = document.createElement("link");
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", filename);
fileref.setAttribute("id", "videoCss");
}
if (typeof fileref != "undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
In this function we have to pass the file location and type of file i.e css or js to add file dynamically.Thank you.
I don't know if I've understood your issue, but let me try to explain:
if the original script is in head section, it will be executed immediately, because Javascript is a procedural language, so there's nothing that you can do in a script placed "later": scripts defined earlier are executed earlier so, maybe your problem is when you call your function, it's simply too late to stop the videojs execution.
On the other side with scripts defined before, you can't see script tags defined later.. or better, you could if you're deferring, but in a deferred situation you'll be fighting again with the same issue, the videojs script would be always executed (it would be always too late or too early, because your statements executes or before, or after, there isn't a third way).
Of course you can load a script before just to set a global object that could say to videojs "stop, don't proceed with your stuff!" but obviously you shall edit videojs code either, with a wrapper "if" that asks that object the permission to proceed, and I don't think that's the response you're looking for.
But the question is: what's executed in that javascript videojs, an event binder that starts on load? Or in another event? Or is just a sequence of statements that are executed - sorry for the wordplay - sequentially?
In the first and second case there's something that you can do before: if video.js starts when an event is triggered, you can stop that function to be executed, operating before that trigger: you must delete the event subscription. To unbind the event, you must know how the first script operates and what event it subscribes in order to unbind it.
Here is how to execute script before jQuery ready event (but it's valid also for native javascript events, so I think that might be helpful):
running jQuery code before the dom is ready
This answer is useful even for every document events, not only for the load or "jQuery ready".
But, even if it's possible to remove the bind "vanishing" every videojs script effects, it's not a clean job, because
Overall, videojs has been executed
This will work only with videojs and at least it may work only with hardcoded scripts that uses the same event to start, but not for all hardcoded scripts
So, what I suggest for your purpose, it's to manage load and unload of scripts entirely with this manager, don't hardcode them in HTML.
PS: Have you ever heard about require.js?
If not, take a look here
Instead of deleting whole element, and than creating new one, maybe try just to change the 'src' attribute in existing element?
now
document.getElementById("videojs").remove();
fileref=document.createElement('script');
fileref.setAttribute("type", "text/javascript");
fileref.setAttribute("src", filename);
fileref.setAttribute("id", "videojs");
suggest
document.getElementById("videojs").setAttribute("src", filename);
You can use $.getScript() to dynamically load js file.
Try this
$('#scriptid').remove(); //remove it first and then add the new one
var script = document.createElement('script');
script.src = something;
document.head.appendChild(script); //Add element to head tag
OR
$("<style type='text/css' href=''></style>").appendTo("head");
$("<script type='text/javascript' src=''></script>").appendTo("head");

Loading CDN files via Javascript

I've been working hard to achieve 100/100 on Google Pagespeed (https://developers.google.com/speed/pagespeed/insights/) but I keep getting hungup when trying to use Javascript to download CDN based files. I get 'CAUTION: Provisional headers are shown.' and I assume it's blocking this kind of call for security reasons but I'm stuck.
I can call script files asycn like this, which Google likes:
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" async></script>
But what am I to do about the CSS files? If I call it the normal way:
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
Google complains and says I have a 'blocking CSS resources'.
Here's a copy of the code I've been trying to use so far:
var headID = document.getElementsByTagName("head")[0];
var cssNode = document.createElement('link');
cssNode.type = 'text/css';
cssNode.rel = 'stylesheet';
cssNode.href = '//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css';
headID.appendChild(cssNode);
Anyone have any suggestions?
Here is the code I ended up creating to handle loading both css and js files async at the same time. Just put this at the bottom of your HTML before you closing tag and edit the loadjscssfile() calls as necessary.
<script>
/* Beginning of async download code. */
window.onload = function(){
function loadjscssfile(filename, filetype) {
if(filetype == "js") {
var cssNode = document.createElement('script');
cssNode.setAttribute("type", "text/javascript");
cssNode.setAttribute("src", filename);
} else if(filetype == "css") {
var cssNode = document.createElement("link");
cssNode.setAttribute("rel", "stylesheet");
cssNode.setAttribute("type", "text/css");
cssNode.setAttribute("href", filename);
}
if(typeof cssNode != "undefined")
document.getElementsByTagName("head")[0].appendChild(cssNode);
}
loadjscssfile("//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css", "css");
loadjscssfile("//fonts.googleapis.com/css?family=Open+Sans:300&subset=latin,cyrillic-ext,latin-ext,cyrillic,greek-ext,greek,vietnamese", "css");
loadjscssfile("/css/style.css", "css");
loadjscssfile("//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js", "js");
loadjscssfile("//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js", "js");
};
/* End of async download code. */
</script>
Google provides a good explanation of this here:
https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery
It seems like they want you to inline CSS that is crucial to the page's initial display. Then load secondary CSS after. Since the bootstrap CSS is one large mix, I think it'll be non-trivial to separate crucial/non-crucial for your page.
Perhaps you can inline some duplicate CSS that exists in bootstrap.css
I'd suggest you to inline the styles for the critical path (above the fold):
https://github.com/addyosmani/above-the-fold-css-tools
https://github.com/addyosmani/critical
Then load the other css async:
https://github.com/filamentgroup/loadCSS/

Rerun Javascript in dynamically filled iframe

On a page i try to fill an empty <iframe id="myFrame"></iframe> with the HTML code of an ajax result. That works well, except script tags in the code are not being executet, so i have to readd them to the iframe's page:
$.post('page.php', function(code) {
$("#myFrame").contents().find("html").get(0).innerHTML = code;
$("#myFrame").contents().find("script").each(function() {
$old_script = $(this);
$frame = document.getElementById("myFrame");
$new_script = $frame.contentWindow.document.createElement("script");
$new_script.type = "text/javascript";
$new_script.src = $old_script.attr("src");
$old_script.remove();
$frame.contentWindow.document.head.appendChild($new_script);
});
});
That works basically, but the document seems to load the Javascript files in a different order. There are 3 js files to load: jquery.min.js, a jquery plugin and a main.js file to control the bahavior inside the iframe:
// main.js:
$(document).ready(function() {
alert("frame document loaded");
// call the jquery plugins etc...
});
The page alerts me "frame document loaded", but cannot execute the jquery plugins. Double-checked the script paths, but they're right. Seems that the jquery.min.js and main.js are loaded before the plugin files.
How could i achieve to load the javascript files one by one as specified originally in the code returned by the ajax request?
EDIT: Forgot to say that sometimes everything works well and the javascript seems to be loaded correctly. On reload it breaks again.

Dynamically changing stylesheet path not working in IE and Firefox

I have the following file:
<html>
<head>
<title></title>
<link rel="css" type="text/css" href="/empty.css" title="css" />
<script type="text/javascript" src="/Prototype"></script>
<script type="text/javascript">
function load_content()
{
var d = new Date();
new Ajax.PeriodicalUpdater('content', '/DOC?'+d.getTime(),
{
method: 'post',
frequency: 5,
onSuccess: function(transport) {
for(i=0; (a = document.getElementsByTagName('link')[i]); i++)
{
if(a.getAttribute('rel') == 'css' && a.getAttribute("type") == 'text/css')
{
a.href = '/CSS?'+d.getTime();
}
}
}
});
}
</script>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
load_content();
</script>
</body>
</html>
Note: Ignore the d.getTime() calls...these are just to get around an issue with IE not loading a new page from an AJAX call because it's caching scheme is too aggressive.
Basically, when it reloads the file at /DOC, it is supposed to be setting the current stylesheet to the file at /CSS... both DOC and CSS and constantly changing.
What's weird is that in Chrome it works great. DOC loads up in the "content" div and the stylesheet gets set to CSS and that css is applied to the page. I can change with CSS page and withing 5 seconds, when the page is refreshed, the CSS will be refreshed as well.
But in IE and Firefox, the HTML will load and I can see that the href attribute of the stylesheet link IS getting changed to "/CSS + getTime()" but, while the HTML loads, the css is never applied to the page. I can even change the content of DOC and it updates, but the css is never even applied. It just stays a style-free page.
Does Firefox and IE not support changing the style sheet reference in this way?
Is there a better way to do this?
Rather than changing the sheet in a single link, try using alternate style sheets. See this link on using alternate style sheets:
http://www.alistapart.com/articles/alternate/
The best way to include files via javascript is to insert a new dom element.
var a = document.createElement('link');
a.href="inset.css";
a.rel="stylesheet";
document.getElementsByTagName("head")[0].appendChild(a);
However, obviously the problem you're going to run into though is that firefox and ie will not repaint the canvas once the document is finished loading (and you're using ajax). The way you get around that is by taking the contents of the stylesheets and including them in a style element. This sample code will change the color on the page dynamically.
function onLoadFunction() {
var a = document.createElement('style');
a.appendChild(document.createTextNode('body {color: blue;}'));
document.getElementsByTagName("body")[0].appendChild(a);
}
When you load a new sheet, just destroy the css inside the style element and replace it.
maybe this will help you ...
http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
function loadjscssfile(filename, filetype){
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
It looks like you are simply reloading the existing page every time. Why not just use the refresh tag in your header to force the document to reload each time and put in the CSS and content server-side. A lot simpler and it works even with javascript disabled.
<meta http-equiv="refresh" content="5;url=http://example.com/DOC" />
It might be a caching issue. If you do a hard refresh (Ctrl+R in FF, Ctrl+F5 in IE) does it display the style properly? If that does fix it, you may want to look at removing the Last-Modified header from the CSS file or adding a cache control header telling the browser not to cache it.

Categories

Resources