Create iframes from original page content with jQuery - javascript

I am trying to dynamically "rewrite" an entire page to a set of iframes. I want a music player bar at the bottom iframe and the original page "rewritten" in an iframe above/behind that. Almost just like SMC player. I feel like I'm close but I am a jQuery novice.. So any pointers will be greatly appreciated beforehand.
Here's the main part that creates the iframes that's not working correctly.
var oldpage = "<html>" + $("html").html() + "</html>";
$('body').html( "<iframe frameborder='0' id='content' allowtransparency='true' name='content'></iframe>" );
$('#content').contents().find('html').html(oldpage);
$('body').append("<iframe id='stratus' allowtransparency='true' frameborder='0' scrolling='0'>");
I'm trying to load the entire original html on line 1. Then creating iframes and trying to inject the oldbody variable into the new iframe #content. The iframes are created but the #content iframe has a blank body.

I don't know why, but you can't replace the whole HTML element, only its contents:
// create raw frame
var frame = $('<iframe id="maincontent" style="position:absolute; top: 0; left: 0; width: 50%; height: 50%;"><html></html></iframe>');
// store a copy of current document contents
var copiedHead = $('head').clone();
var copiedBody = $('body').clone();
// empty the current document
$(':not(iframe) body *').remove();
// load the copy into the frame;
// it's not possible to replace the whole HTML element;
// using plain JS DOM function here, since jQuery would strip out any SCRIPT and STYLE tags
frame.load(function(){
$(this).contents().find('html')[0].replaceChild(copiedHead[0] , $(this).contents().find('head')[0]);
$(this).contents().find('html')[0].replaceChild(copiedBody[0] , $(this).contents().find('body')[0]);
}).appendTo('body');

Related

Javascript Iframe not getting height calculated correctly

I am trying to display my iframe on any website like this one HERE but for some reason the height is not calculated correctly. I get 8px on the style tag instead of 1000+ to display correctly that block.
<iframe id="iframe" allowtransparency="true" frameborder="0" style="width:100%; border:none" scrolling="no" src="http://newskillsacademy.co.uk/affiliates/iframe.php?&products_ids[]=55072&products_ids[]=51883&products_ids[]=49321&products_ids[]=48561&products_ids[]=48398&products_ids[]=46469&products_ids[]=44080&products_ids[]=43167&products_ids[]=42427&products_ids[]=41068&columns=3&aff_id=3"></iframe>
<script>
var frame = document.getElementById('iframe');
frame.style.height = 0;
frame.style.height = frame.contentWindow.document.body.scrollHeight + 'px';
</script>
The line that sets the height (i.e. frame.style.height = frame.contentWindow.document.body.scrollHeight + 'px';) is likely run before the contents of the iframe have loaded. Thus in order to set the height properly, that code must be executed after the contents of the iframe have loaded.
One way to do this is to assign the onload property to a function containing the code to set the height property:
var frame = document.getElementById('iframe');
frame.onload = function() {
frame.style.height = frame.contentWindow.document.body.scrollHeight + 'px';
}
See this demonstrated here.
Also, the code attempts to fetch the iframe from the DOM as soon as the javascript executes. Depending on the location of the script tag/file (e.g. loaded via <head> or <body>) the DOM may not be ready. One solution to this is waiting for the DOMContentLoaded event. This can be achieved using EventTarget.addEventListener() on document.
document.addEventListener("DOMContentLoaded", function(event) {
console.log("DOM fully loaded and parsed");
});
And because you initially tagged the question with jQuery, the .ready() method provides a shortcut to this.
$(document).ready(function(event) {
console.log("DOM is safe to manipulate");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

How do I execute javascript only relative to that frame and not the whole window?

I have the following iFrame:
<div id="sandbox-inner">
<iframe sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts" frameborder="0" name="Output " id="output" src="JavaScript:''"></iframe>
</div>
And when the user clicks to run their code, it injects the javascript successfully within this iframe. However, it actually runs it across the whole window, not just the iframe. So basically if I add a class "test" to an element outside the iframe, and one inside, and then inject the following inside the head of the iframe...
$(function() {
$('.test').css({ background: "blue" });
});
It effects my element outside the iframe too, which I really dont want. I need the iFrame to be a completely seperate environment. This is how I am currently injecting the javascript:
$('#runGuestCode').on("click", function () {
var js = $('#js-input').val(),
iframe = $("#output"),
iframeHead = iframe.contents().find("head").first(),
frame = document.getElementById("output"),
scriptTag = '<script>' + js + '<\/script>';
$('#output').contents().find("head").append(scriptTag);
});
Many thanks
UPDATE #1
The javascript is taken from textarea #js-input, which is whatever the user has typed. This is then appended to the head of the iframe, but currently runs relative to the parent document, not the iframe document.
You can do it following way, it will not effect you current page elements will apply to iframe element only:-
var iframe = $('iframe');
$(element, iframe.contents()).css({'background':'blue'});
Working Fiddle
Showcase the javascript code put by user in iframe:
$('#submit1').click(function (e) {
e.preventDefault();
var myIframe = document.getElementById("resultFrame");
var s = document.createElement("script");
s.type = "text/javascript";
s.innerHTML = $("#textarea1").val();
myIframe.contentWindow.document.head.appendChild(s);
});
Working Fiddle with Javascript Output in iframe

jquery iframe a links into new div / tab / window?

I have a tricky question.
All pages are within same server / portal.
I have a page that embeds iframe from the other page using the following code:
$('#mydiv').append('<p id="loading">Loading ...</p>');
$('#mydiv').append('<iframe id="myframe" name="myframe" class="myframe" onload="myframe()" style="display:none;"></iframe>');
$('#myframe').attr('src', 'https://mywebsite.com/page2');
function myframe() {
var $myframesearch = $('#myframe').contents();
$myframesearch.find("a").attr('target','_parent');
}
$('#myframe').load(function(){
$('#loading').remove();
$('#myframe').fadeIn();
});
All of the links within iframe have no href (but href="javascript:void(0)") and uses scripts within iframe to process the action dynamically.
Some links does open in new window some does not.
I would like to force all links to either open in new Tab, Window, or append to new Div, but none of the methods work, like base / parent, onclick / new window, _top, _parent, etc.
However, my idea was to hide and wait till the content of iframe is loaded after a click and then to append loaded content in new hidden div and then fade it in. When doing so the loaded iframe content resets back to default and not with new content.
Does anyone knows how this can be solved?
Thank you all!
So I check and it appears that other JavaScript overwrites the "a" tag action with some "data" field in the tag only for the "a" tags that contain "Open:" in their link.
I found solution to the problem below by the link for this "a" tag from another page bypassing the JavaScript overwriting:
$(function(){
$('#mydiv').append('<p id="loading">Loading ...</p>');
$('#mydiv').append('<iframe id="myframe" name="myframe" class="myframe" src="https://mywebsite.com/page2" onload="myframe()" style="display:none;"></iframe>');
$('#myframe').load(function(){
$('#loading').hide();
$('#myframe').fadeIn();
});
$('<div id="popup" style="display:none; width:1px; height:1px; position:absolute; top:0; left:0;"></div>').appendTo('html');
});
function myframe() {
var $myframesearch = $('#myframe').contents();
$myframesearch.find("a").attr('target','_parent');
$myframesearch.find('a:contains("Open:")').on('click',function(){
$(this).attr('data','');
var $texta = $(this).text();
var $text = $texta.replace(/Open: /,"");
$('#popup').load('https://mywebsite.com/page2' + ' a:contains("'+$text+'")', function(){
$('#popup a').each(function(){
this.href = this.href.replace(/https:\/\/mywebsite\.com\/page2\/a/, "https://mywebsite.com/page2");
this.click();
});
});
});
}
Hope this helps :)

Insert a value in iFrame

I've got this structure and I want to change the values of the form based on the form before. Problem is, the iframe got no ID and I can't set one as it is a plugin that retrieves the data from another domain.
...<input type="button" onclick="document.getElementById('betterplace').style.display='block';
var betterplace = document.getElementById('betterplace')[0];betterplace.getElementsByTagName('iframe')[0].document.getElementById('donation_presenter_address_first_name').value=document.getElementById('_vorname').value;
" style="border:none; height: 50px; width: 250px; font-weight:bold; font-size: 14pt; background-color:#94C119;color:white;cursor: pointer;" value="Ihre Spende abschließen"/>
<div id="betterplace" style="display:none;">
<div style="width:500px;height:2px;margin-bottom:5px;background-color: #94c119"/>
<br/>
<script type="text/javascript">
...
i can't understand your problem but if you want to insert some text or html into the iframe you can do this:
var iframe = document.getElementById('your iframe id') // if the iframe is already exists
doc, div;
doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write('some text') // if you want to write to the iframe
doc.close();
div = doc.createElement('div');
// this div will appear in iframe
doc.body.appendChild(div)
Note: you can only manipulate iframe content if the iframe domain is the same as the domain of the main page
An example of dynamic creation of iframe:
var iframe = document.createElement('iframe'),
doc, div;
iframe.src = '' // same domain as main page
document.body.appendChild(iframe);
doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write('some text') // if you want to write to the iframe
doc.close();
div = doc.createElement('div');
// this div will appear in iframe
div.appendChild(doc.createTextNode('im a div inside the iframe'));
doc.body.appendChild(div);
fiddle: here
Something like this will call the frame:
parent.frames[1].doWhatEver
All frames are put into an array, the first frame of your site will be parent.frames[0], the second parent.frames[1] and so on.
Edit:
If this does not work, you can always use this method:
parent.getElementsByTagName("iframe")[0].doWhatEver
// or
parent.getElementsByTagName("frame")[0].doWhatEver
getElementsByTagName(tagName) returns an array with elements that have the tagName (e.g. <iframe>). With this you can get your frame.
If it got no ID you have to draw it DOM path just analyze the path and get it in either JavaScript or JQUERY

Dynamic iframe height not working in chrome

im going crazy here. i found a script here that was supposedly going to work on chrome as well but i just cant get it to work
here is the script in my header
<script type="text/javascript">
function resizeFrame() {
var t=document.getElementById("Footer");
var f = document.getElementById("mainContent");
var y = f.contentWindow;
t.innerHTML = y.document.body.offsetHeight;
f.height = y.document.body.offsetHeight;
}
</script>
and the iframe
<iframe onload="resizeFrame()" id="mainContent" src="swwbookpg1.php" scrolling=auto frameborder=0
height="100%" width="100%">Working!</iframe>
<p id="Footer"> Footer</p>
it works in firefox and IE but not in chrome.
if anyone can help that would be amazing!
here it is in use: https://www.whalewatchingsydney.com.au/payment_sww/
thanks =)
Google seem to be living up to their strapline "do no evil". While Chrome is capable of dynamic iframe height adjustment Google do not make it very easy. After two days of struggling with the problem and trying tons of javascript snippets which worked perfectly in every other Browser but Chrome I finally managed to get something that would work. I will share this to hopefully save other website developers the 48 hours pain I had to go through.
Inside external SetiFrameHeight.js file which can then be added to any iframe child document with html.
<script type="text/javascript" src="SetiFrameHeigh.js"></script>
setIframeHeight.js
window.onload=setIframeHeight(window.top.document.getElementById('iFrame_ID'));
//note this code only runs serverside when using Google Chrome, very helpful
function setIframeHeight(ifrm){
var doc = ifrm.contentDocument? ifrm.contentDocument:
ifrm.contentWindow.document;
var RestHeight=ifrm.style.height; //Capture original height see why below.
ifrm.style.visibility = "hidden";
ifrm.style.height = "10px"; //Necessary to work properly in some browser eg IE
var NewHeight = getDocHeight( doc ) + 10;
if (NewHeight>20){
ifrm.style.height=NewHeight + "px";
} else { //if dom returns silly height value put back old height see above.
ifrm.style.height=RestHeight + "px";
}
ifrm.style.visibility = "visible";
}
function getDocHeight(doc) {
doc = doc || document;
var body = doc.body, html = doc.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight,
html.scrollHeight, html.offsetHeight );
return height;
}
The real magic of this code snippet is the function getDocHeight which basically tries every conceivable dom combination and selects the one that gives the maximum height. I cannot take credit for this got it from http://www.christersvensson.com/html-tool/iframe.htm.
Chrome:
I found that when I create an iFrame with document.createElement and assign it a name ("myIframe"), the new iFrame does not load content when I set its location. But if I assign a url to the element's src, it worked fine. Now then, when instead I manually inserted the iframe tags in the html text (static -- as opposed to using document.createElement) it would load the document when setting its location (and also the tag's src). Strange.
Assuming you are intending to display the iframe's content directly, I wonder why? I like to use iframes but really only to dynamically load content to a container in my top window. The last part of the html loaded into the iframe includes a script that moves the output into the desired location of the top frame.
Example of a php script that loads new content via an iFrame.
// top Frame calls the php script like this:
<div id="myContainerDiv">
<p>old content - please replace me with fresh content</p>
</div>
<iframe name="hiddenFrame" style="display:none;"></iframe>
<script>
hiddenFrame.location = 'index.php?getNewContent=125';
</script>
// the following script would be at the top of index.php
<?php //
if( isset($_GET['getNewContent']) ):
echo '<div id="myIframeHtml">';
// the html that I want to load to the top frame..
echo '</div>';
?>
<script>
newContent = document.getElementById('myIframeHtml').innerHTML; // from this iFrame
topContainer = top.document.getElementById('myContainerDiv'); // in top frame
topContainer.innerHTML = newContent; // no fuss-no muss --> no encoding or parsing
</script>
<?php
exit;
endif;

Categories