I have two local .html files in the same folder. One page opens a window with the other page, and attempts to call a function in the newly opened window. However, the function call fails, and I get this in the console:
Unsafe JavaScript attempt to access frame with URL file:///***/A.html from frame with URL file:///***/B.html. Domains, protocols and ports must match.
This happens on both Chrome and Webkit (Mac). Is there any way I can either: disable the cross-domain checks for the file:// protocol, or call a javascript function in a different local file?
You can use window.postMessage to do something like this:
The initial window html file:
<!DOCTYPE html>
<html>
<head>
<script>
var otherWindow;
function openOther() {
otherWindow = window.open("other.html", "otherWindow");
}
function otherFunc() {
otherWindow.postMessage("otherFunc", "*");
}
</script>
</head>
<body>
<div onclick="openOther()">Open the other window</div>
<div onclick="otherFunc()">Call the other window's function</div>
</body>
</html>
Html for the second window:
<!DOCTYPE html>
<html>
<head>
<script>
window.addEventListener("message", function(event) {
alert("The other window's function executed.");
}, false);
</script>
</head>
<body>
<div>This is the other window.</div>
</body>
</html>
Here's a good reference for window.postMessage.
Related
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>
I am currently working on a Cordova project in Visual Studio. In this project, I am trying building 2 html pages, let me call them first.html and second.html.
In the first.html, I want to add a link to second.html, which allows me to navigate to second.html. I tried 2 ways.
window.location
window.location = "second.html"
tag
<a href=“second.html”></a>
As a result, they both caused an error saying "Exception occurred
Message: Exception: Cannot redefine property: org".
Can anyone tell me how to navigate to a new page properly?
You can navigate to another page using window.location.href. An example is shown below
function(){ window.location.href = "second.html";}
try this it work's for me
<!DOCTYPE HTML>
<html>
<head>
<title>My PhoneGap</title>
<script type="text/javascript" charset="utf-8" src="cordova-x.x.x.js"></script>
<script type="text/javascript" charset="utf-8">
function onLoad()
{
document.addEventListener("deviceready", onDeviceReady, true);
}
function onDeviceReady()
{
// navigator.notification.alert("PhoneGap is working");
}
function callAnothePage()
{
window.location = "test.html";
}
</script>
</head>
<body onload="onLoad();">
<h1>Welcome to PhoneGap</h1>
<h2>Edit assets/www/index.html</h2>
<button name="buttonClick" onclick="callAnothePage()">Click Me!</button>
</body>
</html>
You can use the below line to navigate one page to another page.
$('#yourelement').click(function(){
window.location.assign('name_of_page.html');
});
Try this:
window.open("second.html");
window.open opens a new window/tab with the selected URL, while the mentioned method in the question redirects the current page to the selected URL.
I have a question about javascript function flow. I am building a chrome extension where one javascript file creates a popup window using window.open. Based on the button selected in the popup, a variable is set and a function in the original javascript function should be called. But, it doesn't recognize that function from the original javascript file. I don't want to include file1 in file2's header, because other functions that I don't need would be called within file2. How do I handle this case?
A snippet of my code is the following:
in default_popup.html
<html
<head>
<script type="text/javascript" src="login.js"></script>
</head>
</html>
in login.js
function login() {
if (token === null) {
var url = chrome.extension.getURL('options.html');
window.open(url);
}
else {....}
function auth(url) {
............
}
//other functions here
in options.html
<html>
<head>
<script type="text/javascript" src="redirect.js"></script>
</head>
<body>
<button id="button1">Option1</button>
<button id="button2">Option2</button>
</body>
</html>
in redirect.js
var url;
document.getElementById('button1').onclick = function() {
url = 'url_one.com';
auth(url)
}
document.getElementById('button2').onclick = function() {
url = 'url_two.com';
auth(url);
}
Create a different JS file and you can call it common.js.
Transfer all the functions that needs to be accessed by both files there.
It is possible passing a function in the window reference, however chrome security setting may interfere that with local files because of the "same origin security principal", it works in other browsers on local, not sure in server pages and extension, so worth the test, follow the example:
html1:
<html>
<head>
<script type="text/javascript">
function test(){
var windowRef = window.open('test2.html');
windowRef['auth'] = function(){windowRef.document.write('property transferred')}
}//here you'll reference your auth function.
</script>
</head>
<body>
<input type="button" value="test" onclick="test()" >
</body>
</html>
html2:
<html>
<head>
<script type="text/javascript">
window['auth']() //the function to call, window.auth() should work too.
</script>
</head>
<body>
new window
</body>
</html>
The output will be a new window with "property transferred" in it.
My website provides iframe code which is put in some other websites.
For simplicity lets say my domain i.e the source of the iframe is www.abc.com and my client who uses my iframe code has domain www.xyz.com.
In my iframe website I try to access geoLocation of user using javascript.
When www.xyz.com is browsed on mobile, www.abc.com (in iframe) puts a confirmation box to allow or deny the access for geoLocation.
Now my issue is:-
I want to show the confirmation box only when the iframe is in the viewable area of the browser. And I want to do it without asking my clients to put any more js code in their website. It should all happen from my iframe source.
I tried the following, but visibilityChanged() gets fired only when we change the browser tab or minimize or maximize the browser...
Sample code. a.html
<!DOCTYPE html>
<html>
<head>
<script>
function onLoad() {
console.log('onload:', (document.hidden));
document.addEventListener("webkitvisibilitychange", visibilityChanged);
}
function visibilityChanged() {
console.log('visibilityChanged: ',arguments);
}
</script>
</head>
<body onload="onLoad()">
test
</body>
</html>
b.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<iframe style="border:1px solid red; width:200px;height:200px;" src="a.html"/>
</body>
</html>
The new PageVisibility API, which should be widely supported on mobile, looks much more promising:
Broad support: http://caniuse.com/#feat=pagevisibility
Spec: http://www.w3.org/TR/page-visibility/
Code snippet from the spec (above):
var timer = 0;
var PERIOD_VISIBLE = 1000;
var PERIOD_NOT_VISIBLE = 60000;
function onLoad() {
timer = setInterval(checkEmail, (document.hidden) ? PERIOD_NOT_VISIBLE : PERIOD_VISIBLE);
if(document.addEventListener) document.addEventListener("visibilitychange", visibilityChanged);
}
function visibilityChanged() {
clearTimeout(timer);
timer = setInterval(checkEmail, (document.hidden) ? PERIOD_NOT_VISIBLE : PERIOD_VISIBLE);
}
function checkEmail() {
// Check server for new messages
}
One page open another page(eg. openerdemo.html) using the window.open() method, but the popup page cannot access any property of the opener page.
Opener page code:
<head>
<meta http-equiv="content-type" content="html/text"; charset="utf-8" >
<title>windowdemo</title>
<script language="JavaScript">
function openWin(thisurl) {
popWin = window.open(thisurl, 'popupPage', "width=480,height=272");
}
</script>
</head>
<body>
<input type="button" value="open" onClick="openWin('openerdemo.htm')"/>
</body>
Popup page(openerdemo.htm) code:
<html>
<head>
<meta http-equiv="content-type" content="html/text"; charset="utf-8" >
<title>windowdemo</title>
<script language="JavaScript">
function closeWin() {
window.opener.close();
window.close();
}
</script>
</head>
<body>
<h1>close all</h1>
</body>
I use javascript console in Chrome, enter 'window.opener' to the cmd line of popup window, it's return:
window.opener
'Window {}',
That means the opener window is not null, but its all property missing. However, if one page opens a new page like this:
popWin = window.open('', 'popupPage', "width=480,height=272");
popWin.document.write("this is popupPage");
The popup page's window.opener is ref to the opener window, and just can control the opener window with the 'window.opener' object.
ex:
<body>
<script type="text/javascript">
myWindow=window.open('','','width=200,height=100')
myWindow.document.write("This is 'myWindow'")
myWindow.focus()
myWindow.opener.document.write("This is the parent window")
</script>
</body>
I test this code in FF, IE and chrome.
Can anyone tell me how to control the opener window in popup page?
It would work fine, but you're making a cross-domain request. If the window you are opening and the window you opened it from are on the same domain, you wouldn't have a problem
Note: This may be classified as a cross-domain request when you are not using a webserver, but just using the file system (file:/// is your protocol). I haven't tested it - rest assured, however, that when you get it on the web, all will be well as long as both the opener and the openee are server from the same domain.
EDIT
I just did a quick test on my local file system and this is indeed the case - it's classified as a cross-domain request and is forbidden for security purposes - again, it won't be a problem when you put it on a webserver and serve both pages from the same domain.