how can i load <script>'s into an iframe? - javascript

I've got the logic working to append into my iframe from the parent
this works:
$('#iframe').load(function() {
$(this).contents().find('#target').append('this text has been inserted into the iframe by jquery');
});
this doesn't
$('#iframe').load(function() {
$(this).contents().find('body').append('<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>');
});
.lf
The problem is something to do with the inserted script tags not being escaped properly.
Half of the javascript is becomes visible in the html, like the first script tag has been abruptly ended.

Maybe the error is with your string, never create a string in javascript with a literal < /script> in it.
$('#iframe').load(function() {
$(this).contents().find('body').append('<scr' + 'ipt type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></scr' + 'ipt>');
});

I'm a bit surprised that isn't working [Edit: No longer surprised at all, see mtrovo's answer.]...but here's what I do, which is mostly non-jQuery per your comment below but still quite brief:
var rawframe = document.getElementById('theframe');
var framedoc = rawframe.contentDocument;
if (!framedoc && rawframe.contentWindow) {
framedoc = rawframe.contentWindow.document;
}
var script = doc.createElement('script');
script.type = "text/javascript";
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js";
framedoc.body.appendChild(script);
Off-topic: I really wouldn't give an iframe (or anything else) the ID "iframe". That just feels like it's asking for trouble (IE has namespace issues, and while I'm not aware of it confusing tag names and IDs, I wouldn't be completely shocked). I've used "theframe" above instead.

Warning: loading script in this manner would make scripts running in main window context
i.e.: if you use window from somescript.js, it would be NOT iframe's window!
$('#iframe').load(function() {
$(this).contents().find('body').append('<scr' + 'ipt type="text/javascript" src="somescript.js"></scr' + 'ipt>');
});
To be able to use iframe context inject script with this:
function insertScript(doc, target, src, callback) {
var s = doc.createElement("script");
s.type = "text/javascript";
if(callback) {
if (s.readyState){ //IE
s.onreadystatechange = function(){
if (s.readyState == "loaded" ||
s.readyState == "complete"){
s.onreadystatechange = null;
callback();
}
};
} else { //Others
s.onload = function(){
callback();
};
}
}
s.src = src;
target.appendChild(s);
}
var elFrame = document.getElementById('#iframe');
$(elFrame).load(function(){
var context = this.contentDocument;
var frameHead = context.getElementsByTagName('head').item(0);
insertScript(context, frameHead, '/js/somescript.js');
}

Related

Dynamically loaded jQuery not defined when using inline script

Situation:
jQuery is dynamically loaded together with other scripts by one file javascripts.js in the <head> section of the html file
Each html file has it's own javascript code executed on jQuery(document).ready() in the <body> section of the html file
Problem:
Error: jQuery is not defined for javascript in the <body> section
Modifying the html file is not an option (+1000 files with same problem)
Example html file:
<html>
<head>
<title>JS test</title>
<script src="javascripts.js" type="text/javascript"></script>
</head>
<body>
<input type="text" class="date">
<script>
jQuery(document).ready(function() { // Error: jQuery not defined
jQuery('.date').datepicker();
});
</script>
</body>
</html>
javascripts.js:
// Load jQuery before any other javascript file
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
console.log("state: "+state);
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('javascripts/jquery-1.8.3.min.js', function() {
var files = Array(
'javascripts/functions.js',
'javascripts/settings.js'
);
if (document.getElementsByTagName && document.createElement) {
var head = document.getElementsByTagName('head')[0];
for (i = 0; i < files.length; i++) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', files[i]);
script.async = true;
head.appendChild(script);
}
}
});
This is happening, as many in the comments have pointed out, because you are loading jQuery asynchronously. Asynchronous means the rest of the code is executed, and so your document-ready handler (DRH) line is running before jQuery is present in the environment.
Here's a really hacky way of resolving this. It involves making a temporary substitute of jQuery whose job is just to log the DRH callbacks until jQuery has arrived. When it does, we pass them in turn to jQuery.
JS:
//temporary jQuery substitute - just log incoming DRH callbacks
function jQuery(func) {
if (func) drh_callbacks.push(func);
return {ready: function(func) { drh_callbacks.push(func); }};
};
var $ = jQuery, drh_callbacks = [];
//asynchronously load jQuery
setTimeout(function() {
var scr = document.createElement('script');
scr.src = '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js';
document.head.appendChild(scr);
scr.onload = function() {
$.each(drh_callbacks, function(i, func) { $(func); });
};
}, 2000);
HTML:
jQuery(document).ready(function() { alert('jQuery has loaded!'); });
Fiddle: http://jsfiddle.net/y7aE3/
Note in this example drh_callbacks is global, which is obviously bad. Ideally hook it onto a namespace or something, e.g. mynamespace.drh_callbacks.
I believe this simple solution should do the trick. The changed line in the html changes the jquery onload function to a regular function. The jquery onload function will sometimes happen before the jquery is loaded and we can't have that. It's unreliable. We need that function not to execute on page load, but AFTER the jquery has loaded.
To that end, the three lines I've added in the javascript.js are inside the code that is executed immediately after jQuery has finished loading. They test to see if the pageLoaded function has been defined (so you don't have to put one on every page, only the ones that need it) and then execute it if it's there.
Now, because the change to the HTML is simple, you can just do a regex search and replace on those 1000 files to fix them. Tools like Sublime, Eclipse or TextPad are suited for that task.
Cheers!
Example html file:
<html>
<head>
<title>JS test</title>
<script src="javascripts.js" type="text/javascript"></script>
</head>
<body>
<input type="text" class="date">
<script>
function pageLoaded() { // changed
jQuery('.date').datepicker();
} // changed
</script>
</body>
</html>
javascripts.js:
// Load jQuery before any other javascript file
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
console.log("state: "+state);
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('javascripts/jquery-1.8.3.min.js', function() {
var files = Array(
'javascripts/functions.js',
'javascripts/settings.js'
);
if (document.getElementsByTagName && document.createElement) {
var head = document.getElementsByTagName('head')[0];
for (i = 0; i < files.length; i++) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', files[i]);
script.async = true;
head.appendChild(script);
}
}
if( typeof(pageLoaded) == "function" ){ // added
pageLoaded(); // added
} // added
});
You should try following workaround to load scripts synchronously:
function loadJS(src, callback) {
document.write('<scr'+'ipt src="'+src+'"><\/scr'+'ipt>');
callback();
}
IMPORTANT to note: this function should be called always before DOM is fully rendered.

Appending Jquery in HTML dynamically

I am new to jquery. I am trying to append Jquery in an HTML page in java. To include jquery.js file I have written following code:
scriptTag += "var script = document.createElement('script');" +
"script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'; " +
"script.type = 'text/javascript'; " +
"document.getElementsByTagName('head')[0].appendChild(script);" +
and then I appended following js+jquery code with it
"var script2 = document.createElement('script'); window.onload = function() {" +
"$(document).ready(function() {" +
"$(\"#identity\").hide();});};" +
"script2.type = 'text/javascript'; " +
"document.getElementsByTagName('head')[0].appendChild(script2);";
So basically I am trying to write this :
var script = document.createElement('script');
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
var script2 = document.createElement('script');
window.onload = function() {
$(document).ready(function() {
$("#identity").hide();
});
};
script2.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script2);
What I want to do is that I want my function after window load. Somehow, writing $(document).ready(function() { alone does'nt work. I get an error that $ is not defined (looks like jquery.js is not ready yet).
To avoid this problem I have used window.onload = function() {. But now I am getting error: $(document).ready is not a function. I am really confused here on how to write this thing. Is this the correct approach? Any help/guidance is highly appreciated.
[Edit]
Please note that the following code (without jquery) works fine:
window.onload = function() {
document.getElementById('identity').style.visibility='hidden';
};
[Edit]
Actually I am making a web proxy, where I download page and serve them with custom look and field. The pages does not contain any jquery files nor can I include or write HTML. I can only add my Js dynamically using java etc.
Here is some code that shows how to load a script file dynamically and also delay calling of $(document).ready until that file is loaded:
http://jqfaq.com/how-to-load-java-script-files-dynamically/
The code you use to load jquery.min.js file is called asycnhroniously. Probably this file has not been loaded at the moment you try to execute jquery function.
Therefore you should make sure that the file is loaded using a callback function.
In the following link you can find an example on how to this:
http://blog.logiclabz.com/javascript/dynamically-loading-javascript-file-with-callback-event-handlers.aspx
Also here is a working example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>index</title>
<script type="text/javascript">
function loadScript(sScriptSrc, callbackfunction) {
//gets document head element
var oHead = document.getElementsByTagName('head')[0];
if (oHead) {
//creates a new script tag
var oScript = document.createElement('script');
//adds src and type attribute to script tag
oScript.setAttribute('src', sScriptSrc);
oScript.setAttribute('type', 'text/javascript');
//calling a function after the js is loaded (IE)
var loadFunction = function() {
if (this.readyState == 'complete' || this.readyState == 'loaded') {
callbackfunction();
}
};
oScript.onreadystatechange = loadFunction;
//calling a function after the js is loaded (Firefox)
oScript.onload = callbackfunction;
//append the script tag to document head element
oHead.appendChild(oScript);
}
}
var SuccessCallback = function() {
$("#identity").hide();
}
window.onload = function() {
loadScript('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', SuccessCallback)
};
</script>
</head>
<body>
<span id="identity"> This text will be hidden after SuccessCallback </span>
</body>
You should use this code in your scriptTag variable and then you can use eval() function to evaluate the script in this variable. Also you can load the second javascript file in the callback function using jquery's getscript function

How to include jQuery in an external .js file?

I want to provide my clients a simple code to insert and get my plugin.
The code:
<div id='banner-lujanventas'></div>
<script src="http://lujanventas.com/plugins/banners/script.js" type="text/javascript"></script>
The problem is that my plugin only works with jQuery. How do I check if a version of jQuery is installed on my script.js file and if not include it? (I can only modify my /script.js file)
Make your own script element :
if (typeof jQuery === "undefined") {
var script = document.createElement('script');
script.src = 'http://code.jquery.com/jquery-latest.min.js';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
}
//edit
window.onload = function() {
$(function(){ alert("jQuery + DOM loaded."); });
}
You must put your real onload code in a window.onload() function, and NOT in a $(document).ready() function, because jquery.js is not necessary loaded at this time.
You can check for the jQuery variable
if (typeof jQuery === 'undefined') {
// download it
}
For downloading options, e.g. asynchronous vs. document.write, check out this article.
Something like this:
<script>!window.jQuery && document.write(unescape('%3Cscript src="http://yourdomain.com/js/jquery-1.6.2.min.js"%3E%3C/script%3E'))</script>
I dug up some old code that looks for a particular version of jQuery and loads it if it's not found plus it avoids conflicting with any existing jQuery the page already uses:
// This handles loading the correct version of jQuery without
// interfering with any other version loaded from the parent page.
(function(window, document, version, callback) {
var j, d;
var loaded = false;
if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, loaded)) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://code.jquery.com/jquery-2.1.0.min.js";
script.onload = script.onreadystatechange = function() {
if (!loaded && (!(d = this.readyState) || d == "loaded" || d == "complete")) {
callback((j = window.jQuery).noConflict(1), loaded = true);
j(script).remove();
}
};
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script);
}
})(window, document, "2.1", function($) {
$(document).ready(function() {
console.log("Using jQuery version: " + $.fn.jquery);
// Your code goes here...
});
});

Can this be simplified to load multiple scripts in order

The following works but I need to distribute it to clients that may be uncomfortable of pasting all this script into their home page. Just wondering if it can be simplified? I need to load Jquery 1.71, then the UI and then my own script and then call the function in my own script. Even minimized its rather long.
Hope some javascript guru can help. Thanks!
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
script.type = 'text/javascript';
head.appendChild(script);
if (script.onreadystatechange) script.onreadystatechange = function () {
if (script.readyState == "complete" || script.readyState == "loaded") {
script.onreadystatechange = false;
//alert("complete");
load_script();
}
} else {
script.onload = function () {
//alert("complete");
load_script();
}
}
//setup array of scripts and an index to keep track of where we are in the process
var scripts = ['script/jquery-ui-1.8.7.custom.min.js', 'script/wfo171.js'],
index = 0;
//setup a function that loads a single script
function load_script() {
//make sure the current index is still a part of the array
if (index < scripts.length) {
//get the script at the current index
$.getScript('http://mydomainn.com/script/' + scripts[index], function () {
//once the script is loaded, increase the index and attempt to load the next script
//alert('Loaded: ' + scripts[index] + "," + index);
if (index != 0) {
LoadEdge();
}
index++;
load_script();
});
}
}
function LoadEdge() {
Edge('f08430fa2a');
}
As soon as you have jQuery you can use its power:
$.when.apply($, $.map(scripts, $.getScript)).then(LoadEdge);
This relies on its deferred functionality - each URL is replaced with a getScript deferred (this will fetch the script), and these deferreds are then passed to $.when so that you can add a callback using .then to be called when all scripts have finished loaded.
Why don;t you just use an onload event to make sure everything is loaded before trying to execute?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://mydomainn.com/script/jquery-ui-1.8.7.custom.min.js"></script>
<script src="http://mydomainn.com/script/wfo171.js"></script>
<script>
$(function() { // this executes when the page is ready
Edge('f08430fa2a');
});
</script>
(check the paths on the scripts, you seem to be loading from /script/script, wasn't sure if that was correct so I removed it.

Import JavaScript file in JavaScript function [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
Include a JavaScript file in a JavaScript file
How to include a JavaScript file in another JavaScript file?
What is the best way to import a JavaScript file, for example file.js, in a JavaScript function()?
For example, what is the best way to replace the todo statement:
function doSomething() {
if (xy.doSomething == undefined) {
// TODO: load 'oldVersionPatch.js'
}
...
}
Possibly the best solution is to create script element and add it into the HTML page.
Is it better to add/append it into head, or body (what will load when)?
Is it better to use JavaScript or jQuery (what is more cross-browser compatible)?
http://api.jquery.com/jQuery.getScript/
or
(function(){
this.__defineGetter__("__FILE__", function() {
return (new Error).stack.split("\n")[2].split("#")[1].split(":").slice(0,-1).join(":");
});
})();
(function(){
this.__defineGetter__("__DIR__", function() {
return __FILE__.substring(0, __FILE__.lastIndexOf('/'));
});
})();
function include(file,charset) {
if (document.createElement && document.getElementsByTagName) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', __DIR__ + '/' + file);
if(charset){
script.setAttribute('charset', charset);
}
head.appendChild(script);
}
}
var filename = 'oldVersionPatch.js';
var js = document.createElement('script');
js.setAttribute("type","text/javascript");
js.setAttribute("src", filename);
document.getElementsByTagName("head")[0].appendChild(js);
.. should do it
Very simply, in JavaScript create a <script> element, append the src attribute with whatever the URL is and attach to the DOM. That should do it.
You have to make your code asynchronous to gain this:
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = yourJavascriptFileLocation;
script.onload = script.onreadystatechange = function() {
if (!script.readyState || script.readyState === 'complete') {
/* Your code rely on this JavaScript code */
}
};
var head = document.getElementsByTagName('head')[0];
// Don't use appendChild
head.insertBefore(script, head.firstChild);

Categories

Resources