I'm writing a code which fills dynamically an iframe content. The sample below relies on the document object of the iframe:
function createIFrame() {
var iframe = document.createElement("iframe");
iframe.onload = function() {fillIFrame(iframe);};
}
function fillIFrame(iframe) {
// Creating an "header" element with the embedded Document object.
var ifdocument = iframe.contentDocument;
var header = ifdocument.createElement("header");
header.appendChild(ifdocument.createTextNode("Header."));
ifdocument.body.appendChild(header);
}
If I rewrite the iframe filling this way, using the parent document object:
function fillIFrame(iframe) {
// Using the parent Document object
var header = document.createElement("header");
header.appendChild(document.createTextNode("Header."));
iframe.contentDocument.body.appendChild(header);
}
It still works. Is there any relevant difference between these two approaches?
Related
Today I did a my text editor in iframe. I know that values from iframe doesn't send to database. My first idea relies on sending the values from iframe to the div, and that div data send to DataBase with the respective text formats.
function wlaczTrybEdycji(){
edytorTextowy.document.designMode = "On";
}
function execCmd(command){
edytorTextowy.document.execCommand(command, false, null);
}
function przeniesDane(){
var ramka = document.getElementById("ramka");
var dodiv = document.getElementById("daneIframe");
dodiv == ramka;
}
.textarea2{
width: 700px;
float: left;
height: 240px;
border: 2px solid black;
clear: both;
padding: 5px;
}
<body onload="wlaczTrybEdycji();">
<form action="" method="post">
<div class="EdytorTextowy">
<div class="przyciskiTextEdytor">
<button onclick="execCmd('bold');">BOLD</button>
</div>
<iframe name="edytorTextowy" class="textarea2" id="ramka"></iframe>
<div id="daneIframe">
</div>
<button type="submit" name="wyslijText">WYSLIJ</button><!-- here send from "daneIframe" to DB (PHP)-->
</div>
</form>
</body>
One important thing to understand about what you're doing is that the browser has rules about Cross-document communication.
A page inside an iframe is not allowed to access or modify the DOM of its parent and vice-versa unless both have the same origin. So putting it in a different way: document or script loaded from one origin is prevented from getting or setting properties of a document from another origin.
Here's the docs on Same-Origin Policy from MDN.
If the iframe and the page that loads it are of the same origin you should be able to do exactly what you're trying to do just fine. If not, then these documents need to be made available in the same origin to do so.
Hmm I understand now! You can get elements with ajax or javascript like so :
JavaScript for the Example
The JavaScript displayed here is just an example to show how to access to iframe elements.
// attach handlers once iframe is loaded
document.getElementById('ifrm').onload = function() {
// get reference to form to attach button onclick handlers
var form = document.getElementById('demoForm');
// set height of iframe and display value
form.elements.button1.onclick = function() {
var ifrm = document.getElementById('ifrm');
var ht = ifrm.style.height = '160px';
this.form.elements.display.value = 'The iframe\'s height is: ' + ht;
}
// increment and display counter variable contained in iframed document
form.elements['button2'].onclick = function() {
// get reference to iframe window
var win = document.getElementById('ifrm').contentWindow;
var counter = ++win.counter; // increment
this.form.elements['display'].value = 'counter in iframe is: ' + counter;
}
// reference form element in iframed document
form.elements.button3.onclick = function() {
var re = /[^-a-zA-Z!,'?\s]/g; // to filter out unwanted characters
var ifrm = document.getElementById('ifrm');
// reference to document in iframe
var doc = ifrm.contentDocument? ifrm.contentDocument: ifrm.contentWindow.document;
// get reference to greeting text box in iframed document
var fld = doc.forms['iframeDemoForm'].elements['greeting'];
var val = fld.value.replace(re, '');
// display value in text box
this.form.elements.display.value = 'The greeting is: ' + val;
}
form.elements.button4.onclick = function() {
// get reference to iframe window
var win = document.getElementById('ifrm').contentWindow;
win.clearGreeting(); // call function in iframed document
}
}
Or you can do something like this in jquery :
var content=$("iframe").contents().find('body').html();
//alert elements in iframe or show elements as a response in and div
alert(content);
Objective: Copy a chunk of HTML and send it to a website on another domain.
My problem: The website I'm working on and the website in the iframe are on different domains. I own both of them and have set the Access-Control-Allow-Origin to allow the websites to communicate to each other. However, I can't seem to pass the HTML chunk to the parent window.
I've tried parent.window.postMessage(chunk, http://www.parent-page.com) (chunk is the chunk of HTML code) but I get this error:
Uncaught DataCloneError: Failed to execute 'postMessage' on 'Window': An object could not be cloned.
I have also tried to use ajax to send a PUT request to the parent window but, I get a 404 error that it cannot find the parent window. *I am running the parent window from my local server.
My Question: Can anyone tell me the best way to send an object, containing HTML code, from an iframe to the parent window given that the two websites are NOT on the same domain?
EDIT: I removed the stuff about a skeleton object as that was out of the scope of the question I was really trying to ask.
Here is what I wrote to solve this. Any constructive criticism is welcome.
Code on parent window's website:
//send a message to the website in the iframe
$("#frame").on("load", function (event) {
var viewContainer = $('#element-highlight');
var iframe = document.querySelector('iframe');
var receiver = iframe.contentWindow;
var location = 'http://www.child-website.com';
event.preventDefault();
receiver.postMessage("sendStructure",location);
});
//listen for a response
window.addEventListener('message', function(event) { //event = onmessage event object
if (~event.origin.indexOf('http://ccook.oegllc.com')) { //indexOf returns a -1 if the searchValue is not found
var structure = event.data;
var container = document.getElementById("element-highlight");
container.innerHTML = structure;
}
}
<script src="../jquery/3.0.0/jquery.min.js"></script>
<body>
<div id="frame-container">
<iframe id="frame" src="http://www.main-site.com" frameborder="0"></iframe>
<div id="element-highlight">
<!-- Store Skeleton Copies here -->
</div>
</div>
</body>
Code on the website that is shown in the iframe:
I can't get the case statement below to look any better.
//listen for command from main-site.com
window.addEventListener('message', function(event) { //event = onmessage event object
if (~event.origin.indexOf('http://www.main-site.com')) { //indexOf returns a -1 if the searchValue is not found
switch(event.data){
case "sendStructure":
var structure = getStructure(),
tempNode = document.createElement("div");
structure.appendTo(tempNode); //appends structure to html document
var str = tempNode.innerHTML; //creates a serilized version of the structure
parent.window.postMessage(str, event.origin); //send structure string to main-site.com
break;
//I reccomend using a case statement if the two sites will be sending more than one message to each other
default:
sendError();
}
}
});
function getStructure(){
//this method creates a skeleton of the course page you are on
//returns a skeleton object
console.log("compiling structure");
var viewFrame = $('body').contents(); //<-change 'body' to whatever element you want to copy
var visible = viewFrame.find('*:not(html body)').filter(':visible');
var overlayElements = visible.map(function (i, el) {
var el = $(el);
var overlayEl = $('<div>');
overlayEl.addClass('highlight').css($.extend({
position: 'absolute',
width: el.outerWidth(),
height: el.outerHeight(),
'z-index': el.css('z-index')
}, el.offset()));
return overlayEl.get();
});
return overlayElements;
}
function sendError(){
console.log("main-website's request could not be understood");
}
I have a web application in which I have a bunch of iFrame from with source from other tools.
Now the user should have the possibility to open the iframe content in a new window / new tab, normaly I would simply add something like this:
function onButtonClick() { var src = $('#iframe').prop('src');
windows.open(src, "_blank"); }
But his would only open a new version of my iFrame context, e.g. if a user open a page in the iframe or clicked on something and javascript changed something within my iframe, the user would be loosing this value..
So, can I make a iframe Content to a new window content without loosing the dynamic state of the website within my iframe?
You cannot move around iframes between different windows without reloading, because the spec says the attributes must be reevaluated:
When an iframe element is inserted into a document that has a browsing context, the user agent must create a nested browsing context, and then process the iframe attributes for the "first time".
-- https://html.spec.whatwg.org/multipage/embedded-content.html#the-iframe-element
(via https://bugzilla.mozilla.org/show_bug.cgi?id=254144#c97)
Old answer:
// edit: Does not work as expected, since the iframe is reloaded on move and the original src is restored.
It is easy enough if you move the iframe out of the current page:
<button id="example-button">open in new window</button>
<div id="example-container">
<iframe id="example-iframe" src="https://example.com/">
</iframe>
</div>
document.getElementById('example-button').addEventListener('click', function (ev) {
ev.preventDefault();
var win = open('about:blank');
var iframe = document.getElementById('example-iframe');
// the popup might not be immediately available:
setTimeout(function () {
var body = win.document.body;
body.style.padding = 0;
body.style.margin = 0;
body.appendChild(iframe);
iframe.style.position = 'fixed';
iframe.style.padding = 0;
iframe.style.margin = 0;
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.border = 0;
}, 0);
// move the iframe back if the popup in closed
win.addEventListener('beforeunload', function () {
document.getElementById('example-container').appendChild(iframe);
iframe.style.position = '';
iframe.style.padding = '';
iframe.style.margin = '';
iframe.style.width = '';
iframe.style.height = '';
iframe.style.border = '';
});
});
Example: http://jsfiddle.net/cpy2jykv/1/
I've tried:
$(document).on("event", window.iframe_name.doument.getElementsByTagName["body"][0], function(){
//code
});
but it doesn't seem to work.
First you have to wait for the iFrame to load.
$(function(){
$('#iFrame').load(function(){
//then set up some access points
var frame = document.getElementById('iFrame'); // referance to the iframe
var frameWindow = frame.contentWindow; // referance the iframes window
var contents = $(this).contents(); // contents of the iframe
frameWindow.$('body').on(//your code here)
})
})
I want open a new window:
var my = window.open('iframe.html', '_blank' ,"height=600, width=600");
but just when open it, I want modify its DOM, I have tried:
var div = my.document.createElement("div");
div.innerHTML = "Hello!";
my.document.body.appendChild( div );
or:
var div = $('<div>Hello World</div>');
$(my).contents().find('body').append(div);
Both of them doesn't work;
So is it possible modify my iframe DOM when I open it?
It is possible to access and modify the iframe DOM only before the child window is loaded.
var my = window.open('iframe.html', '_blank' ,"height=600, width=600");
my.onload = function () {
var div = my.document.createElement("div");
div.innerHTML = "Hello!";
my.document.body.appendChild( div );
};
Also, make sure that the parent window is not closed before the child window is loaded.