So I have a script that is loaded dynamically into the page as so:
<div>
<script>
var url = 'http://example.com/scripts/myscript.js?foo=bar';
document.write('<scr'+'ipt type=\"text/javascript\" src=\""+url+"\"></scri'+'pt>')
</script>;
</div>
I need to know, if there is a way, inside the myscript.js i am loading, to access the url to get the query string.
Thanks
When a script is running (unless you add defer or async attributes), it will always be the last element on the page so far. You can therefore take advantage of this fact:
var scripts = document.getElementsByTagName('script'),
currentScript = scripts[scripts.length-1],
myScriptURL = currentScript.getAttribute("src");
You can then process that myScriptURL variable to extract query string paramters, as demonstrated in this question.
Related
I'm using the Genius API to retrieve the lyrics for a given song and embed them within an HTML <div> tag. I'm interacting with this API using PHP, via an AJAX GET request.
In the event of a successful AJAX request, I retrieve the following HTML from my PHP:
<div id='rg_embed_link_2351532' class='rg_embed_link' data-song-id='2351532'>
Read <a href='https://genius.com/The-1975-the-sound-lyrics'>“The Sound” by The 1975</a> on Genius
</div>
<script crossorigin src='//genius.com/songs/2351532/embed.js'></script>
The script tag returned by the Genius API will embed the lyrics and lyric information when executed.
I'm attempting to import this HTML into my already existing <div>. In this case, the <script> portion will not be executed. I've tried to use an eval() within the 'success' function of my AJAX to dynamically execute this script, but I'm having no success:
$.ajax({
url: 'lyrics.php',
type: 'GET',
async: true,
success: function(success){
geniusHTML = success;
//Insert geniusHTML including script tag into div
var lyricsDiv = document.getElementById("lyricsDiv");
lyricsDiv.innerHTML = geniusHTML;
//Get the script tag from the html and use eval on it
var innerScript = lyricsDiv.getElementsByTagName('script')
eval(innerScript.outerHTML);
}
});
I've tried to eval the:
.outerHTML -- The console shows this value to be: <script crossorigin="" src="//genius.com/songs/2351532/embed.js"></script>
.innerHTML -- Attribute appears to be empty.
.src -- The console shows this value to be: http://genius.com/songs/2351532/embed.js. Theeval() function errors on this with Uncaught SyntaxError: Unexpected end of input.
I feel I am potentially doing this backward. Should I execute the script from my AJAX return before I add it to the div? (The script generates quite a few embed div tags)
EDIT
With instruction from answerer Sjoerd de Wit, I attempted to create a new script tag from the source tag's src attribute, and add it via document.head.appendChild. This did not work, providing the warning:
Failed to execute 'write' on 'Document': It isn't possible to write
into a document from an asynchronously-loaded external script unless
it is explicitly opened.
You should get the src from the script tag and dynamically create and load it in your html
var script = document.createElement("script");
var innerScript = lyricsDiv.getElementsByTagName('script')
script.src = innerScript.src;
document.head.appendChild(script);
using jQuery's .html() instead of javascript's .innerHTML() will automatically evaluate scripts inside the string
so, try to change this line
//Insert geniusHTML including script tag into div
var lyricsDiv = document.getElementById("lyricsDiv");
lyricsDiv.innerHTML = geniusHTML;
//Get the script tag from the html and use eval on it
var innerScript = lyricsDiv.getElementsByTagName('script')
eval(innerScript.outerHTML);
into
$("#lyricsDiv").html(geniusHTML);
SOLUTION
Answering my own question.
The other answers to this question are perfectly acceptable and work in most situations. However, if the external .js file contains a document.write within it, your browser will give you the following warnings:
Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.
One of the ways to get around this is to use Postscribe. Postscribe will override any instances of document.write within javascript passed to it.
In the context of my code -- which, rest assured, I will refactor to make it more efficient -- I retrieve my script tag from my div by getting the outerHTML of the element, then I pass it into postscribe.
With this use case, postscribe takes two arguments; the div to pass the script to, and the script itself. Of course -- you can pass the script inline or via a variable as I have done in the below example:
var myScript = myDiv.getElementsByTagName('script')[0].outerHTML;
postscribe('#myDiv', myScript);
Please see the postscribe documentation linked above for installation instructions and further functionality.
I have a SWF advert that needs to call the Facebook API, for which I need the following single-line reference in the host HTML page:
<script type="text/javascript" src="//connect.facebook.net/en_US/all.js"></script>
Since I am dealing with an advert, I don't have control over the host page. I understand I can inject functions into a page (there's a good reference for this here: http://www.actionscript.org/resources/articles/745/4/JavaScript-and-VBScript-Injection-in-ActionScript-3/Page1.html), but I haven't found a way to add a reference to an externally-hosted script.
Does anybody know if this can be done, and if so, how?
Just add a SCRIPT tag dynamically to the document. You can do that by running a anonymous function through ExternalInterface:
var js:Array = [
'var script = document.createElement("SCRIPT")',
'script.src = "http://connect.facebook.net/en_US/all.js"',
'var head = document.getElementsByTagName("HEAD")[0]',
'head.appendChild(script)'
];
ExternalInterface.call('(function(){' + js.join(';') + '})()');
Sometimes you see code like this.
<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
{lang:'en', parsetags:'explicit'}
</script>
I'd like to know how it's possible to parse the object literal inside this script tag from the loaded script.
var scripts = document.getElementsByTagName('script');
var thisScriptTag = scripts[scripts.length - 1];
var data = thisScriptTag.textContent || thisScriptTag.innerText;
alert(data);
If you have JSON data you'd use JSON.parse() to convert the data to a JavaScript object.
Note that the code must not be wrapped in a DOMready/onload event - it needs to run right when that <script> tag is processed.
The code to get the current script tag was taken from How may I reference the script tag that loaded the currently-executing script?
I am writing a third party javascript (my.js) that can be inserted in a HTML page using script tag. I want to achieve the following:
my.js gets loaded (which has a function myFunc(params))
myFunc() gets called with appropriate params (parameters can change)
putting my.js script in head is not an option
What is the best approach that I can use?
The problem is that you can't really pass parameters w/ just 1 script tag pointing to an external file, so you would have to get them from some element in the DOM:
The html:
<html>
<body>
<script src="my.js"></script>
<input id="params" type="hidden" value="'param1', 'param2', 'param3'" />
<div id="result"></div>
</body>
</html>
The javascript:
function myfunc() {
var doc = document,
params = doc.getElementById("params").value.split(","); // make an array of params
doc.getElementById("result").innerHTML = params.toString();
}
window.onload = myfunc;
Honestly though, this is a kludge. As mentioned before by Felix, you should probably just use 2 script tags -- One to get the external js file and one to call the function with the parameters you need.
You can pass parameters in via the query string and parse them out dynamically.
For example, your script tag becomes:
<script src="my.js?foo=bar"></script>
You can then get the value of the URL using:
var scripts = document.getElementsByTagName('script');
var url = scripts[ scripts.length - 1 ].getAttribute('src');
Because of the order JS is loaded by the browser, the last script on the page (while your script is executing during load) should always be your script.
Then you parse the query string. There are a bunch of questions on Stack Overflow dealing with that. Ex:
Parse query string in JavaScript
Lets say I have a page with this code on it on www.foo.com:
<script src="http://www.bar.com/script.js" />
Can I write code from within script.js that can check that it was served from bar.com? Obviously document.location.href would give me foo.com.
Thanks!
var scripts = document.getElementsByTagName("script");
give you a collection of all the scripts in the page
After this you can read their src property to find your target (I hope you know how the script is called)
for (var i=0, limit=scripts.lenght; i< limit; i++) {
if (scripts[i].src.substr(<calculate your offset>) == scriptName) {
// Have you found your script, extract your data
}
}
The only way to find out the location of a non-worker script is the non-standard error.fileName, which is only supported by Firefox and Opera:
var loc = (new Error).fileName;
If the script is a worker thread (which of course it isn't), then you could just use the location object.
If it's really important, you could work around it by defining a string containing the script URL in front of each script tag:
<script type="text/javascript">SCRIPT_URL = "http://www.bar.com/script.js"</script>
<script src="http://www.bar.com/script.js" />
Inside the script file you can then access the URL
alert("my URL is "+SCRIPT_URL);
Not too elegant but should work.
You could also, if you have a server-side language like PHP and don't mind sending JS files through the interpreter (Big performance caveat!), do something like this within the JS file:
<script type="text/javascript">var my_url = "<? echo $_SERVER["REQUEST_URI"]; ?>"</script>
but that should really, really be the last resort.
You can wrap your script in a condition, kind of like an adult diaper, if you insist.
if(top.location.host==='www.bar.com'){
//the whole script goes here
}
else alert('Nyah Nyah Nyah!')