I am working with both amq.js (ActiveMQ) and Google Maps. I load my scripts in this order
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>AMQ & Maps Demo</title>
<!-- Stylesheet -->
<link rel="stylesheet" type="text/css" href="style.css"></link>
<!-- Google APIs -->
<script type="text/javascript" src="http://www.google.com/jsapi?key=abcdefg"></script>
<!-- Active MQ -->
<script type="text/javascript" src="amq/amq.js"></script>
<script type="text/javascript">amq.uri='amq';</script>
<!-- Application -->
<script type="text/javascript" src="application.js"></script>
</head>
However in my application.js it loads Maps fine but I get an error when trying to subscribe to a Topic with AMQ. AMQ depends on prototype which the error console in Firefox says object is not defined. I think I have a problem with using the amq object before the script is finished loading. Is there a way to make sure both scripts load before I use them in my application.js?
Google has this nice function call google.setOnLoadCallback(initialize); which works great. I'm not sure amq.js has something like this.
cross-domain scripts are loaded after scripts of site itself, this is why you get errors. interestingly, nobody knows this here.
Is there a way to make sure both scripts load before I use them in my application.js?
JavaScript files should load sequentially and block so unless the scripts you are depending on are doing something unusual all you should need to do is load application.js after the other files.
Non-blocking JavaScript Downloads has some information about how scripts load (and discusses some techniques to subvert the blocking).
in jquery you can use:
$(document).ready(function(){/*do stuff here*/});
which makes sure the javascript is loaded and the dom is ready before doing your stuff.
in prototype it looks like this might work
document.observe("dom:loaded", function() {/*do stuff here*/});
If I understand your problem correctly.. I think that may help..
If you don't want to rely on a lib to do this... I think this might work:
<script>
function doIt() {/*do stuff here*/}
</script>
<body onLoad="doIt();"></body>
I had a similar problem to this, only with a single script. The solution I came up with was to use addEventListener("load",fn,false) to a script object created using document.createElement('script') Here is the final function which loads any standard JS file and lets you add a "post load" script.
function addJavaScript( js, onload ) {
var head, ref;
head = document.getElementsByTagName('head')[0];
if (!head) { return; }
script = document.createElement('script');
script.type = 'text/javascript';
script.src = js;
script.addEventListener( "load", onload, false );
head.appendChild(script);
}
I hope this may help someone in the future.
Is there a way to make sure both scripts load before I use them?
Yes.
Put the code you want loaded last (your application.js stuff) into prototype's document.observe. This should ensure that the code will load only after prototype + other stuff is finished and ready. (If you are familiar with jQuery, this function is similar to jQuery's $(document).ready )
AMQ depends on prototype which the error console in FireFox says object is not defined.
Do you mean that AMQ depends on the Prototype library? I can't see an import for that library in the code you've provided.
Do you mean that AMQ depends on the
Prototype library? I can't see an
import for that library in the code
you've provided.
Yes for ActiveMQ's javascript (amq.js) does depend on Prototype. In the amq.js it loads 3 scripts, _amq.js, behaviour.js and prototype.js.
Thanks you for your help on the JavaScript load order wrumsby. This tells me that my bug is in another castle :(
I guess I have a different problem. I also checked the js files from ActiveMQ 5.0 to 5.1 and noticed they were the same as well. Something has changed in 5.0 to 5.1 that requires a refresh for the topics to subscribe. I'll keep looking, but thanks for eliminating this possible cause.
You can also use the built in SharePoint javascript method to control the execution of your scripts;
_spBodyOnLoadFunctionNames.push("yourFunction");
Related
I want to use Head JS to dynamically load all of the other scripts for my pages. I'm planning on using the version hosted by CDNJS to take advantage of the better caching, decreased latency, etc.
I have no reason to think CDNJS is going anywhere, but even for Google CDN hosted files like jQuery, I like to include a fallback. When I'm using jQuery though, the files are included at the end of the <body> tag. Due to the nature of Head JS, I need to include it in the <head> of my page.
In the <body> I would use two lines like this:
<script src="http://cdnjs.cloudflare.com/ajax/libs/headjs/0.96/head.min.js"></script>
<script> window.head || document.write('<script src="js/libs/head-0.96.min.js"><\/script>') </script>
Can I use this same set of lines in the head as a fallback? Won't document.write() overwrite my entire page? Don't scripts load differently when they exist in the <head> due to the order that browsers parse the DOM?
I'm still pretty new to this, so any guidance would be hugely helpful! Thanks!
As you probably already know, you won't be testing for window.jQuery but some function included in head.js.
Additionally, you're right that you may not want to use document.write() twice here.
Instead of document.write(), try this:
function appendScript(url) {
var head = document.getElementsByTagName('head')[0];
var theScript = document.createElement('script');
theScript.type = 'text/javascript';
theScript.src = url;
theScript.onreadystatechange = callback;
theScript.onload = callback;
head.appendChild(theScript);
}
For the url, use your local fallback.
What is the most ideal way of loading javascript files? Also, I want to make sure that order of the javascript files should be maintained. If I have
<script src="javascript1.js">
<script src="javascript2.js">
on my page, then javascript1.js should load before javascript2.js
Thanks.
EDIT: Thank you for your answers, but mine question is not only related with the order of js files. I want to load js files as quickly as possible without using any 3rd party js library. The solution which is similar can be found at www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/, but using this does not guarantee the order of the files for me, atleast.
There is no single "best" way of loading Javascript files. Different ways work best in different scenarios.
The normal way of loading Javascript files is to put the script tags in the head tag.
You can put some script tags inside the body tag instead, to make them load later. One common reason for this is to make the content of the page display without having to wait for the script to load.
The scripts are executed in the way that the tags are placed in the code. The execution of the code below a script tag waits for the Javascript to be executed first.
In your question you say that you want one script to load before the other, which can't be guaranteed by just using script tags in the code. Then you would have to generate the second script tag in the first Javascript and use document.write to put it in the page. To make the scripts execute in that order, you can just use your script tags the way that you do, and the order is guaranteed.
Note: You should specify the type attribute in the script tags, so that the tags validate without errors. You need to include the closing tag for the script tags.
<script type="text/javascript" src="javascript1.js"></script>
<script type="text/javascript" src="javascript2.js"></script>
As others have said, the scripts are loaded in order of placement on the page (unless they are wrapped in javascript to be loaded in later)
Putting the script tags at the bottom of the page can assist with the loading process for both old and new browsers. Although some scripts might (like modenizer) need to be loaded earlier on in the process. A good example can be seen at http://html5boilerplate.com/ on the index code sample.
Edit:
Following your edit, there is this info which can help
<script type="text/javascript">
document.writeln("<script type='text/javascript' src='Script1.js'><" + "/script>");
document.writeln("<script type='text/javascript' src='Script2.js'><" + "/script>");
</script>
The full documentation on this can be read here (including crevets of other methods) http://blogs.msdn.com/b/kristoffer/archive/2006/12/22/loading-javascript-files-in-parallel.aspx
HTML is a top down procedural language so anything that is posted first gets executed first. Hence the order which you wrote is correct.
Your web browser will execute javascript files in the order they are declared, so in your example:
<script src="javascript1.js">
<script src="javascript2.js">
javascript1.js will be executed before javascript2.js.
As for the most ideal way, this is all very subjective. I prefer progressive enhancement when using javascript so declare my javascript as the last element on a page, since it is not required for the site to function, any user can see the content and use the site even while the javascript is downloading.
I also prefer bundling all my scripts together, in a minified form, so the browser only has to make one request to get my javascript.
There is a school of thought that using parallel loading is good. This means the scripts are loaded like the GA snippet provided by google by using JS. A good way of doing this is to use modernizr. This script enables you to load the scripts when they are needed. You would need to include the modernizr script in the traditional way and then write some JS to load the other script when required.
The Best Answer Can Be Found Here:Here:http://www.html5rocks.com/en/tutorials/speed/script-loading/
Ideally do this if you need to load them in some particular order (In case of dynamically added scripts):
`
['//other-domain.com/1.js',
'2.js']
.forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
`
And this for no order:
`
['//other-domain.com/1.js',
'2.js'
].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
document.head.appendChild(script);
});
`
But if you just need static scripts then just ado this at the end of your body as suggested by many others:
`<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>`
I'm trying to execute some inline javascript within an HTML page as early in page processing as possible that makes use of library functions in an external .js file.
While I've always seen that putting library scripts in the head, and client scripts in the body just seems to work, I can't find documentation anywhere that says that external scripts included within the head of a document are guaranteed to run before script located within the body of a document (except on the w3schools site, but they don't count as a reputable reference)
To illustrate, I'm wondering about the User-Agent behavior for HTML that looks like this:
<html>
<head>
<script type="text/javascript src="libraryModule.js"></script>
</head>
<body>
<script type="text/javascript">
// is this guaranteed to run after the external script?
// or is it possible this module that the external library
// adds to the global namespace won't be there yet?
var result = ModuleInExternalLibrary.DoLibraryThing();
</script>
</body>
</html>
Is this documented anywhere? I can't find anything in the W3C spec or any good post that sums up the behavior in this area of all the major browsers. Please provide a link.
Am I stuck having to wait until the onload event fires in order to guarantee that external scripts have executed?
JavaScript statements that appear between <script> and </script> tags are executed in order of appearance. So yes, it is guaranteed, unless you are doing something clever like deferred loading or something similar.
Execution of JavaScript Programs
Is there a solution out there where I can have JavaScript/jQuery autoload dependent files when needed? For example, consider this scenario:
I have an autoloader script listening for when a particular script needs to be loaded.
A jQuery dialog() plugin is called.
The autoloader is told to listen for when this plugin is called, and loads the jQuery UI.
If more dialogs are called in the future, the required script will not be loaded.
Is this too much effort for simply trying to limit bandwidth? Should I just include all of the core files in one superpackage and be done with it?
Thank you for your time.
Yes you should inclde all of the scripts in one file. Or at least most of them groupped like this: jquery.js, global.js (that's where frequently - on more than one, two pages - used scripts should be) and page_specyfic.js.
Imagine that a dialog() is called and the user has to wait for .js to download and plugins to initialise.
Savings in bandwith (if any) wouldn't be worth harming the users expirience.
There are many examples of on demand script loading out there. For example remy sharp has a code sample on his blog that you could either use as is or turn into a jQuery plugin. Unfortunately it may not work in all browsers.
There is also the jQuery Lazy Plugin Loader which loads jQuery plugins on demand rather than up-front. To use it you would need to set up lazy loading for each piece of jQuery UI you are using as follows (name will be the function name for each piece you use):
$.lazy([{
src: 'jquery-ui-1.8.14.custom.min.js',
name: 'dialog'
}]);
You can also use the techniques in this question about loading jQuery itself on demand. For example you can dynamically create a script tag at the time needed to load jQuery UI.
Finally since you are talking about jQuery UI consider getting it from Google's CDN, which is likely cached in the user's browser anyway.
You can try this new jquery plugin. Works like yeapnope.js but more make sense.
http://plugins.jquery.com/plugin-tags/autoloader
$(document).autoLoader(
{
test: $.ui,
loadScript: "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery- ui.min.js",
complete: function(){
console.log($.ui);
}
}
);
I wouldn't worry too much. The files are cached. Once one page in your site loads the jquery UI (or any other include file like CSS), the next time it's needed it will be in the user's browser cache, never to be loaded again for days/weeks
Sounds like you want a script loader.
You can't generally do synchronous loading of scripts across browsers, though, so script loaders are necessarily asynchronous. What you're asking for isn't exactly possible since the script needs to load, call a callback, and then continue. You wouldn't want to call some plugin and not know whether it is executing synchronously or not, that gets you into a world of problems.
I recommend you look at DeferJS, a script loader for jQuery:
https://github.com/BorisMoore/jsdefer
From your comments, part of your wish seems to be to keep your code organized. I would recommend RequireJs. It lets you break your code up into clearly separated modules with explicit dependencies. Then when you want to go to production, there's a build tool that will merge them all back together into the (request/bandwidth saving) 2-3 files you want to serve.
Yeah, I have also thought about implementing something like this. I am not sure if it would be worthwhile or not in the end but there are quite a few libraries to do this for you like ensure
you could try something like this but it would be a pain. basically you are checking the type of error caught and message if dialog (the function you are trying to call doesn't exist) load the function and try calling the method again. Like I said it would be a pain to do this everywhere unless some elegant solution was thought of.
function loadDialog() {
$('#myDialog').dialog({});
}
try {
loadDialog()
} catch(e) {
if (e && e.type && e.type=='not_defined' && e.message == 'dialog is not defined') {
//load jQuery plugins...
loadDialog();
}
}
This is a follow-up post for a comment above:
<link rel="stylesheet" href="../system/stylesheets/universal.css" />
<link rel="stylesheet" href="../system/stylesheets/jquery-ui.min.css" />
<link rel="stylesheet" href="../system/stylesheets/uploadify.css" />
<link rel="stylesheet" href="system/stylesheets/style.css" />
<script src="../system/javascripts/swfobject.js"></script>
<script src="../system/javascripts/jquery.min.js"></script>
<script src="../system/javascripts/jquery-ui.min.js"></script>
<script src="../system/javascripts/global.jquery.js"></script>
<script src="../system/javascripts/analog.jquery.js"></script>
<script src="../system/javascripts/funtip.jquery.js"></script>
<script src="../system/javascripts/uploadify.jquery.js"></script>
<script src="system/javascripts/install.jquery.js"></script>
<link rel="stylesheet" href="system/templates/stylesheets/style.css" />
<script>
$(document).ready(function() {
$(':text, :password, textarea').funtip();
});
</script>
I am using jQuery UI and a few other JS libs which in total make for quite a chunk of JS (even minified and combined). My idea is to not include a script tag in the page but to stub out all functions that I defined as well as the $ sign for jQuery so that my inline JS on the page can still call them but will hit the stub. The stub will then load the .js file and actually call the function. The question now is:
How can I redirect all function calls on the window object/global object to a custom function of mine?
I am not used to dynamic languages so a little advice on how to do this in JS will be appreciated.
As stated previously ... this is likely an exercise in futility. Unless you are a researcher and are being paid to do this (and only this), I'd spend my time just working on my actual product and/or refactoring so that the page requires fewer disparate JS libs (for example. use jquery only, rather than jquery + yui)
edit, though, I suppose in the interest of actually answering the question. You can easily replace any function by simply setting it in javascript. For example ...
$ = function(searchString) {
// if this method is called
// and jquery hasn't been loaded yet
// load jquery (which will overwrite all of your local jquery functions with its own
};
The method to lazy load .js files is well documented throughout the web, for example here:
http://ajaxpatterns.org/On-Demand_Javascript
Well the root of your problem is the usage of library dependent in-line JS. We had an old legacy site that had a bunch of in-line JS in the Smarty templates. I ended up modding Smarty so that I could capture the JS calls and then output them all in the footer. Looked something like this
<!-- mySubContent.inc.html -->
<div id="theTabs">
<ul><li><!--
...
--></li></ul>
<div id="tab1"><!--
...
--></div>
</div>
{capture_js}
$("#theTabs").tabs();
{/capture_js}
<!-- footer.inc.html -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
{render_captured_js}
</script>
</body>
</html>
Anyway, maybe that'll give you some idea about how to tackle your in-line JS problem if you can't refactor the codebase right now. Oh, and read this - http://developer.yahoo.net/blog/archives/2007/07/high_performanc_5.html .