lightbox2 fallback when cdn js cloudflare is unavailable - javascript

I'm loading lightbox2 via the following CDN //cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/js/lightbox.min.js
if this is unavailable then I want to fallback to my core files. How do I check to see if lightbox has already been defined so as to avoid loading my core files.
I tried typeof lightbox === "undefined" but that always returns true forcing my core files to be loaded.
I have fallbacks for jquery, angular etc already - it is lightbox2 that I am having issues with checking if it has already been loaded.

Yes, the problem here is that there is nothing in global scope because lightbox doesn't add anything to it. (see this SO question). That's why you can't test it like window.lightbox.
A workaround is to load the script with an ajax request like in the demo below. The getScript method is a shorthand Ajax function (see here for details).
There you have a fail callback where you can add your local script to the DOM if loading of the cdn fails.
You can do the same for any file that you're loading from a cdn (e.g. the stylesheet of lightbox).
var addLocalScript = function (src) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = src; // use this for linked script
//script.text = "alert('voila!');" // use this for inline script
document.body.appendChild(script);
};
$(function () {
var url = 'https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/js/lightbox.min.js';
$.getScript(url)
.done(function (script, textStatus) {
console.log(textStatus);
})
.fail(function (jqxhr, settings, exception) {
console.log('cdn load failed');
//add local script
addLocalScript('js/lightbox/lightbox.min.js');
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/css/lightbox.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="http://lorempixel.com/400/200"/>

Related

How to conditionally include assets in the <head> with Angular

I am building a one-page Angular app. One of the views has content which depends on an external javascript library.
I don't want to include this external JS resource on every view of the site, just the single view which depends on it.
What is the best way to conditionally include blocks of code based on the current view?
If it's possible I'm hoping I can place in the something like this:
<script ng-if="view == 'view1'" type='text/javascript' src='http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject2.js'></script>
So you should include the library script in page.
Then within directive bound to elements it needs to act on do the initialization.
app.directive('unity', function () {
return {
link: function (scope, element, attrs) {
// element is jQuery object when jQuery.js is included in page
// before angular - or it is a jQLite object similar to a jQuery object
// config code
u.initPlugin(element[0], "web_ovar_beta.unity3d");
}
}
});
Usage in view:
<div unity></div>
This can easily be expanded to pass in attributes to the directive from controller
It is
<script ng-if="view == 'view1'" type='text/javascript' ng-src='http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject2.js'></script>
And it is something that you don't want to do. It doesn't guarantee that the script won't be loaded twice. Since the script is being used for particular view, make it one-time resolving service
app.factory('unityResolver', function ($document, $rootScope, $q, $timeout) {
var deferred = $q.defer();
var script = angular.element('<script>')[0];
script.src = '...';
script.async = true;
script.onload = script.onreadystatechange = function () {
if (['loaded', 'complete', undefined].indexOf(script.readyState) < 0)
return;
script.onload = script.onreadystatechange = null;
deferred.resolve();
$rootScope.$apply();
}
script.onerror = function onerror() {
script.onerror = null;
deferred.reject();
$rootScope.$apply();
};
$timeout(onerror, 20000);
$document.find('head').append(script);
return deferred.promise;
});
and use it in view/route resolve.
What your wanting to in turn is impossible.
You can get Javascript to include a javascript file if you want however if your using AJAX to load the content that is needed leave it in there it would be the same amount of time to load anyway. but once a file has been loaded into JavaScript it finished with you can remove the file from your HTML but the JavaScript engine still has the content of that file loaded in to it.
Try it in your browsers(chrome or FF with Firebug) inspector now:
open a new tab and go to about:blank then put the code below into the console
var include = (function(){
// the reference to the script
var theScript;
return function (filename, status){
if(status == 'on'){
// adding a script tag
var head = document.getElementsByTagName('head')[0];
theScript= document.createElement('script');
theScript.src = filename;
theScript.type = "text/javascript";
head.appendChild( theScript )
}else{
// removing it again
theScript.parentNode.removeChild( theScript );
}
}
})();
taken from Remove specific <script> tag in <head> tag by onclick event
then in your inspector's console
include("https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js", 'on')
now check Elements and you will see jQuery loaded in the pages head tag.
and type jQueryinto console and you will see function (a,b){return new n.fn.init(a,b)}
And then use this into your console
include("https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js", 'off')
and check your elements tab again the script tag will have gone.
however go back to console and type jQuery again and you will see function (a,b){return new n.fn.init(a,b)} as even though you have unloaded the file you can't remove the executed code from memory.
You have 2 options another framework page gets loaded into an iFrame or if you want to use Anagular to load the View in then just include the file in your head there is no point not having and then removing it as once it is loaded it's loaded

Load JavaScript dynamically [duplicate]

This question already has answers here:
JQuery to load Javascript file dynamically
(2 answers)
Closed 7 years ago.
I have a web page and a canvas with Google Maps embedded in it. I am using jQuery on this site.
I want to load Google Maps API only if the user clicks on "Show me the map". Further, I want to take away the whole loading of the Google Maps from the header in order to improve my page performance.
So I need to load JavaScript dynamically. What JavaScript function I can use?
You may want to use jQuery.getScript which will help you load the Google Maps API javascript file when needed.
Example:
$.getScript('http://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=true', function(data, textStatus){
console.log(textStatus, data);
// do whatever you want
});
Use the Loading on Demand Loading Strategy
Loading on Demand
The previous pattern loaded additional JavaScript unconditionally after page load, assuming
that the code will likely be needed. But can we do better and load only parts of
the code and only the parts that are really needed?
Imagine you have a sidebar on the page with different tabs. Clicking on a tab makes an
XHR request to get content, updates the tab content, and animates the update fading
the color.
And what if this is the only place on the page you need your XHR and animation
libraries, and what if the user never clicks on a tab?
Enter the load-on-demand pattern. You can create a require() function or method that
takes a filename of a script to be loaded and a callback function to be executed when
the additional script is loaded.
The require() function can be used like so:
require("extra.js", function () {
functionDefinedInExtraJS();
});
Let’s see how you can implement such a function. Requesting the additional script is
straightforward. You just follow the dynamic element pattern. Figuring out
when the script is loaded is a little trickier due to the browser differences:
function require(file, callback) {
var script = document.getElementsByTagName('script')[0],
newjs = document.createElement('script');
// IE
newjs.onreadystatechange = function () {
if (newjs.readyState === 'loaded' || newjs.readyState === 'complete') {
newjs.onreadystatechange = null;
callback();
}
};
// others
newjs.onload = function () {
callback();
};
newjs.src = file;
script.parentNode.insertBefore(newjs, script);
}
“JavaScript Patterns, by Stoyan Stefanov
(O’Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750.”
you would just generate the script tag via javascript and add it to the doc.
function AddScriptTag(src) {
var node = document.getElementsByTagName("head")[0] || document.body;
if(node){
var script = document.createElement("script");
script.type="text/javascript";
script.src=src
node.appendChild(script);
} else {
document.write("<script src='"+src+"' type='text/javascript'></script>");
}
}
I think you're loking for this http://unixpapa.com/js/dyna.html
<input type="button" onclick="helper()" value="Helper">
<script language="JavaScript">
function helper()
{
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'your_script_url';
head.appendChild(script);
}
</script>
I used the Tangim response, but after found that is more easy use jquery html() function. When we make ajax request to html file that have html+javascript we do the follow:
$.ajax({
url:'file.html',
success:function(data){
$("#id_div").html(data); //Here automatically load script if html contain
}
});

detect and suppress errors loading javascript file

I want to source a javascript file from facebook http://connect.facebook.net/en_US/all.js
The organization I work for has a firewall that blocks access to Facebook, it just goes to an html page that says "Access Denied blah blah blah"
I want to be able to put a javascript src tag <script src="http://... "> </script> and detect and suppress the warnings when the browser tries to evaluate the html as javascript.
Anyone know how?
Looks like jQuery.getScript is what you need as was mentioned. Or you can manually execute:
$.ajax({
url: url,
dataType: 'script',
success: function(){document.write('<script src="http://... "> </script>');}
});
And append your html on successful load with the <script></script> tag.
With the standard <script> tag, not possible. There's nothing really running at the time when the script's src is hit and content downloaded, so you can't wrap that in a try/catch block. There's some tips here on how to dynamically load scripts. Maybe the browsers will add some stuff to the DOM element created there which you can check for.
This is a workaround, not a direct answer, but you could simply set up a reverse proxy outside the firewall for Facebook and load the script from there. Instead of failing more gracefully, it would allow the script not to fail.
Try this, and see if it works for you:
<script type="text/javascript" onerror="throw('An error occurred')" src="http://connect.facebook.net/en_US/all.js"></script>
Alternatively, if you have access to a proxy script to grab external content I would use it via an xmlHttpRequest to grab the JS content. If it is successful, eval the content (yes, eval is evil, I know).
I would add that if you know the JS will fail, then why bother?
Why do you not do this in very simple way?:
if(!window.FB) { // or (typeof window.FB === "undefined")
alert ("ERROR: http://connect.facebook.net/en_US/all.js is not loaded");
}
if(!window.jQuery) { // or (typeof window.jQuery === "undefined")
alert ("ERROR: jQuery is not loaded");
}
// and so on
Please try the function below, it will only call the onload_function if the script has loaded. You can set a timeout to cancel the script.
function include_js(url, onload_function) {
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) {
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
onload_function();
}
};
} else {
script.onload = function(){
onload_function();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
In Firefox and IE, you should be able to use window.onerror for this. You can take advantage of the fact that scripts run in the order they are listed in the HTML to wrap an error handler around just the facebook script:
<script>
// Remember old error handler, if there is one.
var oldOnError = window.onerror;
// Special error handler for facebook script
window.onerror = function(message, url, linenumber) {
// Potentially alert the user to problem
alert('Problem with facebook: ...');
// Return true to suppress default error handling
return true;
}
</script>
<!-- Load facebook script -->
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>
// Remove error handler for facebook script
window.onerror = oldOnError;
</script>

Loading scripts dynamically

I'm loading a few YUI scripts dynamically in my code in response to an Ajax request. The DOM and the page is fully loaded when the request is made - it's a response for an user event.
I add the <scripts> tag to head as children, but I stumbled in a few problems:
I add two YUI scripts hosted at the Yahoo! CDN and an inlined script of my own responsible for creating object, adding event listeners and rendering the YUI widgets. But I when my script run the YUI scripts are not loaded yet giving me errors and not running as I expect.
There's a way to only run my script (or define a function to be run) when YUI scripts are fully loaded?
Have you tried an onload event?
Edited:(thanks Jamie)
var script = document.createElement("script");
script.type = "text/javascript";
script.src = src;
//IE:
if(window.attachEvent && document.all) {
script.onreadystatechange = function () {
if(this.readyState === "complete") {
callback_function(); //execute
}
};
}
//other browsers:
else {
script.onload = callback_function; //execute
}
document.getElementsByTagName("head")[0].appendChild(script);
If you're using YUI 2.x I highly recommend using the YUI Get utility, as it's designed to handle just this sort of a problem.
If you are loading multiple individual script files from the Yahoo! CDN, you'll need to makes sure both are loaded before executing your dependent code. You can avoid this using the combo handler. See the Configurator to get what the script url should be to load both/all needed YUI files from one url.
http://developer.yahoo.com/yui/articles/hosting/
With that in mind, assuming you must load the YUI files asynchronously, you should use an onload/onreadystatechange handler as noted by digitalFresh.
I would recommend the following pattern, however:
(function (d) {
var s = d.createElement('script'),
onEvent = ('onreadystatechange' in s) ? 'onreadystatechange' : 'onload';
s[onEvent] = function () {
if (("loaded,complete").indexOf(this.readyState || "loaded") > -1) {
s[onEvent] = null;
// Call your code here
YAHOO.util.Dom.get('x').innerHTML = "Loaded";
}
};
// Set the src to the combo script url, e.g.
s.src = "http://yui.yahooapis.com/combo?2.8.1/...";
d.getElementsByTagName('head')[0].appendChild(s);
})(document);
You could use a setTimeout() to run some function that just checks if it's loaded - check something like
if (typeof YUI_NAMESPACED_THING !== "undefined") runCode()
EDIT Thanks, CMS
If I understand this correctly, your ajax response with this:
<script href="yui-combo?1"></script>
<script href="yui-combo?2"></script>
<p>some text here</a>
<script>
// using some of the components included in the previous combos
// YAHOO.whatever here...
</script>
If this is the case, this is a clear case in which you should use dispatcher plugin. Dispatcher will emulate the browser loading process for AJAX responses. Basically it will load and execute every script in the exact order.
Best Regards,
Caridy

Injecting jQuery into a page fails when using Google AJAX Libraries API

I'd like to inject jQuery into a page using the Google AJAX Libraries API, I've come up with the following solution:
http://my-domain.com/inject-jquery.js:
;((function(){
// Call this function once jQuery is available
var func = function() {
jQuery("body").prepend('<div>jQuery Rocks!</div>');
};
// Detect if page is already using jQuery
if (!window.jQuery) {
var done = false;
var head = document.getElementsByTagName('head')[0];
var script = document.createElement("script");
script.src = "http://www.google.com/jsapi";
script.onload = script.onreadystatechange = function(){
// Once Google AJAX Libraries API is loaded ...
if (!done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) {
done = true;
// ... load jQuery ...
window.google.load("jquery", "1", {callback:function(){
jQuery.noConflict();
// ... jQuery available, fire function.
func();
}});
// Prevent IE memory leaking
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
}
// Load Google AJAX Libraries API
head.appendChild(script);
// Page already using jQuery, fire function
} else {
func();
}
})());
The script would then be included in a page on a separate domain:
http://some-other-domain.com/page.html:
<html>
<head>
<title>This is my page</title>
</head>
<body>
<h1>This is my page.</h1>
<script src="http://my-domain.com/inject-jquery.js"></script>
</body>
</html>
In Firefox 3 I get the following error:
Module: 'jquery' must be loaded before DOM onLoad! jsapi (line 16)
The error appears to be specific to the Google AJAX Libraries API, as I've seen others use a jQuery bookmarklet to inject jQuery into the current page. My question:
Is there a method for injecting the Google AJAX Libraries API / jQuery into a page regardless of the onload/onready state?
If you're injecting, it's probably easier to request the script without using the google loader:
(function() {
var script = document.createElement("script");
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js";
script.onload = script.onreadystatechange = function(){ /* your callback here */ };
document.body.appendChild( script );
})()
I found this post after we figured out a different solution. So for some reason, if you can't use the accepted solution, this one seem to work fine:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
if (typeof jQuery == 'undefined') {
// jQuery hasn't been loaded... so let's write it into the head immediately.
document.write('<script type="text/javascript" src="/jquery-1.3.2.min.js"><\/script>')
}
</script>
One issue with the accepted solution is that you're forced to put all your code that you want to run on the page into your callback function. So anything that needs jQuery (like plugins) need to be called from that function. AND, all your other included JS files that require jQuery are dependent upon jQuery being loaded BEFORE all the other scripts fire.
I Got It Working!!!!! I figured it out by looking in the application playground....
Here is the wrapper to start using jquery.... Put an alert in the function to see it work
google.load("jquery", "1.4.2");
function OnLoad(){
$(function(){
});
}
google.setOnLoadCallback(OnLoad);
You can use less painful solution to inject jquery (the lastest stable version available) to any page.
jQuerify - Chrome extension used to inject jQuery (the latest stable version available) into any web page (even HTTPS)"

Categories

Resources