jquery to run in iframe when created on the fly - javascript

I am trying to first create an iframe and then inject into it jQuery library and then have an alert to say that jQuery has loaded.
The jQuery library is being inserted into the iframe head as expected and the alert on jQuery load into the body.
The problem is, it does not show the alert and instead says jQuery is not defined.
Can anyone suggest anything?
Here is the code
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<title>iFrame Test</title>
</head>
<body>
<script>
var insertScript = function(src){
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = false;
script.src = src;
$('iframe').contents().find('head')[0].appendChild(script);
}
var insertScriptContent = function(code){
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = false;
script.innerHTML = code;
$('iframe').contents().find('body')[0].appendChild(script);
}
$(function(){
$('iframe').load(function(){
var contents = $('iframe').contents();
insertScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
insertScriptContent('jQuery(function(){ alert("loaded"); });');
});
});
</script>
<div class="output">
<iframe></iframe>
</div>
</body>
</html>

You're loading jQuery asynchronously (despite the script.async=false) and then loading your alert script immediately after that. jQuery is not yet loaded when that script runs, so you get the undefined jQuery reference.
As a quick fix, I added a setInterval() that waits until jQuery is defined. I also made these other changes:
Removed the script.async = false; both places because it doesn't do any good.
Removed the $('iframe').load() wrapper. When I tested your code, the callback function in that wrapper never gets called at all. That's not surprising since nothing is being loaded into the iframe at that point.
Changed the two places where you use document.createElement() to use the iframe document (called iframedoc in my version) instead. It works OK using document, but I'm a bit more comfortable creating those scripts under the document they will be loaded into.
Changed two instances of ...find(something)[0].appendChild(); to the simpler ...find(something).append();.
Here's the working code:
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>
<title>iFrame Test</title>
</head>
<body>
<script type="text/javascript">
$(function() {
var $contents = $('iframe').contents();
var iframedoc = $contents[0];
var insertScript = function(src) {
var script = iframedoc.createElement('script');
script.type = 'text/javascript';
script.src = src;
$('iframe').contents().find('head').append(script);
}
var insertScriptContent = function(code) {
var script = iframedoc.createElement('script');
script.type = 'text/javascript';
script.innerHTML = code;
$('iframe').contents().find('body').append(script);
}
insertScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
insertScriptContent(
'var timer = setInterval( function() {' +
'if( typeof jQuery == "undefined" ) return;' +
'clearInterval( timer );' +
'jQuery(function(){ alert("loaded"); });' +
'}, 50 )'
);
});
</script>
<div class="output">
<iframe></iframe>
</div>
</body>
</html>
That was good for a first pass, but there's a simpler way to do it. I tried replacing the two script functions with jQuery code, so here is another working version:
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>
<title>iFrame Test</title>
</head>
<body>
<script type="text/javascript">
$(function() {
var $contents = $('iframe').contents();
$contents.find('head').append(
'<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"><\/script>'
);
$contents.find('body').append(
'<script>' +
'jQuery(function(){ alert("loaded"); });' +
'<\/script>'
);
});
</script>
<div class="output">
<iframe></iframe>
</div>
</body>
</html>
Oddly enough, this one works OK without the setInterval() timer, so I took that code out. I'm not sure exactly why this works - which is not a comforting feeling - but it does seem to be consistent in the browsers I tested it in.
And finally, here is a non-working experiment. In the past I've used document.write() targeting an iframe to good effect. So I thought I would try that:
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>
<title>iFrame Test</title>
</head>
<body>
<script type="text/javascript">
$(function() {
var $contents = $('iframe').contents();
var iframedoc = $contents[0];
iframedoc.write(
'<!doctype html>',
'<html>',
'<head>',
'<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js"><\/script>',
'</head>',
'<body>',
'<script>',
'debugger;',
'jQuery( function(){ alert("loaded"); } );',
'<\/script>',
'</body>',
'</html>'
);
});
</script>
<div class="output">
<iframe></iframe>
</div>
</body>
</html>
This version does load jQuery and the inline script into the iframe, and it executes the jQuery() call in the inline script. But it never calls the callback function with the alert() in it. This actually relates to something I'm working on, so I'll probably take another look at it tomorrow, but in the meantime I left the experimental code in case you're curious. I changed it to use the uncompressed jQuery inside the iframe for easy debugging, and left a debugger; statement in there.

Related

Unable to display JavaScript widget

I'm trying to add a JustGiving widget to my website but it doesn't display at all. I had other scripts in the file which I thought might be interfering so I ended up testing in a new plain html file and it still wouldn't work.
Interestingly enough if I copy/paste it into a W3 schools code editor it works! It's the same exact code and I cannot work out why it doesn't load in an html file.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="jg-charity-events-board" data-config="id=45107">123</div>
<script>
(function(d) {
var jg = d.createElement('script');
jg.type = 'text/javascript';
jg.async = true;
jg.src = (d.location.protocol == 'https:' ? 'https://widgets.justgiving.com/charity-events-board/host.js' : 'http://widgets.justgiving.com/charity-events-board/host.js');
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(jg, s);
})(document);
</script>
</body>
</html>
Why do you just not use something like this? Didn't test but I assume it works.
<div id="scripts"></div>
<script>
var url = document.location.protocol + '//widgets.justgiving.com/charity-events-board/host.js';
var script = '<script type="text/javascript" src="${url}"></script>';
document.getElementById("scripts").innerHTML = script;
</script>
And jQuery has html and append functions for this.

Preload polyfills before executing main code

I'm trying to load some polyfills only if the user needs them but I can't get the scripts to download and be executed in order causing errors.
Dependencies have the asynchronous attribute and the main code has the defer attribute although is located at the end of the body tag so much of the parsing is already done.
Is there any simple way of doing this without using a preloader?
<html>
<head>
</head>
<body>
<script>
// Google Analytics
</script>
<script>
var firstScript = document.getElementsByTagName('script')[0];
if (!self.fetch) {
var fetchScript = document.createElement('script');
fetchScript.src = '/js/fetch.min.js';
fetchScript.async = 1;
firstScript.parentNode.insertBefore(fetchScript , firstScript);
}
if (!self.URLSearchParams) {
var urlspScript = document.createElement('script');
urlspScript.src = '/js/url-search-params.min.js';
urlspScript.async = 1;
firstScript.parentNode.insertBefore(urlspScript , firstScript);
}
</script>
<script defer src="/js/main.min.js"></script>
</body>
</html>

How use a script DOM element?

How do I change the script tag with a script DOM? Previously I used a script like this
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
But I want to use the script DOM. when I change like this, script not working
<script>
var jquerymin = document.createElement('script');
jquerymin.type = 'text/javascript';
jquerymin.async = true;
jquerymin.src = 'https://code.jquery.com/jquery-2.2.2.min.js';
document.getElementsByTagName('head')[0].appendChild(jquerymin);
var jqueryui = document.createElement('script');
jqueryui.type = 'text/javascript';
jqueryui.async = true;
jqueryui.src = 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js';
document.getElementsByTagName('head')[0].appendChild(jqueryui);
</script>
Is DOM script, cant run script jquery.min and jquery.ui?
If you want to use pure Javascript to add (asynchronously) a new script file, you can do this:
<html>
<head>
<title>JS</title>
</head>
<body>
<script type="text/javascript">
var
scriptElement,
script;
scriptElement = document.createElement('script');
scriptElement.src = "https://code.jquery.com/jquery-2.2.2.min.js";
script = document.getElementsByTagName('script')[0];
script.parentNode.insertBefore(scriptElement, script);
</script>
</body>
</html>

JavaScript src onload

Ok, I have this code:
<script language="javascript">
window.onload = function(){
var s = document.createElement('script');
s.src = 'jscript.js';
document.getElementsByTagName('body')[0].appendChild(s);
} </script>
<script type="text/javascript" src="https://www.facebook.com/dragosgaftoneanu"
onload = "alert('logged in')"
onerror="alert('not logged in)">
</script>
I want to execute the code from the first script at the onload of the second script. I have jscript.js where it is defined function().
as what i understand, do you want to call the first js file using the second js file?
here is the code
in your file2.html you need to add the src of the first file
<script language="javascript" src='location'></script>
<script language="javascript">
function init()
{
name();//call the function name. It's either in this file or in your first file
}
</script>
<body onload="init()">

Load and execute conditionally an external js file

I'd like to load and execute an external javascript file (Google Adwords's conversion script) only if a condition is met. Similar questions have already been asked, I've tried their solutions but it didn't work. I've the following code :
<script>
$(function() {
if ([condition]) {
$.getScript('//www.googleadservices.com/pagead/conversion.js');
}
});
</script>
The script is loaded but isn't executed. How do I do to execute it ?
I've tried to change getScript() with
var script = document.createElement("script" );
script.setAttribute("src", "//www.googleadservices.com/pagead/conversion.js" );
document.getElementsByTagName("head" )[0].appendChild(script);
but it didn't work as well.
Thanks !
#VLAS: Oops pasted the wrong thing, corrected
#ejay_francisco: I already tried to create the script tag and append it to the head but it doesn't work
#Barar: I mean the page downloads the script file but doesn't execute it. Yes, if you want the full code :
<!-- Google Code for Formulaire Contact Conversion Page -->
<script type="text/javascript">
/* <![CDATA[ */
var google_conversion_id = [...];
var google_conversion_language = "en";
var google_conversion_format = "3";
var google_conversion_color = "ffffff";
var google_conversion_label = "[...]";
var google_remarketing_only = false;
/* ]]> */
</script>
<!-- <script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js"></script> -->
<script type="text/javascript" src="//code.jquery.com/jquery.min.js"></script>
<script>
$(function() {
if ([condition]) {
$.getScript('//www.googleadservices.com/pagead/conversion.js');
$("#google_conversion").attr('src','//www.googleadservices.com/pagead/conversion/[...]/?label=[...];guid=ON&script=0');
}
});
</script>
<div style="display:inline;">
<img id="google_conversion" height="1" width="1" style="border-style:none;" alt="" src="#"/>
</div>
In the long run you'd be better off using the proper asynchronous version of the adwords conversion script I think as it has been built specifically to handle these sorts of things. This way avoids any encoding mistakes and is easier to read and maintain.
So, based on this here is what I reckon you'd want (although I am no jQuery expert - I prefer to use standard javascript but hey each to their own):
<head>
<!-- Add the async conversion script as usual - use async if you want --->
<script type="text/javascript" src="http://www.googleadservices.com/pagead/conversion_async.js" charset="utf-8"></script>
</head>
<!-- the rest of your site HTML and code -->
<script>
$(function() {
if ([condition]) {
window.google_trackConversion({
google_conversion_id: "[...]",
google_conversion_language: "en",
google_conversion_format: "3",
google_conversion_color: "ffffff",
google_conversion_label: "[...]",
google_conversion_value: 0,
google_remarketing_only: false
});
}
});
</script>
Try This:
<script type="text/javascript">
$(document).ready(function(){
if ([condition]) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://www.googleadservices.com/pagead/conversion.js";
document.getElementsByTagName("head")[0].appendChild(script);
}
});
</script>
Try this:
$(function() {
if ([condition]) {
$.getScript('//www.googleadservices.com/pagead/conversion.js', function() {
$("#google_conversion").attr('src','//www.googleadservices.com/pagead/conversion/[...]/?label=[...];guid=ON&script=0');
});
}
});
This doesn't set the src of #google_conversion until after the conversion.js script is loaded. If there's a dependency, you need to do them in the right order. You were doing this first, because $.getScript is asynchronous.

Categories

Resources