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

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

Related

Cookiebot Cookie Consent Script

I am adding ZohosalesIQ to the CookieBot Prior Consent widget on w WP install.
This script given by zoho is
<script type="text/javascript" data-cookieconsent="statistics">
var $zoho = [];
var $zoho = $zoho || {};
$zoho.salesiq = $zoho.salesiq || {
widgetcode: "1c636a8a8d8e3410b7e579760898b7768f3cb213adb21970788a3891735df801800b6e4a1385c37b0f792b9ee54ce",
values: {},
ready: function() {}
};
var d = document;
s = d.createElement("script");
s.type = "text/javascript";
s.id = "zsiqscript";
s.defer = true;
s.src = "https://salesiq.zoho.eu/widget";
t = d.getElementsByTagName("script")[0];
t.parentNode.insertBefore(s, t);
d.write("<div id='zsiqwidget'></div>");
</script>
I am supposed to be adding <script type="text/plain" data-cookieconsent="statistics">
to the script tag to enable prior consent on cookies created by this script however, when I add this it breaks and fails to load.
Console is empty but the page renders as a white page after pre-load. When I add the code with the jaavscript type tag, it works fine.
I've tried popping itto a call back function but no joy :(
Any pointers would be great.
If the script tag is using the deprecated JavaScript function “document.write” it might cause the problem you have described above because using this function the script is loaded synchronously and it will then clear the window content (generates blank page).
To prevent this issue please make sure that the script is loaded asynchronously since the Cookiebot triggers all scripts asynchronously (i.e. to wait for the visitor’s consent) in order to work properly.
You need rewrite it to use a different approach e.g. “document.write = function(node) {document.body.insertAdjacentHTML(‘beforeend’, node);}”

how to know if the javascript, which has been loaded by a javascript, has been loaded [duplicate]

This question already has answers here:
'onload' handler for 'script' tag in internet explorer
(2 answers)
Closed 7 years ago.
I know my subject is quite tricky but i dont know how to much more ellaborate it on the subject alone.
so here how it goes.
i have a button
Load IT!
on the script tag:
function loadTheFile() {
var script = $("<script><\/script>");
script.attr("type", "text/javascript");
script.attr('src','http://www.thisismyexternalloadingjsfile"');
$('body').append(script);
alert("done! the file has been loaded");
}
the script well, when loaded will automatically have a modal box.
but the problem is, my alert seems to fire first than what is one the script
so how will i know if i have finished to load the script?
update for the first attempt to answer:
function loadTheFile() {
var script = $("<script><\/script>");
script.attr("type", "text/javascript");
script.attr('src','http://www.thisismyexternalloadingjsfile"');
$('body').append(script);
$(document).ready(function() {
alert("done! the file has been loaded")};
}
same problem
alert does indeed run before the script has been loaded. All that appending the script tag to the page does is append the script tag to the page. Then the browser has to download the script and, once received, run it. That will be after your loadTheFile function has exited.
So you need to get a callback when the script has actually be loaded and run. This is more standard than it used to be, but still has some cross-browser hassles. Fortunately for you, jQuery's already solved this problem for you (since you're using jQuery already):
function loadTheFile() {
$.getScript('http://www.thisismyexternalloadingjsfile"')
.then(function() {
alert("done! the file has been loaded");
});
}
Re your comment:
but my script file has data-* attributes
Assuming you're talking about data-* attributes on the script tag, then you'll have to do a bit more work, but it's still fairly straightfoward:
function loadTheFile() {
var load = $.Deferred();
var script = document.createElement('script');
script.src = 'http://www.thisismyexternalloadingjsfile"';
// No need for `type`, JavaScript is the default
script.setAttribute("data-foo", "bar");
script.onreadystatechange = function() {
if (script.readyState === "loaded") {
load.resolve();
}
};
script.onload = function() {
load.resolve();
};
load.then(function() {
alert("done! the file has been loaded");
});
document.body.appendChild(script); ;// Or wherever you want to put it
}
The onreadystatechange bit is to handle older versions of IE.
Rather than forge the script with text and jQuery, just use native Javascript:
var s = document.createElement('script');
s.onload = scriptLoaded;
s.src = '/path/to/my.js';
document.body.appendChild(s);
function scriptLoaded() {
console.log('Script is loaded');
}
Try something along these lines:
Your main page:
function whenScriptIsReady(){
alert('This function is called when the other script is loaded in!')
}
function loadTheFile() {
var script = $("<script><\/script>");
script.attr("type", "text/javascript");
script.attr('src','myotherjs.js');
$('body').append(script);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Load IT!
myotherjs.js:
alert('This will automatically run when the JS is loaded in!');
whenScriptIsReady();
JavaScript is executed asynchronously, so you alert will be executed before the browser can load the new script. If you want to execute logic after the script has been loaded, you could add an event listener to your script that will call the function 'loadFunc` once the script load is completed:
var loadFunc = function() {
alert("External Javascript File has been loaded");
};
//Other browsers trigger this one
if (script.addEventListener)
script.addEventListener('load', loadFunc, false);

Injecting jQuery to webpage from Safari extension

I just want to inject jQuery into a webpage from a safari extension. But only to some pages because adding jQuery as a start-/endscript would inject it to all pages and this makes browsing slow.
I tried it by creating a script tag using its onload function:
var node = document.createElement('script');
node.onload = function(){
initjquerycheck(function($) {
dosomethingusingjQuery($);
});
};
node.async = "async";
node.type = "text/javascript";
node.src = "https://code.jquery.com/jquery-2.0.3.min.js";
document.getElementsByTagName('head')[0].appendChild(node);
to check if jquery is loaded i use:
initjquerycheck: function(callback) {
if(typeof(jQuery) != 'undefined'){
callback(jQuery);
}else {
window.setTimeout(function() { initjquerycheck(callback); }, 100);
}
}
But typeof(jQuery) remains undefined. (checked that using console.log()).
Only if I call console.log(typeof(jQuery)) from the debugging console it returns 'function'. Any ideas how to fix that? Thanks in advance!
Extension injected scripts cannot access the web page's JavaScript namespace. Your injected script creates a <script> element and adds it to the page's DOM, but then the jQuery object instantiated by the script belongs to the page's namespace, not to your injected script's.
There are at least two potential solutions. One, inject jQuery into the page the normal way, using the extension API. This method is only viable if the web pages that you are targeting can be categorized using URL patterns.
Two, use Window.postMessage to communicate between your injected script and the web page's namespace. You will need to add another <script> to the page, and in this script, have a listener for the message event. The listener will be able to use jQuery as if it were "native" to the page itself.
Here's some code to get you started, if needed.
In the extension injected script:
var s0 = document.createElement('script');
s0.type = 'text/javascript';
s0.src = 'https://code.jquery.com/jquery-2.0.3.min.js';
document.head.appendChild(s0);
var s1 = document.createElement('script');
s1.type = 'text/javascript';
s1.src = safari.extension.baseURI + 'bridge.js';
document.head.appendChild(s1);
window.addEventListener('message', function (e) {
if (e.origin != window.location.origin)
return;
console.log(e.data);
}, false);
window.postMessage('What jQuery version?', window.location.origin);
In bridge.js:
window.addEventListener('message', function (e) {
if (e.origin != window.location.origin)
return;
if (e.data == 'What jQuery version?') {
e.source.postMessage('Version ' + $.fn.jquery, window.location.origin);
}
}, false);

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
}
});

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

Categories

Resources