Functions() out of iframe? [duplicate] - javascript

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to call Javascript function in parent document from JS in iframe?
I have a main.php page.
This contains an iframe which src is random.php.
How can I have script in the main.php with a random function, random(), and let random.php use that function?

If you are working with HTML5, you can use the postMessage() function..
here is a nice demo:
http://html5demos.com/postmessage
UPDATE
The idea is to postMessage to the iframe window object, each window is listening to the message event like so:
In your main.php:
window.addEventListener("message", function(e){
var data = e.data; // data can be any object for example { type: 'random', payload: {}... }
switch(data.type){
case 'random':
// do somthing here with the payload...
break;
}
});
in your iframe (random.php):
window.parent.postMessage({ type: 'random', payload: {...} });

You can call the function random in the page that contains the iframe using window.parent.random(). If you want to do the opposite, namely calling a function in an (i)frame from a containing page, you should use [DOM Reference to frame].contentWindow.random() instead.
↪ More information about window.parent at the Mozilla Developer wiki
If random.php is at a different domain, you can't do this because of the Same Origin Policy. If that's the case, you can use HTML5 postMessage to transfer information across pages*. This does not allow you to directly call functions of a different domain's JavaScript, however.
* See Can I use for browser support information

Related

Restore native Window method

For a script I'm writing, I'd like to use the native window.open method. However, a script already loaded to which I don't have access, overwrites the global window.open method with a boolean (ouch).
I know how to restore the methods on the Document (via HTMLDocument.prototype), but I don't know how to restore them on the Window, as I can't seem to find the equivalent for that to Window. Window.prototype.open does not exist for example.
I have tried creating an iframe, and getting the open method from that contentWindow in the iframe, but the browser will block opening windows using open because it was probably created in another origin. Neither delete open; does work because open was defined using var in the globally loaded script.
So, how can I restore the open method, defined as 'native code' in Chrome?
I know there are similar questions around, but actually the main question is:
Is there a equivalent of HTMLDocument for the Window object?
I've found this question and the accepted answer (using an iframe) could be used in your case.
The only issue is you can only use the retrieved version of window.open as long as the iframe is still in your document.
function customOpen() {
// local variables definitions :
var url = "https://stackoverflow.com", iframe, _window;
// creating an iframe and getting its version of window.open :
iframe = document.createElement("iframe");
document.documentElement.appendChild(iframe);
_window = iframe.contentWindow;
// storing it in our window object
window.nativeOpen = _window.open;
try {
window.open(url);
} catch (e) {
console.warn(e); // checking that window.open is still broken
}
window.nativeOpen(url);
// deleting the iframe :
document.documentElement.removeChild(iframe);
}
document.getElementById("button").addEventListener("click", customOpen);
Another JSFiddle
Keeping the workaround answer in case someone needs it :
Can you execute a custom script prior to the execution of the script that redefines window.open? If so, you could create a copy of the window.open in another global variable.
It could look like this :
1. First : a backup script
window.nativeOpen = window.open;
2. Then, whatever the window.open overwriting script does :
window.open = false; // who does that, seriously?
3. Your window opening script, that'll use your window.open copy :
function customOpen() {
var url = "https://stackoverflow.com";
try {
window.open(url);
} catch (e) {
console.warn(e);
}
window.nativeOpen(url);
}
JSFiddle example

Send a message from an iframe on the main page

I have seen from this documentation: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage , the way to pass a data correctly to an iframe. But now I want to send an answer:
//from main page
myIframe.contentWindow.postMessage('send me a response', '*');
//from iframe of main page
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event){
alert(event.data);//the value of message
//now i need to send an answer 'this is a response'
}
}
How do I send an answer to the main page from the iframe?
I need really of this answer.
Edit:
Ok i found the solution ty at all.
You have access to the parent window on the global window.parent.
I believe it is as easy as using this object's method at this point to postMessage. So something like:
var parent = window.parent;
parent.postMessage("some message");
A full example can be found here.
The gist is the window.parent.postMessage() function takes the following arguments: otherWindow.postMessage(message, targetOrigin, [transfer]);
I would consider using easyXDM
EasyXDM WebSite

postMessage() generates error "undefined is not a function"

I'm trying to get postMessage() to work to communicate between an iframe and my main website. However using the exact syntax given in the example code on MDN, I am being presented with a nice Undefined is not a function error. I've tried several things, such as initializing the iframe inside Javascript and appending it to my page, but that left me with the same error. Same for have seperate selectors to select my iframe.
I have the following Javascript code:
<script type="text/javascript">
$(document).ready(function() {
$('.editor').postMessage("A", "domain here");
});
function receiveMessage(event)
{
if (event.origin !== "domain here")
return;
// Do something
}
window.addEventListener("message", receiveMessage, false);
</script>
The script above tries to send a message to my iframe on the page, which looks like:
<iframe src="domain here/frameListener.html" class="editor"></iframe>
It then has a function receiveMessage to catch any messages being send as a response to the main webpage. Last but not least, I've tried the answers given in this question: But that did not fix my problem. It is therefore not a duplicate.
How can I get rid of this error message?
postMessage is not a jQuery function so you need to get the actual window DOM element and call it on that:
$('.editor').get(0).contentWindow.postMessage("A", "domain here");
Furthermore, you need to access the contentWindow property of the iframe. Here is an excerpt from the MDN docs:
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
A reference to another window; such a reference may be
obtained, for example, using the contentWindow property of an iframe
element, the object returned by window.open, or by named or numeric
index on window.frames.

Chrome extensions: best method for communicating between background page and a web site page script

What I want to do is to run go() function in image.js file. I've googled around and I understand that is not possible to run inline scripts.
What is the best method to call the JavaScript I want? Events? Messages? Requests? Any other way?
Here is my code so far:
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
var viewTabUrl = chrome.extension.getURL('image.html');
var newURL = "image.html";
chrome.tabs.create({
url : newURL
});
var tabs = chrome.tabs.query({}, function(tabs) {
for (var i = 0; i < tabs.length; i++) {
var tab = tabs[i];
if (tab.url == viewTabUrl) {
//here i want to call go() function from image.js
}
}
});
});
image.html
<html>
<body>
<script src="js/image.js"></script>
</body>
</html>
image.js
function go(){
alert('working!');
}
There are various ways to achieve this. Based on what exactly you are trying to achieve (which is not clear by your question), one way might be better than the other.
An easy way, would be to inject a content script and communicate with it through Message Passing, but it is not possible to inject content scripts into a page with the chrome-extension:// scheme (despite what the docs say - there is an open issue for correcting the docs).
So, here is one possibility: Use window.postMessage
E.g.:
In background.js:
var viewTabURL = chrome.extension.getURL("image.html");
var win = window.open(viewTabURL); // <-- you need to open the tab like this
// in order to be able to use `postMessage()`
function requestToInvokeGo() {
win.postMessage("Go", viewTabURL);
}
image.js:
window.addEventListener("message", function(evt) {
if (location.href.indexOf(evt.origin) !== -1) {
/* OK, I know this guy */
if (evt.data === "Go") {
/* Master says: "Go" */
alert("Went !");
}
}
});
In general, the easiest method to communicate between the background page and extension views is via direct access to the respective window objects. That way you can invoke functions or access defined properties in the other page.
Obtaining the window object of the background page from another extension page is straightforward: use chrome.extension.getBackgroundPage(), or chrome.runtime.getBackgroundPage(callback) if it's an event page.
To obtain the window object of an extension page from the background page you have at least three options:
Loop through the results of chrome.extension.getViews({type:'tab'}) to find the page you want.
Open the page in the first place using window.open, which directly returns the window object.
Make code in the extension page call a function in the background page to register itself, passing its window object as a parameter. See for instance this answer.
Once you have a reference to the window object of your page, you can call its functions directly: win.go()
As a side note, in your case you are opening an extension view, and then immediately want to invoke a function in it without passing any information from the background page. The easiest way to achieve that would be to simply make the view run the function when it loads. You just need to add the following line to the end of your image.js script:
go();
Note also that the code in your example will probably fail to find your tab, because chrome.tabs.create is asynchronous and will return before your tab is created.

Calling a function inside an iframe from outside the iframe [duplicate]

This question already has answers here:
Invoking JavaScript code in an iframe from the parent page
(17 answers)
Closed 8 years ago.
I have a page with an iframe. Inside that iframe I have a javascript function like this:
function putme() {}
How can I call this function on the main page?
window.frames['frameName'].putme();
Do note that this usually only works if the iframe is referring to a page on the same domain. Browsers restrict access to pages within frames that belong to a different domain for security reasons.
For even more robustness:
function getIframeWindow(iframe_object) {
var doc;
if (iframe_object.contentWindow) {
return iframe_object.contentWindow;
}
if (iframe_object.window) {
return iframe_object.window;
}
if (!doc && iframe_object.contentDocument) {
doc = iframe_object.contentDocument;
}
if (!doc && iframe_object.document) {
doc = iframe_object.document;
}
if (doc && doc.defaultView) {
return doc.defaultView;
}
if (doc && doc.parentWindow) {
return doc.parentWindow;
}
return undefined;
}
and
...
var el = document.getElementById('targetFrame');
var frame_win = getIframeWindow(el);
if (frame_win) {
frame_win.putme();
...
}
...
If the iframe is in a different domain than the outer page, with great difficulty, or not at all.
In general, the browser prevents javascript from accessing code from a different domain, but if you control both pages, there are some hacks to make something work. More or less.
For example, you can change the fragment of the URL of the iFrame from the outer one, poll the fragment from inside the iframe and call that function. There is a similar trick with the name of the window.
On the frameset, specify a name for your frame and in main page you can access the frame by its given name:
window.[FrameName].putme();
You can access the iframe with it's name:
foo.putme();
Functions declared globally inside the iframe page will become members of the window object for that iframe. You can access the window object of the iframe with the iframe's name.
For this to work, your iframe needs to have a name attribute:
<iframe name="foo" ...>
Also, the main page and the iframe page should be from the same domain.
Give the frame a name and an id - both identical.
window.frameNameOrId_.functionName()
Both frames must be in the same domain (though there are ways around this to limited degree)
This can be done with JavaScript:
window.top.location.href = url;
Works perfectly in all major browsers.

Categories

Resources