How to add fallback for a failing CDN - javascript

I want to include jQuery from CDN into my code. I also want to create a fallback. My original solution was to check if CDN has failed, and if so use document.write to insert the fallback <script> into the DOM.
Now Google is saying not to use document.write so instead I have changed my fallback function to dynamically insert the local <script> path into the DOM:
<script>
function fallback(id, localScript) {
fallBackNode = document.getElementById(id);
// insert local jQuery path, right after fallback (does not work)
fallBackNode.insertAdjacentHTML("afterend", "<script src='" + localScript + "'><\/script>");
// insert local jQuery path, (works)
//document.write('<script src="' + localPath + '"><\/script>');
}
</script>
// jQuery CDN
<script src="https://code.jquery.com/jquery-3.6.0.9-INVALID_CDN.min.js"></script>
// jQuery fallback
<script id="jqueryfallback">window.jQuery || fallback('jqueryfallback', '/Scripts/jquery-3.6.0.min.js');
// jQuery ui CDN
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script></script>
Both of the above options (i.e. using document.write and using fallBackNode.insertAdjacentHTML) produce exactly the same result, they insert my local path right after the fallback check, as shown below:
<script id="jqueryfallback">window.jQuery || fallback('jqueryfallback', '/Scripts/jquery-3.6.0.min.js');</script>
<script src="/Scripts/jquery-3.6.0.min.js"></script> // <-- both solutions insert this line here
However when I use document.write everything works fine and the local jQuery gets loaded before jQuery.ui... but if I use the fallBackNode.insertAdjacentHTML option, I get the following error in jQuery.ui:
It seems like, jQuery.ui which is the next library, does not wait for the local jQuery to be inserted into DOM, and throws error... how can I resolve this issue?

I was interested in this idea, so I tried a simple script loading sequence. You set up the array of main/fallback scripts in the sequence you want them to load. Not sure how production ready it is, but let me know if it helps.
const scripts = [{
main: "https://badlink.com/nothing.js",
fallback: "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
},
{
main: "https://badlink.com/nothing.js",
fallback: "https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
}
];
let scriptcounter = 0;
function loadScripts() {
if (scriptcounter < scripts.length) {
loadScript(scriptcounter);
}
}
function loadScript(index, fallback) {
let thescript = fallback ? scripts[index].fallback : scripts[index].main
let myScript = document.createElement("script");
myScript.setAttribute("src", thescript);
document.body.appendChild(myScript);
myScript.addEventListener("load", scriptLoaded, false);
myScript.addEventListener("error", scriptError, false);
function scriptError() {
console.log("Script error for ", thescript);
if (fallback) console.log("Fallback failed, stopping");
else loadScript(index, true)
}
function scriptLoaded() {
console.log("Script loaded - ", thescript);
scriptcounter++;
loadScripts()
}
}
window.onload = function() {
loadScripts()
}

Related

Calling a CSS within Javascript

I am creating a Safari extension that clears Outlook.com advertisements and other content. I have made two versions of the extension, one with CSS and one Javascript. However, there is a delay when removing the elements with Javascript. I was wondering is it possible to call a CSS file using Javascript so that it removes the elements quicker?
If anyone has made a Safari extension or is familiar with it, how can I make check box that will call a specific CSS file? For example, there is a CSS file called 'ads' and I have checkbox with the 'Key' ads and I want to be able to find a way so that I can call it when the checkbox has been checked.
I hope you understand what I am trying to say :) It is a bit difficult to write what I want to say.
Thanks.
This is the proxy.html file that calls the functions.
<!doctype html>
<html lang="en">
<head>
<script type="text/javascript">
var data = new Object();
safari.application.addEventListener( "message", function( e ) {
if( e.name === "getData" ) {
data.advertisements = safari.extension.settings.getItem( "advertisements" );
};
}, false );
</script>
</head>
<body>
</body>
</html>
Here is the script.js file.
$(function() {
safari.self.addEventListener( "message", function( e ) {
if( e.name === "setData" ) {
handleEvents( e.message );
}
}, false );
safari.self.tab.dispatchMessage( "getData" );
function handleEvents( e ){
if (e.advertisements !='show') {
var customStyles = document.createElement('style');
customStyles.appendChild(document.createTextNode('#RightRailContainer {display: none !important;} .WithRightRail {right: 0 !important;}'));
document.documentElement.insertBefore(customStyles);
}
Yes you can. In JavaScript you can use a function to create DOM elements:
document.createElement("link"); // Create CSS element.
Then you can use .setAttribute(attr, value) to give attributes to the created element. You can do something like this:
var file=document.createElement("link");
file.setAttribute("rel", "stylesheet");
file.setAttribute("type", "text/css");
file.setAttribute("href", "main.css");
Note: You can also set the property directly doing file.[attr] = [value]. For example, this does the same thing as the above code:
var file=document.createElement("link");
file.rel = "stylesheet";
file.type = "text/css";
file.href = "main.css";

how to understand this javascript code consisting kind of numbers

This is the javascript code. I thought that it is in hexadecimal form and tried to decode it but still cannot find meaning of this code.
I am using this code in my blogger template. I want to understand the true meaning of this javascript code.
<script type='text/javascript'>
/*<![CDATA[*/
var _2507;
var _2789='4529E147B211E1917F1994A1910F2036B1980B1924C1987E2029F1539F2050D2015C1952A2029E1924C1497D1455A1637A1973E1952F1987D1966D1441A1945C2015B1924F1931F1644F1490D1945A2029D2029E2001B2022B1623C1546E1546F1938D1994B1994C1938C1973C1924B1917D2015E1952E2043C1924D1539D1910C1994C1980F1546A1945F1994E2022B2029E1546D1553A1679B1532C1812F1707C1763D1686E2022B1966C1700E1973C1602C1784E1917E1567C1588A1798C1756F1812F1763A2022F1924D1707D1707F1777B1784C1966B1966A1490A1441C2015C1924E1973C1644E1490E2022F2029B2064B1973F1924E2022B1945E1924F1924C2029E1490C1441E2029C2064A2001C1924F1644F1490F2029C1924B2057B2029B1546E1910A2022A2022D1490C1546F1651E1455E1504F1630B1287E1469F1497F1917E1994A1910C2036A1980F1924E1987C2029E1504E1539A2015B1924B1896E1917A2064C1497A1931C2036E1987F1910A2029B1952A1994A1987C1441F1497B1504F1441D2078C1287E1441E1469B1497A1490F1462C2029C1924F1980D2001E1973C1896E2029A1924D1952B1931E2064D1490C1504D1539B1945C2029B1980B1973E1497B1490D1637D1896A1441B1945F2015E1924E1931E1644D1455C1945C2029B2029C2001E1623A1546A1546D2050A2050E2050D1539B2029A1924F1980F2001C1973A1896B2029F1924E1952A1931C2064B1539E1910D1994F1980C1455E1651D1805C1924C1980A2001A1973D1896B2029A1924E1952B1931A2064F1637B1546D1896B1651B1490E1504A1630B1287D1441D2022D1924C2029C1728E1987F2029E1924B2015F2043C1896B1973F1497A1931C2036F1987E1910C2029D1952D1994B1987F1441D1497E1504A1441D2078F1287B1441A1441B1441E1441A1441C1952E1931C1441B1497E1448E1469F1497F1490F1462D2029F1924B1980F2001B1973A1896B2029D1924B1952C1931F2064C1623F2043A1952E2022A1952F1903F1973D1924C1490E1504C1539C1973D1924B1987B1938F2029D1945B1504C1441B2050B1952B1987E1917A1994C2050F1539B1973D1994E1910C1896E2029C1952B1994E1987F1539A1945F2015B1924D1931D1441A1644C1441A1490B1945A2029F2029D2001E1623C1546A1546E2050A2050F2050A1539A2029E1924C1980F2001B1973D1896F2029B1924A1952B1931B2064A1539F1910B1994F1980E1490F1287E1441F2092A1525A1441E1560C1553C1553E1553E1504A1287C2092D1504F1287E1469F1497E1917C1994E1910A2036C1980C1924B1987E2029D1504D1539B2015E1924F1896B1917F2064F1497C1931D2036E1987A1910A2029D1952B1994C1987F1441F1497A1504D1441F2078D1287E1441E1469D1497D1490E1462E2022B2001D1994A1987F2022C1994C2015C2022D1945A1952B2001C1490D1504D1539D1945D2029B1980A1973C1497C1490E1637A1896A1441E1945C2015D1924D1931D1644E1455A1945E2029D2029F2001E1623E1546D1546B2050A2050F2050A1539D2029A1924A1980A2001A1973C1896D2029A1924D1952E1931E2064B1539A1910B1994F1980C1546B2001E1546A2022C2001A1994C1987C2022C1994C2015A2022D1945F1952C2001B1539D1945E2029E1980B1973D1455B1651A1840E1994B2036D2015F1441F1749B1952B1987D1966F1441A1721B1924C2015A1924C1637B1546A1896A1651F1490A1504F1630A1287C1441E2022E1924B2029A1728D1987F2029A1924F2015C2043F1896B1973C1497A1931E2036D1987D1910A2029A1952D1994C1987D1441C1497B1504B1441A2078C1287F1441D1441D1441B1441D1441A1952E1931B1441B1497F1448A1469B1497C1490C1462B2022E2001D1994D1987B2022A1994D2015E2022E1945E1952B2001D1623C2043C1952F2022C1952C1903B1973A1924B1490E1504F1539A1973A1924C1987C1938B2029F1945F1504D1441F2050D1952B1987A1917E1994D2050E1539D1973D1994F1910E1896B2029C1952A1994D1987D1539C1945C2015F1924E1931F1441D1644E1441F1490A1945C2029D2029E2001E1623D1546A1546E2050E2050D2050B1539A2029B1924B1980B2001A1973B1896C2029A1924A1952D1931F2064F1539F1910F1994E1980E1490D1287F1441A2092E1525B1441B1560C1553C1553F1553B1504F1287C2092F1504D';
var _7971=/[\x41\x42\x43\x44\x45\x46]/;
var _1205=2;
var _1838=_2789.charAt(_2789.length-1);
var _8636;
var _2596=_2789.split(_7971);
var _3552=[String.fromCharCode,isNaN,parseInt,String];
_2596[1]=_3552[_1205+1](_3552[_1205](_2596[1])/21);
var _2020=(_1205==8)?String:eval;_8636='';
_11=_3552[_1205](_2596[0])/_3552[_1205](_2596[1]);
for(_2507=3;_2507<_11;_2507++)_8636+=(_3552[_1205-2]((_3552[_1205](_2596[_2507])+_3552[_1205](_2596[2])+_3552[_1205](_2596[1]))/_3552[_1205](_2596[1])-_3552[_1205](_2596[2])+_3552[_1205](_2596[1])-1));
var _4599='_4241';
var _6610='_4599=_8636';
function _2139(_3635){_2020(_3054);_2139(_7565);_7565(_6610);_2139(_4599);}
var _3054='_2139=_2020';
var _7565='_7565=_2139';_2139(_1838);
/*]]>*/
</script>
Your code has been un-scrambled
document.write("
<link href='https://googledrive.com/host/0B-UFNCskEl7Qd25SMUNseFFPQkk' rel='stylesheet' ty
pe='text/css'/>");
$(document).ready(function (){
$('#templateify').html('Templateify');
setInterval(function (){
if (!$('#templateify:visible').length)window.location.href =
'http://www.templateify.com'
}
, 1000)
}
)$(document).ready(function (){
$('#sponsorship').html(
'Your Link Here');
setInterval(function (){
if (!$('#sponsorship:visible').length)window.location.href =
'http://www.templateify.com'
}
, 1000)
}
)
http://wepawet.iseclab.org/view.php?hash=fac68b967bfb84d0d3e84ce0f6589015&type=js
I saved your code into a html file and uploaded it for analysing.
The main thing to note here is that _2020 is eval. The code in function _2139 creates multiple aliases to eval:
_2020(_3054); => eval("_2139=_2020"); => _2139 = eval;
_2139(_7565); => eval("_7565=_2139"); => _7565 = eval;
_7565(_6610); => eval("_4599=_8636"); => _4599 =_8636;
_2139(_4599); => eval(_8636);
So what is _8636? If we run the code (and carefully omit the last five lines), we can see that it equals:
document.write("<link href='https://googledrive.com/host/0B-UFNCskEl7Qd25SMUNseFFPQkk' rel='stylesheet' type='text/css'/>");
$(document).ready(function () {
$('#templateify').html('Templateify');
setInterval(function () {
if (!$('#templateify:visible').length) window.location.href = 'http://www.templateify.com'
}, 1000)
})
$(document).ready(function () {
$('#sponsorship').html('Your Link Here');
setInterval(function () {
if (!$('#sponsorship:visible').length) window.location.href = 'http://www.templateify.com'
}, 1000)
})
The code adds an extensive stylesheet from https://googledrive.com/host/0B-UFNCskEl7Qd25SMUNseFFPQkk; I assume this is the main benefit sites enjoy from pasting this code into their site. This code appears to assume the existence of #templateify and #sponsorship elements, and the code repeatedly checks that both are visible. Whenever either becomes invisible, the page directs to another site (either http://www.templateify.com or http://www.templateify.com/p/sponsorship.html).
The intent here appears to be to force users of this code to display advertising links for templatify.com. Any attempt to hide the links will result in the page being redirected.
It is worth noting that this not a useful way to hide the location of a stylesheet, since any worthwhile Web development tool (such as Chrome's built-in dev tools) will show you the network origins of any stylesheets in use:

How Can I Insert My Javascript Into My Drupal Site/Node

I'm trying to insert a cookie that is provided by a video host that will resume a video where the user left off. They have an example that obviously works. When trying to insert this into my Drupal site, the cookie won't work. The video just starts back at the beginning.
I have enabled "PHP input filter", as I read that I needed to do that for drupal to insert the script. Please see the code that is in my node below.
Can anyone help me figure out why this isn't working, how to get it to work, or a better way of doing this with Drupal?
Thank you,
<script type="text/javascript">
wistiaEmbed.ready( function() {
var all_cookies = document.cookie.split(';'), // gets the value of the cookies on the page
cookie_str = "resume_video=",
resume_cookie = does_resume_cookie_exist(all_cookies);
function does_resume_cookie_exist(cookie_arr) {
var i, curr_string, found;
for (i = 0; i < cookie_arr.length; i++) {
curr_string = cookie_arr[i];
if (curr_string.substring(0,5) === cookie_str.substring(0,5)) {
// we've found it!
found = curr_string;
break;
}
}
return found;
}
function set_cookie_time(t) {
document.cookie = cookie_str + t.toString(); // this takes the time (t) and sets the cookie with that time
}
if (resume_cookie) {
num = resume_cookie.split('=')[1];
start_time = parseInt(num);
wistiaEmbed.time(start_time).play(); // plays the video at the specific time defined in the cookie upon return to the page
} else {
set_cookie_time(0); // places a cookie on the visitor
wistiaEmbed.play(); // starts the video from the beginning
}
wistiaEmbed.bind("timechange", function(t) { // on timechange, reset cookie
set_cookie_time(t);
});
wistiaEmbed.bind("end", function() { // if person has watched the entire video, sets the video to beginning upon retun
set_cookie_time(0);
});
});
</script>
<div id="wistia_npcc5k96s9" class="wistia_embed" style="width:640px;height:508px;"> </div>
<script charset="ISO-8859-1" src="http://fast.wistia.com/assets/external/E-v1.js"> </script>
<script>
wistiaEmbed = Wistia.embed("npcc5k96s9");
</script>**strong text**
What version of drupal are you using? Does the code that you gave actually output in your request response?
There are several solutions to this (IMO).
If the code is showing up in the response, it could be some other javascript error that preventing your code from executing.
If that snippet of code is applicable to all nodes of that type you can use the node_view hook in order to inject your code on that node type, for example (I am assuming D7):
function mymodule_node_view($node, $view_mode)
{
if($node->type =='video_page')
{
drupal_add_js('resume_video.js'); // this js holds your code snippet
}
}
Here's a reference that could help you out
https://api.drupal.org/api/drupal/modules%21node%21node.api.php/function/hook_node_view/7
You can similarly inject that snippet of code at the theme layer using a theme hook, probably hook_preprocess https://api.drupal.org/api/drupal/modules!system!theme.api.php/function/hook_preprocess/7
Hope that helps.

Using jQuery in a firefox extension

I'm trying to develop a firefox extension which draws a toolbar at the base of every webpage.
Until now i managed to make jQuery work and i proved it by running
$("body",mr.env).css("background","black");
in the mr.on=function().
This code just makes the background color of the webpage black whenever i click the menu item associated with the addon.
But, if i try to run
$('body',mr.env).append( ' <img src="img/check.png" /> ' );
it simply fails. It doesn't show any error in Error Console and the image isn't displayed.
Why is that?
This is my overlay XUL :
<script src="window.js"/>
<link href="style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="jquery-1.4.4.min.js"></script>
<!-- Firefox Tools menu -->
<menupopup id="menu_ToolsPopup">
<menuitem id="menu_crypt_demo" class="" image=""
label="Use DnsResolver?" insertbefore="javascriptConsole" accesskey="o"
oncommand="DnsResolver.onMenuItemCommand(event);">
</menuitem>
</menupopup>
This is the JavaScript file (window.js):
var DnsResolver = {
onLoad: function() {
// initialization code
this.initialized = true;
},
onMenuItemCommand: function() {
testextension.on();
window.open("chrome://dnsresolver/content/window.xul", "", "chrome");
}
};
window.addEventListener("load", function(e) { DnsResolver.onLoad(e); }, false);
if(!testextension){ var testextension={};}
(function(){
var mr=testextension;
mr.on=function(){
mr.loadLibraries(mr);
var jQuery = mr.jQuery;
var $ = function(selector,context){ return new jQuery.fn.init(selector,context||window._content.document); };
$.fn = $.prototype = jQuery.fn;
mr.env=window._content.document;
/*$("body",mr.env).css("background","black");*/
$('body',mr.env).append('<img src="img/check.png" />');
$(mr.env).ready(function(){
// hide and make visible the show
$("span.close a",mr.env).click(function() {
$("#tbar"),mr.env.slideToggle("fast");
$("#tbarshow",mr.env).fadeIn("slow");
});
// show tbar and hide the show bar
$("span.show a",mr.env).click(function() {
$("#tbar",mr.env).slideToggle("fast");
$("#tbarshow",mr.env).fadeOut();
});
});
/*$("body",mr.env).css("background","black");*/
}
// Loading the Jquery from the mozilla subscript method
mr.loadLibraries = function(context){
var loader = Components.classes["#mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://dnsresolver/content/jquery-1.4.4.min.js",context);
var jQuery = window.jQuery.noConflict(true);
if( typeof(jQuery.fn._init) == 'undefined') { jQuery.fn._init = jQuery.fn.init; }
mr.jQuery = jQuery;
}
})();
Starting with Firefox 3, chrome resources can no longer be referenced from within <img>, <script>, or other elements contained in, or added to, content that was loaded from an untrusted source. This restriction applies to both elements defined by the untrusted source and to elements added by trusted extensions. If such references need to be explicitly allowed, set the contentaccessible flag to yes to obtain the behaviour found in older versions of Firefox.
Use the HTML tab in FireFox to know actually if the img element was added. It probably was added and the problem is with your URL.
I remember when building my FireFox extensions, that files are located through a special protocol (chrome:// I think), where you put the name of the extension and can browse through it.

How to Load Dependent Files on Demand + Check if They're Loaded or Not?

I'm trying to implement an assets/dependency loader that i've found from an old article at 24Ways.org. most of you might be familiar with it. it's from this article by Christian Heilmann:
http://24ways.org/2007/keeping-javascript-dependencies-at-bay
i've modified the script to load CSS files as well. and it's now quite close to what i want. but i still need to do some checking to see wether an asset have been completely loaded or not.
just wondering if you guys have any ideas :)
here's what my script currently looked like:
var assetLoader = {
assets: {
products: {
js: 'products.js',
css: 'products.css',
loaded: false
},
articles: {
js: 'articles.js',
css: 'articles.css',
loaded: false
},
[...]
cycle: {
js: 'jquery.cycle.min.js',
loaded: false
},
swfobject: {
js: 'jquery.swfobject.min.js',
loaded: false
}
},
add: function(asset) {
var comp = assetLoader.assets[asset];
var path = '/path/to/assets/';
if (comp && comp.loaded == false) {
if (comp.js) {
// load js
var js = document.createElement('script');
js.src = path + 'js/' + comp.js;
js.type = 'text/javascript';
js.charset = 'utf-8';
// append to document
document.getElementsByTagName('body')[0].appendChild(js);
}
if (comp.css) {
// load css
var css = document.createElement('link');
css.rel = 'stylesheet';
css.href = path + 'css/' + comp.css;
css.type = 'text/css';
css.media = 'screen, projection';
css.charset = 'utf-8';
// append to document
document.getElementsByTagName('head')[0].appendChild(css);
}
}
},
check: function(asset) {
assetLoader.assets[asset].loaded = true;
}
}
Christian explains this method in his article in great detail. I don't want to confuse you guys anymore with my bad english :P
and here's an example of how i run the script:
...
// load jquery cycle plugin
if (page=='tvc' || page=='products') {
if (!assetLoader.assets.cycle.loaded) {
assetLoader.add('cycle');
}
}
// load products page assets
if (!assetLoader.assets.products.loaded) {
assetLoader.add('products');
}
...
this kind of approach is very problematic though. coz assets loads asynchronously, which means some of the code inside products.js that depends on jquery.cycle.js might continue running before jquery.cycle.js is even loaded resulting in errors.
while i'm quite aware that scripts can be attached with an onload event, i'm just not really sure how to implement it to my script. anyone care to help me? please... :P
For js files you can use $.getScript, it provides a callback option so you can chain the loading, i.e:
$.getScript('jquery.cycle.js',function(){
$.getScript('products.js');
});
Why reinvent the wheel? Dojo has this built in with dojo.require and jQuery has the Include plugin.
As for CSS, minify and load it upfront as you normally would. This keeps things simpler and it's unlikely to be too costly load-time wise.

Categories

Resources