From a script call a function in .js file - javascript

I have this in a test.html:
<script>
function h(){
g();
}
<script>
k.js has:
g();
In test.html I successfully entered h() but not g(). I added k.js as a script tag:
scriptTag.src="k.js"
It is not finding g() just the same.
What am I doing wrong?

You said that k.js has this:
g();
This isn't a valid function to call, it's just trying to call g(); which still isn't defined.
What k.js should have is something like this:
function g() { alert('you called g()'); }

It sounds like you are trying to add the script when the document loads or whenever an event fires. If you try to call a function immediately after the external file that contains it is added to the dom, you will get an error. The external file will not have been downloaded. There is latencey in this process. The computer cycles through the client side script faster than it can dowload the .js file. Ad a set timeout and you should see it working. I could be wrong but that is my thoughs...

Have you ensured that k.js is loaded before calling h()?
Is it successfully finding k.js and the path resolves correctly?

Make sure the function you are calling is higher up in the DOM than the line calling it.

I added k.js as a script tag [ scriptTag.src="k.js" ]
Sounds like you're writing your script tag dynamically? If so, make sure you're injecting it into the DOM then waiting for the browser to load it before you try and access anything from it. Just creating the script node won't do anything until you inject it somewhere.

Does your code look someyhing like this?
var scriptTag = document.createElement('script');
scriptTag.src = 'k.js';
Really, you ought to have this line:
scriptTag.type = 'text/javascript';
And as previously mentioned, the script has to be inserted into the DOM. These two lines should solve the problem:
var head = document.getElementsByTagName('head')[0];
head.appendChild(scriptTag);
resulting in:
var scriptTag = document.createElement('script');
scriptTag.src = 'k.js';
scriptTag.type = 'text/javascript';
var head = document.getElementsByTagName('head')[0];
head.appendChild(scriptTag);
Now why aren't you using this?
<script type="text/javascript" src="k.js" />

Related

Function from External file is not defined [JS]

Hello I have a problem with JavaScript function.
I have 3 external JS files that are included to my JS file like that:
var badgeJs = document.createElement('script');
badgeJs.type = 'text/javascript';
badgeJs.src = 'url'
document.head.appendChild(badgeJs);
So here is the problem I need to use 3 functions, but sometimes I received error
Refference error: functionName is not defined, after that I refresh the page and first function works but second one no, and every time on refresh some of functions are not defined.
I don't know what is the problem and why this happen? Any advice will be appreciate.
I don't know if this is gonna help but JS code is for a shopify-app
How I call functions
var content = 'function1(param);function2(param1, param2, param3, [10, 25]);function3(param1, param2);';
(function() { var script = document.createElement('script'); script.text = content; var body = document.querySelector('body'); body.append(script);})();
Your file inclusions run at the sime time you're trying to call your functions. As the file inclusion need time to load your files, you are calling the functions before they have been loaded.
You have to manually add your scripts to the HTML:
<script type="text/javascript" src="/to/your/file.js">
And then run your function when the DOM has been loaded:
document.addEventListener("DOMContentLoaded", function(event) {
// Your code to run since DOM is loaded and ready
});
If you can't change the HTML, then include your files dynamically and make sure to call your functions when the files are loaded.

Including dynamic script in jQuery [duplicate]

Any idea why the piece of code below does not add the script element to the DOM?
var code = "<script></script>";
$("#someElement").append(code);
The Good News is:
It's 100% working.
Just add something inside the script tag such as alert('voila!');. The right question you might want to ask perhaps, "Why didn't I see it in the DOM?".
Karl Swedberg has made a nice explanation to visitor's comment in jQuery API site. I don't want to repeat all his words, you can read directly there here (I found it hard to navigate through the comments there).
All of jQuery's insertion methods use
a domManip function internally to
clean/process elements before and
after they are inserted into the DOM.
One of the things the domManip
function does is pull out any script
elements about to be inserted and run
them through an "evalScript routine"
rather than inject them with the rest
of the DOM fragment. It inserts the
scripts separately, evaluates them,
and then removes them from the DOM.
I believe that one of the reasons jQuery
does this is to avoid "Permission
Denied" errors that can occur in
Internet Explorer when inserting
scripts under certain circumstances.
It also avoids repeatedly
inserting/evaluating the same script
(which could potentially cause
problems) if it is within a containing
element that you are inserting and
then moving around the DOM.
The next thing is, I'll summarize what's the bad news by using .append() function to add a script.
And The Bad News is..
You can't debug your code.
I'm not joking, even if you add debugger; keyword between the line you want to set as breakpoint, you'll be end up getting only the call stack of the object without seeing the breakpoint on the source code, (not to mention that this keyword only works in webkit browser, all other major browsers seems to omit this keyword).
If you fully understand what your code does, than this will be a minor drawback. But if you don't, you will end up adding a debugger; keyword all over the place just to find out what's wrong with your (or my) code. Anyway, there's an alternative, don't forget that javascript can natively manipulate HTML DOM.
Workaround.
Use javascript (not jQuery) to manipulate HTML DOM
If you don't want to lose debugging capability, than you can use javascript native HTML DOM manipulation. Consider this example:
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "path/to/your/javascript.js"; // use this for linked script
script.text = "alert('voila!');" // use this for inline script
document.body.appendChild(script);
There it is, just like the old days isn't it. And don't forget to clean things up whether in the DOM or in the memory for all object that's referenced and not needed anymore to prevent memory leaks. You can consider this code to clean things up:
document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.
The drawback from this workaround is that you may accidentally add a duplicate script, and that's bad. From here you can slightly mimic .append() function by adding an object verification before adding, and removing the script from the DOM right after it was added. Consider this example:
function AddScript(url, object){
if (object != null){
// add script
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "path/to/your/javascript.js";
document.body.appendChild(script);
// remove from the dom
document.body.removeChild(document.body.lastChild);
return true;
} else {
return false;
};
};
function DeleteObject(UnusedReferencedObjects) {
delete UnusedReferencedObjects;
}
This way, you can add script with debugging capability while safe from script duplicity. This is just a prototype, you can expand for whatever you want it to be. I have been using this approach and quite satisfied with this. Sure enough I will never use jQuery .append() to add a script.
I've seen issues where some browsers don't respect some changes when you do them directly (by which I mean creating the HTML from text like you're trying with the script tag), but when you do them with built-in commands things go better. Try this:
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );
From: JSON for jQuery
It is possible to dynamically load a JavaScript file using the jQuery function getScript
$.getScript('http://www.whatever.com/shareprice/shareprice.js', function() {
Display.sharePrice();
});
Now the external script will be called, and if it cannot be loaded it will gracefully degrade.
What do you mean "not working"?
jQuery detects that you're trying to create a SCRIPT element and will automatically run the contents of the element within the global context. Are you telling me that this doesn't work for you? -
$('#someElement').append('<script>alert("WORKING");</script>');
Edit: If you're not seeing the SCRIPT element in the DOM (in Firebug for example) after you run the command that's because jQuery, like I said, will run the code and then will delete the SCRIPT element - I believe that SCRIPT elements are always appended to the body... but anyway - placement has absolutely no bearing on code execution in this situation.
This works:
$('body').append($("<script>alert('Hi!');<\/script>")[0]);
It seems like jQuery is doing something clever with scripts so you need to append the html element rather than jQuery object.
Try this may be helpful:
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);
I want to do the same thing but to append a script tag in other frame!
var url = 'library.js';
var script = window.parent.frames[1].document.createElement('script' );
script.type = 'text/javascript';
script.src = url;
$('head',window.parent.frames[1].document).append(script);
<script>
...
...jQuery("<script></script>")...
...
</script>
The </script> within the string literal terminates the entire script, to avoid that "</scr" + "ipt>" can be used instead.
Adding the sourceURL in the script file helped as mentioned in this page:
https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/
In the script file, add a statement with sourceURL like "//# sourceURL=foo.js"
Load the script using jQuery $.getScript() and the script will be available in "sources" tab in chrome dev tools
Your script is executing , you just can't use document.write from it. Use an alert to test it and avoid using document.write. The statements of your js file with document.write will not be executed and the rest of the function will be executed.
This is what I think is the best solution. Google Analytics is injected this way.
var (function(){
var p="https:" == document.location.protocol ? "https://" : "http://";
d=document,
g=d.createElement('script'),
s=d.getElementsByTagName('script')[0];
g.type='text/javascript';
g.src=p+'url-to-your-script.js';
s.parentNode.insertBefore(g,s); })();
You don't need jQuery to create a Script DOM Element. It can be done with vanilla ES6 like so:
const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
(function(i,s,o,g,r,a,m){
a=s.createElement(o),m=s.getElementsByTagName(o)[0];
a.innerText=g;
a.onload=r;m.parentNode.insertBefore(a,m)}
)(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))
It doesn't need to be wrapped in a Promise, but doing so allows you to resolve the promise when the script loads, helping prevent race conditions for long-running scripts.
Append script to body:
$(document).ready(function() {
$("<script>", { src : "bootstrap.min.js", type : "text/javascript" }).appendTo("body");
});
Another way you can do it if you want to append code is using the document.createElement method but then using .innerHTML instead of .src.
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.innerHTML = 'alert("Hey there... you just appended this script to the body");';
$("body").append( script );
I tried this one and works fine. Just replace the < symbol with that \x3C.
// With Variable
var code = "\x3Cscript>SomeCode\x3C/script>";
$("#someElement").append(code);
or
//Without Variable
$("#someElement").append("\x3Cscript>SomeCode\x3C/script>");
You can test the code here.
Can try like this
var code = "<script></" + "script>";
$("#someElement").append(code);
The only reason you can't do "<script></script>" is because the string isn't allowed inside javascript because the DOM layer can't parse what's js and what's HTML.
I wrote an npm package that lets you take an HTML string, including script tags and append it to a container while executing the scripts
Example:
import appendHtml from 'appendhtml';
const html = '<p>Hello</p><script src="some_js_file.js"></script>';
const container = document.getElementById('some-div');
await appendHtml(html, container);
// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)
Find it here: https://www.npmjs.com/package/appendhtml
Just create an element by parsing it with jQuery.
<div id="someElement"></div>
<script>
var code = "<script>alert(123);<\/script>";
$("#someElement").append($(code));
</script>
Working example: https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz

Injected Javascript seems to run asynchronously

I'm making a bookmarklet version of a Greasemonkey extension that appends two <script> tags to the page body: the first one is a largish library, the second calls a function from that library.
Generally, it takes two or more attempts (never one, sometimes more than two) to get the script to properly fire. Running the function directly from the console after injecting the library also works. If I check my error logs, I get the message that my injected method doesn't exist yet - hence the title: despite the fact that JavaScript ought to be single threaded, somehow the second method tag is being run first, before the library is done loading.
The bookmarklet code, before minifying, looks like this:
document.body.appendChild(document.createElement('script')).src = "https://my-site-address";
var scrN = document.createElement('script');
var txtN = document.createTextNode("main.Main().main(document.location.href)");
scrN.appendChild(txtN);
document.body.appendChild(scrN);
and the generated html is simply
<script src="https://my-site-address"></script>
<script>main.Main().main(document.location.href)</script>
Use the load event of the script element to execute the function in it:
var script = document.createElement("script");
script.onload = function() { main.Main().main(document.location.href); };
script.src = "https://my-site-address";
document.body.appendChild(script);

How to insert a string into a script tag?

I have been using XMLHttpRequest to load my javascript file and insert it into the the head of my html file. I have tried:
var headNode = document.getElementsByTagName('head')[0];
var js = document.createElement("script");
js.type = "text/javascript";
js.src = this.url.replace(project.basePath,'');
headNode.appendChild(js);
This works but i have a timing problem when i do it this way, so no function can be called. I am now trying another way, where i can get the string of codes from the js file and insert it into the head, when i do it this way it clears my html and only adds the new code in.
var code= this.ajaxRequest.responseText;
script.write('<script>'+code+'</script>')
is there away to append it to the head for example (this doesn't work);
var code= this.ajaxRequest.responseText;
var headNode = document.getElementsByTagName('head')[0];
var script = document.createElement("script");
script.write('<script>'+code+'</script>')
headNode.append(script)
Thanks for the help in advance. p.s I am not using jquery.
The first approach you tried failed because XmlHttpRequest (also called an ajax request) is asynchronous.
So by the time your script gets loaded, your other scrip tags code get executed (before the script file is load).
You could fix this issue, by using event handling in javascript.
You can create a custom event called 'loaded' and dispatch it.
And in your other script tag that contains code, add an event listener for the same event.
And in the event handling or the event listener function, call the required functions that you want to execute after the script gets loaded.
Your second approach fails because document.write or document.append over-writes the document if it is used after the html page is rendered.
So using this functions after the page has displayed should be avoided.
P.S - Sorry that I could not give any demo code as I am answering this from my cell phone.
JS parser error on your < /script> in code.
try
var code= this.ajaxRequest.responseText;
script.write('<script>'+code+'</scr'+'ipt>');
Can you just eval() the response text?

External JS file can't be executed

I have a js function that should get some advertisement js code from some server and place it in specified DOM element. It looks like this:
function LoadAd(scriptContainer)
{
var js = document.createElement("script");
js.async = true;
js.src ='someAdUrl';
var sHolder = document.getElementById(scriptContainer);
if (sHolder != null) {
sHolder.appendChild(js);
}
}
the argument 'scriptContainer' is an ID of DOM element, that should contain created js element.
This external js file contains a lot of code that should provide an ad. But this code is never reached and never executed.
When I put this js src directly in html:
<script src='someAdUrl'></script>
it works fine.
I've checked, the js file is being loaded.
Any ideas?
EDIT: Here is an example of content of js file:
document.write('<!-- Some Message -->\n\n\n<img width=\"336\" height=\"110\" border=\"0\" src="someImageSource">\n\n');
And it always contains document.write
If the external JS file is being loaded, have you checked whether or not the function is actually being invoked and run?
If the function isn't self-executing and you don't explicitly call it, the code won't run.
I use this code in my case. It may help you
var js=document.createElement('script');
js.setAttribute('src','http://domain.com/js/jscpt.js');
document.body.appendChild(js);

Categories