Looking for an elegant way to load JS and execute it - javascript

I'm new into JavaScript and I really like jQuery and hate when it comes to writing some cumbersome code to get simple things done.
I'm currently trying to load an external JS dynamically and execute it (to communicate with Google Translate API).
The sample code creates a script tag, sets its src and appends it to document's head to execute it:
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
var sourceText = escape(document.getElementById("sourceText").innerHTML);
var source = 'https://www.googleapis.com/language/translate/v2?key=INSERT-YOUR-KEY&source=en&target=de&callback=translateText&q=' + sourceText;
newScript.src = source;
// When we add this script to the head, the request is sent off.
document.getElementsByTagName('head')[0].appendChild(newScript);
I wonder if there's any one-liner in jQuery for this.

$.getScript('https://www.googleapis.com/language/translate/v2?key=INSERT-YOUR-KEY&source=en&target=de&callback=translateText&q=' + $('#sourceText').html());

Try this:
http://api.jquery.com/jQuery.getScript/

HeadJS is made for such use, this is easy and optimized way to include scripts This will helps you sure.
basic Method: ( took 800ms)
<script src="https://github.com/DmitryBaranovskiy/raphael/raw/master/raphael.js"></script>
<script src="https://github.com/jquery/jquery-ui/raw/master/jquery-1.4.4.js"></script>
<script src="https://github.com/smith/scripty2/raw/master/lib/prototype.js"></script>
<script src="https://github.com/headjs/www/raw/master/content/test/jquery-ui.js"></script>
<script src="https://github.com/kosmas58/compass-jquery-plugin/raw/master/lib/jslint.js"></script>
using head.js (took 700 ms)
<script src="../media/js/head.min.js"></script>
<script>
head.js("https://github.com/DmitryBaranovskiy/raphael/raw/master/raphael.js")
.js("https://github.com/jquery/jquery-ui/raw/master/jquery-1.4.4.js")
.js("https://github.com/smith/scripty2/raw/master/lib/prototype.js")
.js("https://github.com/headjs/www/raw/master/content/test/jquery-ui.js")
.js("https://github.com/kosmas58/compass-jquery-plugin/raw/master/lib/jslint.js");
</script>
see the testcase

Related

Trouble loading js

I'm sorry in advance if this is simple or if it just can't be done. Basically, I am trying to load an age verification js on my site, but I am trying to chose between different pages depending on the legal drinking age in different countries.
If I load the script simply, it works fine:
<script type="text/javascript" src="https://av.ageverify.co/jsfr/singlemalt.18.js"></script>
However, if I trying to do any sort of modification to this script, it won't load at all. For example, if I try to set the src to a variable (that I would call in a different script, it fails to load).
<script>
url = "https://av.ageverify.co/jsfr/singlemalt.18.js";
</script>
<script type="text/javascript" src=url></script>
Any ideas would be greatly appreciated!
EDITED:
Additional info:
I tried to use getScript as people have suggested but also had issues with it:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script>
$.getScript("https://av.ageverify.co/jsfr/singlemalt.18.js");
</script>
or this method:
function loadJs() {
var url = "https://av.ageverify.co/jsfr/singlemalt.18.js";
var script = document.createElement("script");
script.src = url;
document.head.appendChild(script);
}
This last one seems to work with other simple scripts, but maybe this particular script is looking for some sort of browser condition? Any suggestions on how to figure that out or what to look for? There should be an age verification page that pops up, asking your age.
HTML tags do not understand variables. You need to use a URL for the src attribute. HTML has no idea what your JavaScript variables are.
If you want to load the .js file this way, you need to use JavaScript. What you can do is create a new <script> tag then append it to the page.
var url = "https://av.ageverify.co/jsfr/singlemalt.18.js";
var script = document.createElement("script");
script.src = url;
document.head.appendChild(script);
If you are using jQuery, this is basically what $.getScript does.
var url = "https://av.ageverify.co/jsfr/singlemalt.18.js";
$.getScript(url);

Inserting a <script> tag dynamically via jQuery

I'm trying to add a widget to the page in run-time. Based on this post, I wrote the code below. Unfortunately, it doesn't show anything. Can anybody tell me why?
<script type="text/javascript">
$(document).ready(function () {
var s = document.createElement("script");
s.type = "text/javascript";
s.src = "https://widgets.factiva.com/syndication/subscriber/InsertWidget.ashx?tkn=LDyKkRh5SFskMPuGz6nika6Sg%2bqurZ4vspn0e1OvlEQc6JqLTdcyY8%2btC7a9zO0Z42ta%2f%2fl7QbCByRVbs7TTuQ%3d%3d%7c2&typ=0&st=1&target=7";
// Use any selector
$(".testWidget").append(s);
});
</script>
<div class="testWidget">
</div>
If I put the same script as below, it works and shows some information on the page. However, I should insert the script dynamically, not as static.
<div class="testWidget">
<script src="https://widgets.factiva.com/syndication/subscriber/InsertWidget.ashx?tkn=LDyKkRh5SFskMPuGz6nika6Sg%2bqurZ4vspn0e1OvlEQc6JqLTdcyY8%2btC7a9zO0Z42ta%2f%2fl7QbCByRVbs7TTuQ%3d%3d%7c2&typ=0&st=1&target=7" type="text/javascript" charset="utf-8"></script>
</div>
You should be getting this warning in the console, Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened. Here's a way around that:
<script type="text/javascript">
$(document).ready(function () {
// Save a copy of the document.write method
var oldWrite = document.write;
var s = document.createElement("script");
s.type = "text/javascript";
s.src = "https://widgets.factiva.com/syndication/subscriber/InsertWidget.ashx?tkn=LDyKkRh5SFskMPuGz6nika6Sg%2bqurZ4vspn0e1OvlEQc6JqLTdcyY8%2btC7a9zO0Z42ta%2f%2fl7QbCByRVbs7TTuQ%3d%3d%7c2&typ=0&st=1&target=7";
// After script is loaded, revert document.write to the original
s.onload = function () {
document.write = oldWrite;
};
var $testWidget = $('.testWidget');
// Redefine document.write to make the script's call work
document.write = function (html) {
$testWidget.html(html);
};
$testWidget.append(s);
});
</script>
The script tag you include programatically has to be parsed by the browser. Just by inserting the script tag the included code is not parsed by the JavaScript interpreter.
If you explain what you want to finally achieve I am pretty sure that must be a simpler way to do it.

loading a backup copy of jQuery when CDN is down

I have this code in a script we use for initializing all of our applications, it loads the jQuery from the google CDN amongst several other things that all of our applications require. Then when we load the specific program functionality we check to make sure that jquery has loaded, in case the CDN is down. The problem I am running into is it is still loading the second one. If I add a simple alert("Test"); after the line headTag.appendChild(jqTag); it works perfectly, but if I remove the alert it uses the second one. What gives?
They are loaded like so:
<script type="text/javascript" src="i-initializer.js"></script>
<script type="text/javascript" src="i-program.js"></script>
initializer script:
if(typeof jQuery=='undefined'){
var headTag = document.getElementsByTagName("head")[0];
var jqTag = document.createElement('script');
jqTag.type = 'text/javascript';
jqTag.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js';
headTag.appendChild(jqTag);
}
Then in another script we have the following:
if(typeof jQuery=='undefined'){
var header = document.getElementsByTagName("head")[0];
var qtag = document.createElement('script');
qtag.type = 'text/javascript';
qtag.src = 'http://feedback.oursite.com/scripts/jquery-1.8.3.min.js';
qtag.onload = checkjQueryUI;
header.appendChild(qtag);
}
else
{
jQCode();
}
jQCode() {
...
}
This is the technique used by HTML5 Boilerplate. First it loads the Google CDN script, then immediately checks if the global jQuery object exists -- if it doesn't, the CDN failed and a local copy is loaded instead.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.3.min.js"><\/script>')</script>
Your fallback code loads jQuery asynchronously.
That means that the rest of your scripts run before jQuery loads.
Adding an alert() call forces the rest of your code to wait (until you click OK); by the time that happens, jQuery will have loaded.
Instead, you can emit a new <script> tag using document.write() to load it synchronously.
Alternatively, you could wrap the rest of your code in a callback and call the callback(s) after jQuery loads.
If you do it this way, you should use a script loader library, which will handle all of that for you.

Combine 2 scripts into 1 file

I have two scripts that load in my head area which are:
<script type="text/javascript">
var myDate = new Date();
var myStamp = ""+myDate.getDate()+myDate.getMonth()+myDate.getFullYear()+myDate.getHours()+myDate.getMinutes();
document.write('<script type="text/javascript" src="https://scriptlocation.com/js/script.js?' + myStamp + '"><\/script>');
</script>
<script type="text/javascript">
document.write('<script type="text/javascript" src=""https://scriptlocation.com/js/script2.js?'+SVNInfo.revision+'"><\/script>');
</script>
My ideal scenario would be to merge these two into 1 javascript file, so I've tried to create a new file which contains the following:
var myDate = new Date();
var myStamp = ""+myDate.getDate()+myDate.getMonth()+myDate.getFullYear()+myDate.getHours()+myDate.getMinutes();
document.write('<script type="text/javascript" src="https://scriptlocation.com/js/script.js?' + myStamp + '"><\/script>');
document.write('<script type="text/javascript" src=""https://scriptlocation.com/js/script2.js?'+SVNInfo.revision+'"><\/script>');
however that does not seem to work as the script is not being loaded properly. Do I need to rewrite / change something to have this working correctly?
Some advice would be greatly appreciated.
This should do the trick.
<script type="text/javascript">
var myStamp = (new Date()).getTime(), //easier way to get a relatively unique timestamp
script1 = document.createElement('script'),
script2 = document.createElement('script'),
body = document.getElementsByTagName('body')[0];
script1.setAttribute('type', 'text/javascript');
script1.setAttribute('src', 'https://scriptlocation.com/js/script.js?' + myStamp);
script2.setAttribute('type', 'text/javascript');
script2.setAttribute('src', 'https://scriptlocation.com/js/script2.js?' + SVNInfo.revision); //is SVNInfo.revision defined?
body.appendChild(script1);
body.appendChild(script2);
</script>
For the record, document.write is an extremely primitive (and not a friendly way) of adding scripts to the page. Just create them as elements and then add them to the DOM.
SVNInfo is defined by the first script. So you can't include the second script (whose source path includes the value of SVNInfo) until you've executed the first.
When you document.write content from a <script> block, it's adding new content for the HTML parser at the point just after the </script> end-tag of the current block. If that content itself includes a <script> element, then the script inside it cannot start to execute until the current script has finished. So the </script><script> tags break up the current script execution allowing the script inserted by document.write to run. You won't be able to put both writes into the same script without breaking this.
You may be able to do it the way pete suggests with inserting script elements directly into the DOM, avoiding the parser completely. Because no parser is involved, the inserted script can execute straight away, without waiting for the current script block to complete.
However, you will need to ensure that the first script element is added to the document and run before you attempt to set the src of the second script element, because you need SVNInfo to be ready. Also, you should append the scripts to the <head> element and not <body> because writing to an element that hasn't been completely parsed yet is likely to cause the page load to abort in IE.
It is also possible that this might still not work, if there's something in the second script that expects to be running from a document.write-invoked script. Can't really see from here as the script is unreadable compressed.
Given that the integration doc tells you what it wants you to do, I'd stick with that; even if you have a better way, they might change the script at some point in the future in a way that relies on the two document.write scripts.

How to load Google's Custom-search-engine(CSE) JS APIs after page loads?

I am using Google Custom Search Engine with their new auto-completion feature. I want this whole javascript to be loaded AFTER the page itself is loaded. The original Google code is this:
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('search', '1');
google.setOnLoadCallback(function() {
google.search.CustomSearchControl.attachAutoCompletion(
'some-long-unique-id',
document.getElementById('q'),
'cse-search-box');
});
</script>
<script type="text/javascript" src="http://www.google.com/cse/brand?form=cse-search-box&lang=cs"></script>
I have transformed this code using tutorial about JS dynamic loading to this code:
(function() {
var goog = document.createElement('script'); goog.type = 'text/javascript';
goog.src = 'http://www.google.com/jsapi';
var cse = document.createElement('script'); cse.type = 'text/javascript';
cse.src = 'http://www.google.com/cse/brand?form=cse-search-box&lang=cs';
goog.onload = function() {
google.load('search', '1');
google.setOnLoadCallback(function() {
google.search.CustomSearchControl.attachAutoCompletion(
'some-long-unique-id',
document.getElementById('q'),
'cse-search-box');
});
};
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(cse, s);
s.parentNode.insertBefore(goog, s);
})();
Well, even though I think my solution should work(the same way has Google changed their Analytics on-demand asynchronous code), it doesn't. The page loads fine and as soon as CSE loads, the page goes blank. Something clears the DOM, I suppose its some kind of "Google thing" ? Can someone bring some light on this problem and possibly a working solution ?
Thanks
OK, so by checking Google Loader Developer's Guide and by lots of trying-and-testing I've figured how to change my code so it works as I expected in my question:
(function() {
var goog = document.createElement('script'); goog.type = 'text/javascript';
goog.src = 'http://www.google.com/jsapi';
goog.onload = function() {
google.load('search', '1', {"callback": function() {}});
google.setOnLoadCallback(function() {
google.search.CustomSearchControl.attachAutoCompletion(
'some-long-unique-id',
document.getElementById('q'),
'cse-search-box');
});
};
var cse = document.createElement('script'); cse.type = 'text/javascript';
cse.src = 'http://www.google.com/cse/brand?form=cse-search-box&lang=cs';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(cse, s);
s.parentNode.insertBefore(goog, s);
})()
The main thing is this line:
google.load('search', '1', {"callback": function() {}});
If you don't specify callback (at least empty function as I do), then the whole page goes blank, when Google's CSE loads. I have no idea why, but it works fine now with this dummy callback function.
Hope it helps someone with the same problem.
I guess you can use some js loader (eg yepnope) that allows you to load js on demand and add a callback.
I don't fully-understand what you're trying to achieve. You've asked for someone to suggest how to 'correct' your code, but you haven't given any context, or what you actually want the end-result to be.
Also, the updates you've provided with the function()s you've written- it's not clear how these are being called. In the when the document readyState is complete?
Firstly, I'd suggest using jQuery to wrap up the JavaScript stuff. Yes, Google provide onload events and other helpers for their API, but jQuery will apply to any Javscript, there's no point in using two Javascript frameworks where you don't have to.
The jQuery might be like this:
<script type="text/javascript" language="javascript" src="/js/jquery/jquery-1.4.2.min.js"></script>
<script type="text/javascript" language="javascript">
// Use the jQuery document load functionality.
$(document).ready(function ()
{
// Load the Google API asynchronously. The callback 'GoogleApiLoaded' will be called when the script is fully-loaded.
$.getScript("http://www.google.com/jsapi?key=yourkey", GoogleApiLoaded);
// Load other scripts, do other init code here (non-Google-dependent).
});
function GoogleApiLoaded()
{
// Google-related init here.
// Load the custom search API.
// (Could make the callback an in-line function).
$.getScript("http://www.google.com/cse/brand?form=cse-search-box&lang=cs", CustomSearchApiLoaded);
}
function CustomSearchApiLoaded()
{
google.load('search', '1', LoadCustomSearchControl);
}
function LoadCustomSearchControl()
{
google.search.CustomSearchControl.attachAutoCompletion('some-long-unique-id', document.getElementById('q'), 'cse-search-box');
}
</script>
It might be helpful to break the code apart into different functions, in order to track-down more easily where the problem is. That you have to put in an optional callback on the 'google.load()' function is strange- it may be a bug in the Google code, there are some floating around.
I've used google.load('search', '1', LoadCustomSearchControl), rather than the google.setOnLoadCallback, because as far as I can see they should do the same thing, and using a callback on load() is neater, in my view.
I'd strongly advise you use jQuery (or any JavaScript framework), as it makes life a lot easier.
I'd be interested to see whether what I've suggested works, and if not where it goes wrong. (Make sure to add-in your own JSAPI key).

Categories

Resources