Top of page from within iFrame - cross domain - javascript

Am hoping I haven't overlooked a solution here on SO, but I have been pulling my hair out trying to figure out what I am doing wrong and hoping somebody can see what it is. Here is the configuration:
I have a page that is served on DOMAIN1.COM. For the most part is is a form with a submit button and lots of jQuery. The form can be lengthy and so a user needs to scroll down the page to input form fields. The submit button is at the bottom of this form while the output results are at the top of the form. When the user clicks the submit button he/she cannot see the results because they are off of the top of the page. What I want to do is use jQuery scrollTo() to position to the top of the page once the submit button is clicked.
The problem is that the page above (and submit button) is within an iFrame on DOMAIN2.COM and so when the submit button is clicked I have a cross domain situation that I need to overcome.
I posted a question here, but my question wasn't really accurate. The thread evolved into helpful information and pointed me to a script that uses jQuery postMessage() to communicate cross domain, but I am having a problem implementing the proposed solution. Here's my code:
DOMAIN1.COM (child):
<html>
<head>
<!-- Load jquery -->
<script type="text/javascript" src="./jquery-2.0.3.min.js"></script>
<!-- Cross-domain scripting goodness (scroll to top) -->
<script type="text/javascript" src="./jquery.ba-postmessage.js"></script>
<script type="text/javascript">
// EVENT Handler - Form Submission
$(function () {
$("#btnSubmit").bind('click', function (event) {
// Get the parent page URL as it was passed in,
// for browsers that don't support window.postMessage
var parent_url = decodeURIComponent(document.location);
window.postMessage("scrollTop", parent_url, parent);
});
});
</script>
</head>
<body>
<form>
... Lots of form fields resulting in vertical height ...
<input type="submit" id="btnSubmit" value="Submit" />
</form>
</body>
</html>
DOMAIN2.COM (parent):
<html>
<head>
<!-- Load jquery -->
<script type="text/javascript" src="./jquery-2.0.3.min.js"></script>
<!-- Cross-domain scripting goodness (scroll to top) -->
<script type="text/javascript" src="./jquery.ba-postmessage.js"></script>
<script type="text/javascript">
// Cross-domain - scroll window to top
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.data == "scrollTop") {
window.scrollTo(0, 0);
}
}
</script>
</head>
<body>
<iframe src="http://domain1.com/index.html"></iframe>
</body>
</html>
Running both pages above on the same domain provides the desired results - clicking submit scrolls the page to the top.
Running on separate domains as documented and coded above, the page does not scroll to top, my output results fail, and jQuery outputs this error message in Firebug:
DataCloneError: The object could not be cloned.
If I change the code to leave out the parent parameter in the page on DOMAIN1.COM like:
var parent_url = decodeURIComponent(document.location);
window.postMessage("scrollTop", parent_url); //, parent);
Then nothing happens at all and no errors are output. It does not appear that receiveMessage() on DOMAIN2.COM gets called at all.
Can anyone see what I might be doing wrong that prevents this code from working cross domain?

I think it very late now but for others, it may work.
You are almost there; You need to use
window.postMessage("scrollTop","#domain of parent page exact page");
Instead of your code snippet:
window.postMessage("scrollTop", parent_url, parent);
If at the time the event is scheduled to be dispatched the scheme, hostname, or port of otherWindow's document does not match that provided in targetOrigin, the event will not be sent by Dom. Read documentation here
In Parent Page use following code snippet.
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "#domain of iframe")
return;
if (event.data == "scrollTop"){
window.scrollTo(0,0);
}
}

Related

JavaScript Message event not being fired [duplicate]

This question already has answers here:
How do you use window.postMessage across domains?
(3 answers)
Closed 5 years ago.
I have a simple HTML5 page with an iframe whose src attribute is initially empty string. The page renders without any JavaScript errors.
The src attribute of iframe element is only set when the window has loaded, so initially an empty iframe loads. The iframe src is being set to a page from another domain.
The problem I am facing is that the postMessage method works without throwing any errors, however the source page is not firing the message event even though it's set up before the iframe page starts loading. I am having the alert messages from iframe page show up, which means the postMessage method did not throw any errors.
Question
What am I missing when subscribing to the message event in source page?
Source page
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Cross domain iframe messaging</title>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script type="text/javascript">
var iframec = null;
window.addEventListener("load", function () {
iframec = document.getElementById("iframec");
//set up event listener for iframe object so it can receive message from page shown in iframe
iframec.contentWindow.addEventListener("message", function (event) {
alert("received: " + event.data);
}, false);
//load the iframe page but after you have set up to receive messages
iframec.src = "http://www.abcx.com";
});
</script>
</head>
<body>
<form id="form1">
<div>
<h1>Testing iframe messaging in a Cross Domain scenario</h1>
<p> Trying to send a message to an iframe that comes from a page in another domain. The postMessage method does not throw an error when called from the other domain page, but it's not being received by the page having iframe element in it.</p>
<div id="divComments"></div>
<iframe src="" id="iframec" name="iframec" style="border:none;margin:0;padding:0;width:100%; "></iframe>
</div>
</form>
</body>
</html>
Iframe Page JavaScript that is not throwing any error (i.e. page at http://www.abcx.com)
<script>
$( document ).ready(function() {
alert("loaded the iframe page on another domain. Just before postMessage");
window.postMessage("Some message was sent from other domain message", "*");
alert("loaded the iframe page on another domain. Just after postMessage");
});
</script>
You're hooking up the listener on the wrong window, and using the wrong window to send the message. (This is fairly easy to get wrong. :-) )
In the main window, you want to receive message events on the main window, not the iframe, so:
window.addEventListener("message", function (event) {
// ^^^^^^^
alert("received: " + event.data);
}, false);
In the iframe, you want to send to window.parent (well, parent), not window:
parent.postMessage("Some message was sent from other domain message", "*");
// ^^^^^^
With both of those changes, the message sent by the iframe is received by the main window.
I found a similar question here
On the page you're trying to load, it should be using top.postMessage or parent.postMessage
Additionally, you should be attaching the listener to the window, not the iframe (and make sure to filter the origin, or else localhost will throw you a false positive)
This is the version of yours I was playing with:
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script>
var iframec = null;
window.addEventListener("load", function () {
if(!iframec){
iframec = document.getElementById("iframec");
//set up event listener for iframe object so it can receive message from page shown in iframe
window.addEventListener("message", function (event) {
if(event.origin == '[your domain here]') alert("received from " + event.origin + ": " + event.data);
}, false);
//load the iframe page but after you have set up to receive messages
iframec.src = "[iframe target url]";
}
});
</script>
And the target for the iframe:
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script>
$( document ).ready(function() {
alert('loaded the page. Just before postMessage');
top.postMessage("Some message was sent from appsprocure", "*");
alert("loaded the page. Just after postMessage");
});
</script>
</head>
<body><h1>Hello!</h1></body>
</html>

Chrome JavaScript console is null after submitting the page

This was unexpected. I use Chrome as my primary development browser and make generous use of "console.log" (way better than alerts!)
Anyway, I have a page inside an IFrame (for uploading images). That page includes scripts that often write out to the console window (console.log) for tracking purposes. The first time the parent page submits the embedded page via script, everything goes smoothly. If I, however, then attempt to submit the page a second time I get the error ...
Uncaught TypeError: Cannot call method 'log' of null
All of a sudden it seems that the console is no longer available. If I replace it with an alert the alert box appears as expected, but the page no longer submits either.
Has anybody experienced anything like this before?
I want to thank folks for their responses. I did not include any code in the OP because it is an extensive script and parsing out an "example" of what I was attempting to do so that it wasn't too tedious to go through would likely strip out any relevancy.
I am posting, however to say that I did discover the problem.
I have PageA which contains an IFrame which is in turn loaded with PageB.
<html>
<head><title>PageA</title></head>
<body>
<IFrame src="PageB" name="frame1" id="frame1"></IFrame>
</body>
</html>
PageB contains a function that needs to be called from PageA when a button is clicked.
<!-- PageB -->
<html>
<head><title>PageB</title></head>
<body>
<form id="form1" name="form1" >
</form>
<script>
var SubmitForm = function(){
var $form = $("form[id$='form1']");
$form[0].submit(); // this was not firing
console.log("some log output"); // this was throwing an error
};
</script>
</body>
</html>
<!-- PageA -->
<html>
<head><title>PageA</title></head>
<body>
<IFrame src="PageB" name="frame1" id="frame1"></IFrame>
<button onclick="submitIFrameForm()">Submit</button>
<script>
var frameWindow = frames["frame1"];
var frameForm = frameWindow.SubmitForm;
function submitIFrameForm(){
frameForm();
};
</script>
</body>
</html>
THE PROBLEM
When PageA first loads, the IFrame is loaded with PageB and the script in PageA makes it's reference (frameForm) to the "SubmItForm()" function on PageB. When I click on the submit form button in PageA, PageB is submitted back to the server. No problem ...
However when PageB is submited it is UNLOADED from the window. So when I click on the
submit button in PageA a second time, although PageB may reload it is a different instance of the page. Therefore all the variables which reference the original PageB are now pointing to nothing ... hence the window that console was referencing no longer exists, so the "log" method cannot run.
THE FIX
Instead of creating a global reference to the contents of the IFrame, we must re-establish this reference to the function each time the button is clicked. (Since the IFrame is a member of PageA we do not need to re-establish the IFrame reference).
<!-- PageA -->
<html>
<head><title>PageA</title></head>
<body>
<IFrame src="PageB" name="frame1" id="frame1"></IFrame>
<button onclick="submitIFrameForm()">Submit</button>
<script>
var frameWindow = frames["frame1"];
function submitIFrameForm(){
frameWindow.SubmitForm(); // move the reference to the click event handler
};
</script>
</body>
</html>
I hope that this made sense and that it helps someone out there. I get caught up on this kind of stuff constantly.

Javascript Body OnLoad Event is not triggered due to missing body tag

I am trying to entegrate 3D Secure payment logic with javascript.
As I post the credit card info to bank, I get a reply html.. This html redirects the screen to 3D Password screen of the bank which is
<html>
<head>
<title>MDpay default response template for web</title>
</head>
<body bgcolor="#02014E" OnLoad="OnLoadEvent();" >
<form name="downloadForm" action="https://katmai.est.com.tr/mdpayacs/pareq" method="POST">
<!-- Some Input Fields -->
</form>
<SCRIPT LANGUAGE="Javascript" >
function OnLoadEvent() {
document.downloadForm.submit();
}
</SCRIPT>
</body>
</html>
if we want to open this html in a pop up screen, OnLoadEvent does not get triggered with :
var popup = window.open('','');
popup.document.write("'"+data+"'");
popup.focus();
bu if this does work which is everything good. I call the onload function in body so i dont care what is the function to be called in OnLoad.
var popup = window.open('','');
popup.document.write("'"+data+"'");
popup.document.body.onload();
popup.focus()
BUT, we don't want to do this in popup, we dont want to open a new tab or page. We want to do this on same screen that we get the values from the user.. So I write the returning html to a div, but because there can be no 2 body tags in one html, the browser does not include the new body tag which includes OnLoad function name..
document.getElementById('vpos').innerHTML=data;
document.downloadForm.submit() // this is the code that works in OnLoad function.if a write that code statically of course it works, but this code logic can always change.
How will I solve this. Hope I am clear..

Execute Function when iFrame url Changes

I have a signup form which is inside an iframe on my site and I want to create a redirect when the url of the iframe changes (when user successfully signed-up).
These 2 sites are cross domain and I know that it is almost impossible to pull the url cross domains but is there a workaround? I know the src will not change and I was thinking to use onload(), when the iframe loads a second time (when user successfully signed-up), execute a function to redirect to a thank you page.
Here is an example using the javascript 'Porthole'.
Its possible, but keep in mind the safety issues with iframes. The solution: if you have control of the original page + iframe, you can 'trick' the browser by implementing some javascripts on both sides.
First create a 'proxy' page on both domains. Name it 'proxy.html' or something (note: you have to use 'porthole.min.js', you can get this from the sources in the bottom)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- Replace the url with your own location -->
<script type="text/javascript" src="porthole.min.js"></script>
<script type="text/javascript">
window.onload=function(){ Porthole.WindowProxyDispatcher.start(); };
</script>
</head>
<body>
</body>
</html>
On the parent page: (refer to the iframe proxy.html page)
<script type="text/javascript" src="porthole.min.js"></script>
<iframe id="guestFrame" name="guestFrame" src="http://iframe.otherdomain.com/"></iframe>
<script type="text/javascript">
var iframeDomain = 'http://iframe.otherdomain.com';
var redirectUrl = 'http://www.mydomain.com/redirect-to/signed-up';
function onMessage(messageEvent) {
if (messageEvent.origin == iframeDomain) {
if (messageEvent.data["action"]
&& messageEvent.data["action"] == 'signed-up) {
window.location.href = redirectUrl; // The final action!
// This is the eventual redirect that will happen
// once your visitor has signed-up within the iframe
}
}
}
var windowProxy;
window.onload=function(){
// Create a proxy window to send to and receive messages from the iFrame
windowProxy = new Porthole.WindowProxy(
'http://iframe.otherdomain.com/proxy.html', 'guestFrame');
// Register an event handler to receive messages;
windowProxy.addEventListener(onMessage);
};
</script>
On the iframe page (refer to the parent proxy.html page)
<script type="text/javascript">
var windowProxy;
window.onload=function(){
// Create a proxy window to send to and receive messages from the parent
windowProxy = new Porthole.WindowProxy(
'http://www.mydomain.com/proxy.html');
// Register an event handler to receive messages;
windowProxy.addEventListener(function(event) {
// handle event (not used here, the iframe does not need to listen)
});
};
</script>
From the iframe you can send a message with javascript to the parent page (and also the other way). If you use only 1 javascript within the iframe domain, you can do something like this to send a message to the parent frame when the url is changed to something specific, for example 'signed-up.php' (untested, but you'll get the idea)
<script type="text/javascript">
window.onload=function(){
if(window.location.href.indexOf("signed-up.php") > -1) {
windowProxy.post({'action': 'signed-up'}); // Send message to the parent frame
// On the parent page, the function 'onMessage' is triggered.
}
};
</script>
Sources:
http://ternarylabs.github.io/porthole/
Github: https://github.com/ternarylabs/porthole
Demo: http://sandbox.ternarylabs.com/porthole/

JavaScript access parent window from popup windows

I am trying to code this for hours and still couldn't do it. It keep tell me "Permission Denied".
Here is what I am trying to accomplish. This pretty hard to explain please follow the example below.
For example. domain111.com and domain222.com.
When I am on domain111.com i click on the popup link , it will pop-up the domain111.com/popup.html then it redirect me to domain222.com. On this domain222.com it will redirect to couple pages before it redirect back to domain111.com with the result. I want to send the result from domain111.com to domain111.com.
The process is like below.
Domain111-popup to-->Domain111-redirect-->Domain222-redirect xxx Domain222 pages then redirect to-->-Domain111---SEND to parent window->Domain11
Here is my code.
File name 1.hml on domain111.com
<script type="text/javascript">
function IamParent() {
alert('I am the parent of this window')
}
function PopUP() {
window.open("http://domain222.com/2.htm", 'ALpop').focus();
}
</script>
<body>
<a href="#void(0);" onclick="PopUP();" >Click</a>
</body>
File name 2.html on domain222.com
<head>
<title></title>
<meta http-equiv="refresh" content="1;url=http://domain111.com/3.htm?Result=Yes" />
</head>
Filename 2.htm on domain111.com
<script type="text/javascript">
parent.IamParent(); //execute the function from the same domain111.com/1.htm
</script>
Please don't suggest AJAX or web request because it will not work with this case.
Thanks for reading.
Parent windows in other domains are inaccessible due to a security restriction requirement in the JavaScript engines. This applies to all browsers. It is a cross-site scripting attack prevention that cannot be disabled.

Categories

Resources