I'm currently in the process of writing a userscript for a certain website. What I'm trying to accomplish requires access to the content scope with the page variables and functions.
Standard operating procedure for that sort of thing seems to be a function that injects a new <script> tag into the DOM, like so:
function injectScript(f) {
var target = document.head || document.documentElement;
var script = document.createElement("script");
script.type = "text/javascript";
script.text = "(" + f.toString() + ")();";
target.appendChild(script);
target.removeChild(script);
}
However, this approach doesn't work because the website has a Content Security Policy which prevents the injected script tag from executing! I've also tried the location hack (basically location.href="javascript:someCode()"), but that also counts as an inline script and won't work.
unsafeWindow would be an option that is unfortunately only available with Greasemonkey. Ideally my script should work with Chrome as well. Is there a better way to access page variables?
Related
ive installed typekit on my site, the usual two lines of js just after the opening head tag but its extremely slow / unresponsive to load in the fonts, this is completly remedied by refreshing the page, after that the typekit font load in perfectly and really quickly. But from a users point of view they will never know to do that, so they will be served the default fonts.
I have the typekit js as the very first thing under the opening head tag before the metatags and before loading in jquery, jquery-ui and other scripts.
Has any one else had trouble with this ?
what seemed to work for me was to load the script in an asynchronous pattern - as specified on the typekit blog, ive copied it in bellow
Standard asynchronous pattern
This first pattern is the most basic. It’s based on patterns written about by web performance experts like Steve Souders and used in other JavaScript embed codes like Google Analytics.
<script type="text/javascript">
TypekitConfig = {
kitId: 'abc1def'
};
(function() {
var tk = document.createElement('script');
tk.src = '//use.typekit.com/' + TypekitConfig.kitId + '.js';
tk.type = 'text/javascript';
tk.async = 'true';
tk.onload = tk.onreadystatechange = function() {
var rs = this.readyState;
if (rs && rs != 'complete' && rs != 'loaded') return;
try { Typekit.load(TypekitConfig); } catch (e) {}
};
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(tk, s);
})();
</script>
This pattern uses a single inline tag to dynamically add a new script element to the page, which loads the kit without blocking further rendering. An event listener is attached that calls Typekit.load() once the script has finished loading.
How to use it:
Place this snippet at the top of the so the download starts as soon as possible.
Edit the highlighted TypekitConfig object and replace the default with your own Kit ID.
You can add JavaScript font event callbacks to the TypekitConfig object.
Advantages:
Loads the kit asynchronously (doesn’t block further page rendering while it loads).
Disadvantages:
Adds more bytes to your html page than the standard Typekit embed code.
Causes an initial FOUT in all browsers that can’t be controlled or hidden with font events.
I have a webpage that is rich in content such as graphics and javascript. Now the problem is that my page loads too slow, especially with slower internet connections. Now at the bottom of my webpage I have a jquery slider, which is the least important item on my website.
now...
Is there a way I can postpone or delay the loading of that whole slider(which has a div ID as parent element) until directly after everything else has loaded on my page, and not alongside the rest of the more important content?
Absolutely, you might want to look up javascript loader like RequireJS or LABjs.
The principle is that you inject the script-tag that loads your javascript. For instance, you could have the following code as the last element before your </body>-tag:
<script type='text/javascript'>
var head = document.getElementsByTagName("head")[0];
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = 'url/to/script.js';
head.appendChild(newScript);
</script>
I am using bookmarklet to inject a element in document with a custom JS script file. I did it like this:
var newscript = document.createElement('script');
newscript.type = 'text/javascript';
newscript.async = true;
newscript.src = 'http://www.myurl.com/my_js_script.js';
var oldscript = document.getElementsByTagName('script')[0];
oldscript.parentNode.insertBefore(newscript, oldscript);
But I can't figure out how to actually execute it. Can someone tell me how can I execute that JS file?
Note: Since this can be a Greasemonkey script as well, I am tagging this question for Greasemonkey as well.
Script tags are automatically downloaded and executed when they're added to the document. Note, however, that the script you're using may fail if the document you're injecting into doesn't already contain any <script> tags, as oldscript will be undefined.
My html page dynamically loads pages via Ajax for dynamic panels on the page. I need the script tags in the dynamically loaded pages to be executed. I fixed the code from a SO question. It works fine on FF/Safari/Chrome.
But dom nodes of type script work differently on IE. -- I can't seem to add text to a script node in IE 7:
// variable "data" holds the script element's content from an
// incoming html page loaded via ajax
var script = document.createElement("script");
script.type = "text/javascript";
script.appendChild(document.createTextNode(data)); // doesn't work on ie
// also doesn't work on IE 7:
script.innerHTML = data;
script.innerText = data;
Any ideas for getting the sw to work on IE? (Other than using eval.)
You should simple call eval(data).
Although it is true that eval should usually be avoided, this is one of the few exceptions.
EDIT: Without eval, you can do it like this:
var scriptNode = document.createElement('script');
scriptNode.type = 'text/javascript';
scriptNode.text = data;
document.head.appendChild(scriptNode);
document.head.removeChild(scriptNode); //Optional
You have a few options I can think of (other than using eval).
The script could be served from a separate path; setting the src of the script element instead of its content should work, even in IE.
The script to be executed could be attached to the onload listener of an image or other element, which can be appended to the document as you are doing with the script element.
use Function instead of eval. This will at least keep the evaluated code out of the local scope: new Function(data)();
var head =document.getElementsByTagName("head")[0];
newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.innerHTML = '$(window).load(function(){ someFooo(); }); ';
head.appendChild(newScript);
This is causing an Unknown Runtime Error in IE6. Any other way around this?
Try the text property instead:
newScript.text = '$(window).load(function(){ someFooo(); });';
This works in non-IE browsers as well. I've used this in FF2, FF3, FF3.5, Safari 4 (win), Opera 9+, Chrome 2, Chrome 3, and they all work.
According to the spec (I have to say this otherwise I feel misleading), you're supposed to use appendChild:
var script = '$(window).load(function(){ someFooo(); });';
newScript.appendChild(document.createTextNode(script));
But that fails in IE (<script> elements are not allowed to have children or some other inane IE thing). So just go with the former.
Looks like this is an issue with innerHTML being used in a readonly element. This happens too when you try to set innerHTML in tbody. According to msdn documentation:
(...) Doing this can also be a little
tricky because you cannot use
innerHTML to inject into the HEAD or
STYLE element directly. (Both of these
tags are READ ONLY.) The best way to
dynamically add styles to a page is to
wait for the document to load, and
then create the rule in a new style
sheet.
Why is it a readonly attribute? Here is an explanation.
So, you need to use a DOM approach to do this dynamic loading. Check this link to load external javascript resources and this one to inline scripts which is your case.
newScript = document.createElement('script');
newScript.type = 'text/javascript';
var head = document.getElementsByTagName("head")[0];
var src = '$(window).load(function(){ someFooo(); }); ';
newScript.text = src;
head.appendChild(newScript);