Reference External JavaScript File in Function - javascript

Is it possible to reference a JavaScript file inside of a JavaScript function?
Therefore i am wanting to convert this:
<script type="text/javascript" src="http://crypto-js.googlecode.com/files/2.5.3-crypto-sha1-hmac.js"></script>
<script type="text/javascript">
var hmacString = Crypto.HMAC(Crypto.SHA1, "Message", "Secret Passphrase", { asString: true });
</script>
In to:
function hmac (input){
var hmacString = Crypto.HMAC(Crypto.SHA1, "Message", "KEY", { asString: true });
return hmacString;
}
I am using a tool called Cast Iron, which therefore restricts JavaScript down to only a function, but i need to call an external file, to load the needed functionality.
Is this even possible?

If I understand correctly, yes you can access functions and classes from one JS file as long as the other class was loaded before you attempt to access it.
So, if some-javascript-file.js has a function named getThings(), then you can do this:
<script type="text/javascript" src="http://cdn.example.com/js/some-javascript-file.js"></script>
<script type="text/javascript">
var things = getThings(); // getThings is a publicly accessible function in an external class.
</script>

Yes, you can load other js files with javascript. Depending on the load state where your function is executed, you may either use
document.write('<script type="text/javascript" src="http://crypto-js.googlecode.com/files/2.5.3-crypto-sha1-hmac.js"'+'><'+'/script>"');
// loads synchronouly and executes
Crypto.HMAC(...); // is available here
Watch out that document.write breaks the whole page once your DOM is loaded. You can also use:
var s = document.createElement("script");
s.type = "text/javascript";
s.src = "http://crypto-js.googlecode.com/files/2.5.3-crypto-sha1-hmac.js";
s.onload = function() {
// the file should be executed now so
Crypto.HMAC(...); // is available here
};
document.head.appendChild(s); // load asychronously
See also Load js from external site on fly

OK the screenshot kind of helps. It seems you want something from an external JS file, and to manipulate it inside this function.
So you could have one javascript file with:
var foo = 'foo'; //this is in the global scope
and then your other file has:
function hmac(key){
alert(document.foo);
}
should access what you want

Related

inline javascript function not detecting script loaded via code

This works:
<script src="some.js">
<script>
afunction(); //this function is in some.js
</script>
Then I thought to improve the page speed of the site and load some.js like this
var element = document.createElement("script");
element.src = "some.js;
document.body.appendChild(element);
and now the function doesn't exist and i get an error.
Is there a solution to this?
As others pointed out above, some of the errors you might be encountering are perhaps due to missing " and so on. Assuming that you have every syntax correct, this approach will fail because how HTML parsing happens:
Assuming that you've got this code in the <HEAD> section:
When the parser (in your browser) reads the file stream where you've got this code, it is going to construct the DOM as it is doing so. This means that when it gets to the point in your code where you are telling it to append as a child your script node element to the body, it is going to fail because document.body does not exist yet and this is an error.
Assuming that you've got this code in the <BODY> section:
Then by the mere that you have attached a SCRIPT node element to the DOM does not imply that the file has been loaded by the Javascript engine and processed the content of "some.js". Therefore, when "aFunction" is called, it is undefined.
Finally, i do not think you gain anything peformance-wise by loading your script after your document has loaded.
There are many Syntax Error in your Script
But the answer to the actuall question is window.onload
<script>
window.onload = function () {
afunction();
}
</script>
Syntax Need Correction
1) Close Script Tag :
<script src="some.js"></script>
<script>
afunction(); //this function is in some.js
</script>
2) Missing double quote(")
var element = document.createElement("script");
element.src = "some.js";
document.body.appendChild(element);
The function needs to be written globally like,
$(document).ready(function () {
});
afunction () {
}
in 'some.js' script.
and access tat function using div tag.
<div id = 'a' onClick='afunction()'>
</div>
The problem is caused by calling the function too soon after the node has been appended. All you need is a timeout.
<script type="text/javascript">
var elem = document.createElement("script");
elem.src = "scripts/test.js";
elem.type="text/javascript";
//
function runTest()
{ document.body.appendChild(elem);
setTimeout("alertThis('This is a test')",50);
}
window.onload=runTest;
</script>
The external js for this example says
function alertThis(msg) { alert(msg); }
It runs correctly in all browsers.

How to load JS scripts that will add only one additional script

I have 2 script files that you put in the <head>
However, they share the same Util script file.
I want that in case they are both loaded on the same page, the util file will load only once.
If only one of them is loaded, the util will still be loaded once...
I cant use <script src=...utils.js>... only the 2 scripts
I am using
var s = document.createElement("script");
s.src = s3 + "/js_enc/utils.js";
s.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(s);
What is the best way to achieve this?
thanks
This doesn't seem like a problem, since the Util script will only be loaded when it is declared:
<script type='text/javascript' src='util.js'></script>
<script type='text/javascript' src='script1.js'></script>
<script type='text/javascript' src='script2.js'></script>
But if you want to check that the script has been loaded, you could set a global variable in the Util script, something like
var utilFound = true;
Then check in each script to see if it is set or not.
if(!utilFound) { alert("Util not loaded!"); }
You could also toggle the variable depending on some condition, for example:
if(utilFound) {
alert("Util hasn't been accessed yet.");
utilFound = false;
}
else {
alert("Util has already been accessed.");
}
UPDATE
As per your edit, the "check if set and toggle" solution would work fine. If the variable has been set, don't run your document.createElement code.
In your util.js file, add
var utilLoaded = false;
Then in each script, add your snippet, plus a utilLoaded check/toggle:
if(!utilLoaded) {
var s = document.createElement("script");
....
utilLoaded = true;
}

How and when do browsers implement real-time changes to a document's DOM?

My website dynamically embeds an external Javascript file into the head tag. The external Javascript defines a global variable myString = "data". At what point does myString become accessible to Javascript within the website?
<html>
<head>
<script type="text/javascript">
myString = null;
external = document.createElement("script");
//externalScript.js is one line, containing the following:
//myString = "data";
external.setAttribute("src", "externalScript.js");
external.setAttribute("type", "text/javascript");
document.getElementsByTagName("head")[0].append(external);
alert(myString);
<script>
</head>
<body>
</body>
</html>
This code alerts null (when I thought it would alert "data") in Chrome and IE, even though the DOM has loaded in externalScript.js at this point. When is externalScript.js actually evaluated by the browser and at what point do I have access to the new value of myString?
You can access it when the onload event fires for that script element, like this:
external = document.createElement("script");
external.onload = function() { alert(myString); };
script.onreadystatechange= function () { //for IE, the special kid...
if (this.readyState == 'complete') alert(myString);
}
external.setAttribute("src", "externalScript.js");
external.setAttribute("type", "text/javascript");
document.getElementsByTagName("head")[0].appendChild(external);
This just attaches a function to run once that script has loaded, execute any code that depends upon the script in there. Correction to previous answer: as seanmonstar points out in comments (thanks!), you do indeed need an IE exception here again, because it's a bit "special"...

Can't access variables from dynamically loaded javascript

I'm using a fairly simple system to load javascript dynamically:
include = function (url) {
var e = document.createElement("script");
e.src = url;
e.type="text/javascript";
document.getElementsByTagName("head")[0].appendChild(e);
};
Let's say I have a file test.js which has the following contents:
var foo = 4;
Now, in my original script, I want to use
include(test.js);
console.log(foo);
However, I get a 'foo has not been defined' error on this. I'm guessing it has to do with the dynamic script being included as the last child of the <head> tag. How can I get this to work?
It is because you have to wait for the script to load. It is not synchronous like you would think. This may work for you:
include = function (url, fn) {
var e = document.createElement("script");
e.onload = fn;
e.src = url;
e.async=true;
document.getElementsByTagName("head")[0].appendChild(e);
};
include("test.js",function(){
console.log(foo);
});
That is one problem, but it also takes time for the browser to download and parse the remote JS file — and it hasn't done that before you call console.log.
You need to delay things until the script has loaded.
This is easiest done by letting a library do the heavy lifting, jQuery has a getScript method that lets you pass a callback to run when the script has loaded.

How do I pass argument to anonymous Javascript function?

I am writing a simple counter, and I would like to make installation of this counter very simple for users. One of the simplest counter code (for users who install it) I ever see was Google Analytics Code
So I would like to store main code in a file and user who will install my counter will need just to set websiteID like this:
<html><head><title></title></head><body>
<script type="text/javascript" src="http://counterhost.lan/tm.js">
var websiteId = 'XXXXX';
</script>
</body></html>
Here is my code:
<script type="text/javascript" src="http://counterhost.lan/tm.js">
var page = _gat.init('new');
</script>
and this is my JS file:
(function() {
var z = '_gat';
var aa = function init(data) { alert(data); alert(z);};
function na() {
return new z.aa();
}
na();
})();
I tried to understand Google Analytics javascript code but I failed to do this. Can anyone suggest how can I specify variable between tags and then read it in anonymous function which is located in a javascript file ?
Thanks.
In your example, websiteId is a global variable. So it is accessible everywhere including anonymous functions unless there is a local variable with the same name
<script> var websiteId = "something"; </script>
Later in the page or included js file...
(function() {
alert(websiteId); //this should work
})();
Can anyone suggest how can I specify variable between tags and then read it [...]
Not if your tag has both a SRC attribute and JS content.
<script type="text/javascript" src="http:/x.com/x.js"></script>
.. is different from,
<script type="text/javascript">
var x = 1;
</script>
One framework that optionally adds JS variables to SCRIPT tags is Dojo. So if you're using Dojo you can add variables to the global djConfig hash by writing,
<script type="text/javascript" src="mxclientsystem/dojo/dojo.js"
djConfig="
usePlainJson: true,
parseOnLoad: true
">
</script>
Dojo does this by running through the SCRIPT tags and evaluating the custom djConfig attribute.
This does not, however solve your problem.
You do really want two SCRIPT tags. One saying,
<script type="text/javascript">
var websiteId = '123456';
</script>
which will set a global variable websiteId and a second one,
<script type="text/javascript" src="http:/x.com/myreporter.js"></script>
which can load from anywhere and read out the websiteId variable and, I assume, report it back.
You can pass variables to an anonymous function like so:
(function(arg1, arg2, arg3) {
alert(arg1);
alert(arg2);
alert(arg3);
})("let's", "go", "redsox");
// will alert "let's", then "go", then "redsox" :)
I'm not entirely clear about what you're asking, but...
You can tag any HTML element with an id attribute, then use
document.getEntityById() to retrieve that specific element.
You can also give any HTML element user-defined attributes having names of your own choosing, then get and set them for that element within Javascript.
I think you've got a bit confused with how JS objects are called.
z is a String, '_gat'. You can't call aa() on it because a String has no member called aa. aa is a standalone function stored in a local variable. Even if you did call aa(), it doesn't return anything, so using the new operator on its results is meaningless. new can only be called on constructor-functions.
I guess you mean something like:
var _gat= function() {
// Private variable
//
var data= null;
// Object to put in window._gat
//
return {
// Set the private variable
//
init: function(d) {
data= d;
}
};
}();
Then calling _gat.init('foo') as in your second example would set the variable to website ID 'foo'. This works because the _gat object is the return {init: function() {...}} object defined inside the anonymous function, keeping a reference (a ‘closure’) on the hidden data variable.
If you specify a src attribute as part of a script element, any code within the script element tags themselves will not be executed. However, you can add this functionality with the following code. I got this technique from Crockford (I believe it was him), where he uses it in of his talks on the unrelated topic of rendering performance and asynchronously loading scripts into a page to that end.
JavaScript:
(function() {
// Using inner class example from bobince's answer
var _gat = (function() {
var data= null;
return {
init: function(d) {
console.info("Configuration data: ", d);
data = d;
}
}
})();
// Method 1: Extract configuration by ID (SEE FOOT NOTE)
var config = document.getElementById("my-counter-apps-unique-and-long-to-avoid-collision-id").innerHTML;
// Method 2: search all script tags for the script with the expected name
var scripts = document.getElementsByTagName("script");
for ( var i=0, l=scripts.length; i<l; ++i ) {
if ( scripts[i].src = "some-script.js" ) {
config = scripts[i].innerHTML;
break;
}
}
_gat.init( eval("(" +config+ ")") );
})();
HTML:
<script type="text/javascript" src="some-script.js" id="my-counter-apps-unique-and-long-to-avoid-collision-id">
{some: "foo", config: "bar", settings: 123}
</script>
Both methods have their draw backs:
Using a unique and non-colliding ID will make determining the proper script element more precise and faster; however, this is not valid HTML4/XHTML markup. In HTML5, you can define arbitrary attributes, so it wont be an issue at that time
This method is valid HTML markup; however, the simple comparison that I have shown can be easily broken if your url is subject to change (e.g.: http vs https) and a more robust comparison method may be in order
A note on eval
Both methods make use of eval. The typical mantra concerning this feature is that "eval is evil." However, that goes with say that using eval without knowing the dangers of eval is evil.
In this case, AFAIK, the data contained within the script tags is not subject to inject attack since the eval'ing script (the code shown) is executed as soon as that element is reached when parsing the HTML into the DOM. Scripts that may have been defined previously are unable to access the data contained within the counter's script tags as that node does not exist in the DOM tree at the point when they are executed.
It may be the case that a well timed setTimeout executed from a previously included script may be able to run at the time between the counter's script's inclusion and the time of the eval; however, this may or may not be the case, and if possible, may not be so consistently depending on CPU load, etc.
Moral of the story, if you're worried about it, include a non-eval'ing JSON parser and use that instead.

Categories