I have a javascript that sits on my server. I want to provide my visitors with javascript code that they can place on their servers in the way that Google Analytics does it. For example:
<script type="text/javascript" src="http://www.somedomain.com/script/script.js?id=2001102"></script>
I got everything working up to the point where I need to grab the id. I'm just not sure what to use for that.
I tried both location.href and location.search, but that gives me url + param of the file where the script is embeded, not "script.js?id=XSOMEIDX"
In script.js I have the following:
function requestContent() {
var script = document.createElement("script");
script.src = "http://www.somedomain.com/script/xss_script.php?id="I WANT TO INPUT ID HERE+"&url="+location.href;
document.getElementsByTagName("head")[0].appendChild(script);
}
Any how I can take id=XSOMEIDX and put it in xss_script.php?id= ?
Thanks in advance!
You can use URL rewritting to take id=XSOMEIDX and put it in xss_script.php?id=
A mod rewrite rule doing it would look like this :
RewriteRule ^/scripts/([a-zA-Z0-0]+)/script.js$ /scripts/script.php?id=$1
This way you could simply ask the people to include yoursite.com/scripts/{id}/scripts.js
how about setting up the external script tag with a certain attribute?
<script data-my-script="my_value" type="text/javascript" src="http://www.somedomain.com/script/script.js?id=2001102"></script>
in modern browsers you can then do
var scripts = document.querySelectorAll("script[src][data-my-script]");
$.each(scripts, function(i, script) { console.log(script.src); });
and iterate over the nodeList...
NOTE: querySelectorAll is not working cross-browser
NOTE: querySelectorAll is returning an array-like object
Related
I have a static script declaration as a requirement, is it possible to have its URL dynamically constructed once browser wants to download it?
<script async src='https://my-known-host.com/script.js?param1=<dynamicValue>'
</script>
This parameter is generated on the client and let's say I want it to be just a random number.
I want to generate random on client side because server caches pages and this request should have a unique random number every time paged is loaded (even from cache)
I need to have it statically declared in order to start the download right away (even before browser parsed to the line of declaration)
Is it possible?
Yeah, a common approach is to write a script that injects the script tag. Something like this:
<script type="text/javascript">
setTimeout(function(){
var a = document.createElement("script");
var b = document.getElementsByTagName("script")[0];
// this adds some number, for example
// you can tweak it to be a random number if you want
a.src = document.location.protocol +
"my-known-host.com/script.js?param1=" +
Math.floor(new Date().getTime()/3600000);
a.async = true;
a.type = "text/javascript";
b.parentNode.insertBefore(a,b)
}, 1);
</script>
I actually took this example script from an analytics provider (crazyegg.com), but Google Analytics does a similar approach. In other words, it's a common thing.
<head>
<script>
$("head").append($("<script>", {async: true, src: "test.js?params=" + Math.random()}));
</script>
<script async src="test.js?params=0.524902342"></script> <!-- parse-able result from the script below -->
</head>
Sorry, I provided jQuery, but this or a vanilla approach should get the job done. The trick is to run JavaScript in head that would append <script src="example.js?" + random></script> to head.
After the browser runs that, it would parse your parameterized <script> at the end of the head tag.
I tested it myself and my browser made a request to test.js?params=0.3607864086033945
Hope that solves it!
EDIT:
If you don't want the script to be at the end of head, you can also do this. Very important that you let the browser parse <script id="randScript" async></script> first.
<script id="randScript" async></script>
<script>
$("#randScript").prop("src", "test.js" + Math.random()); //jQuery
document.getElementById("randScript").src = "test.js" + Math.random(); //vanilla
</script>
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(';') + '})()');
I'm trying to write a piece of javascript that integrates a webpage with an external system. Currently, what I have is a very small amount of code that dynamically inserts a script element into the page.
$(document).ready(function() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://example.com/example.php?arg1=1&arg2=2";
document.body.appendChild(script);
});
The JS returned by the external system is a large one-line document.write call which writes a table to the page.
document.write('<table><tr><td>blah</td></tr></table>');
When I inject this script element into the page, I can see it using a DOM inspector, but the script does not appear to execute. If I put the script element into the HTML manually, the javascript executes just fine (so it's not a same origin policy or malformed html error...), but I'd like it to be dynamic.
Any ideas why the javascript isn't executing?
Using document.write after the DOM is ready will replace the contents of the page with whatever it is you're writing.
I suggest using one of the actual DOM manipulation methods if you want to insert anything into a page.
As far as the script not executing, are you positive it's being attached correctly? Have you tried setting a javascript breakpoint on the included script to verify that this is the case?
Try to use this code (it the same use by google for analytics or facebook).
Put it on the bottom of your page ;)
<script type="text/javascript">
(function() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = '/example.php?arg1=1&arg2=2';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(script, s);
})();
</script>
OR as davidbuzatto suggest, you have to use $.getScript() which is a shorthand $.ajax() function.
$(document).ready(function() {
$.getScript("/example.php?arg1=1&arg2=2", function(data, textStatus, jqxhr) {
console.log(data); //data returned
console.log(textStatus); //success
console.log(jqxhr.status); //200
console.log('Load was performed.');
});
});
Edit :
Seens you have probably a cross-domain restriction, just try to use relative url "/example.php?arg1=1&arg2=2" instead of the full url for the include.
Or if it's not the same web server, use a cross-domain.xml file.
Because you are just including it, not executing. As you are using jQuery, take a look in the $.getScript() function.
http://api.jquery.com/jQuery.getScript/
It will fit your needs. This function is an Ajax function, so take care, because its behavior is asynchronous. Use its callbacks to execute code that is based in the loaded script.
Edit: Felix corrected me about the script execution, but I still think that you may give the function a try.
i think you need to use JSONP to achieve that and using a call back function to append it to body tag
$(document).ready(function() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://example.com/example.php?arg1=1&arg2=2&callback=showit(data)";
document.body.appendChild(script);
});
function showit(data){document.write(data);}
I've always seen this done more like:
document.write('<scr' + 'ipt>---scripthere---' + '</scr' + 'ipt>');
I'm assuming it is for similar reasons. Try that instead of creating a "real" script element.
Why not just stick the JS in a separate window/iframe where it executes and displays the tables correctly, and then pull that table using AJAX to that page?
JQuery AJAX is the easiest to use IMO:
http://api.jquery.com/jQuery.ajax/
The following are the first lines of code in a <script> tag just above the closing body tag in my document (it specifies that a locally-served copy of jQuery is run in the event that Google's CDN fails):
if(!window.jQuery){
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '/js/jquery.js';
var scriptHook = document.getElementsByTagName('script')[0];
scriptHook.parentNode.insertBefore(script, scriptHook);
}
jQuery(document).ready(function($){
// page behaviors
});
It does execute successfully, in the sense that if my computer is not connected to the Internet (this is a locally-served page), the local copy of jQuery is inserted. However, the document.ready() section below does not execute. I'm guessing this is because it is invoked before the fallback copy of jQuery takes effect. What's the proper practice for somehow "delaying" its execution so that either copy of jQuery will work properly?
Consider using an existing script loader such as yepnope. There's an example of exactly what you're trying to do on the home page.
You need to be sure that the script you are appending to the dom has finished loading before calling jQuery. You can do this with the technique described here:
if(!window.jQuery){
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '/js/jquery.js';
script.onreadystatechange= function () {
if (this.readyState == 'complete') jQueryLoaded();
}
script.onload = jQueryLoaded;
var scriptHook = document.getElementsByTagName('script')[0];
scriptHook.parentNode.insertBefore(script, scriptHook);
}
function jQueryLoaded() { };
You can also fetch the jQuery contents as an Ajax request, create a script tag with those as the body of the script and append it. That would also work.
Try that
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.2.min.js"><\/script>')</script>
<script>
jQuery(document).ready(function($){
// page behaviors
});
</script>
This way the script tag will be loaded synchronously.
The question "of how do I cope with my CDN failing and load a file hosted on my server" seems to come up a few times lately.
Question I'd ask is whether adding yet more js is the way to achieve the resilience and what level of resilience do the js approaches really add e.g. if the CDN is down they'll be a quick failure but how well do these approaches if the CDN is slow to respond how well do these solutions cope?
An alternative way to approach this is treat it as an infrastructure problem...
Run a CDN based on a domain/sub-domain you own. Have automated monitoring on it's availability, when it fails switch the DNS over to a backup server (anycast may provide an alternative solution too)
A php solution would be something like this:
$google_jquery = 'https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js';
$fp = #fsockopen($google_jquery, 'r');
if (!$fp)
{
echo '<script type="text/javascript" src="js/jquery.js"></script>';
}
else
{
echo '<script src="'.$google_jquery.'"></script>' }
}
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!')