Post a message to newly opened browser - javascript

I'm trying to post a message using the postMessage function to a browser that I've opened using window.open and while I've found a couple of articles explaining on how to do it:
Window.postMessage()
HTML5’s window.postMessage API
I just can't get it to work.
In my grid, when double clicking on a row, I call the following code:
var win = window.open('#Url.Action("Index", "StandaloneViewer")', '_blank',
'width=600,height=800,scrollbars=yes');
var domainOrigin = document.location.origin;
var message = 'My Message';
win.postMessage(message, domainOrigin);
and in my Index.cshtml, I've got the following:
$(document).ready(function () {
window.addEventListener('message', function (event) {
debugger;
var domainOrigin = document.origin;
var domainPath = document.location.href;
if (event.origin !== domainOrigin) return;
...
}, false);
});
I've also tried the same code in the load event:
$(window).on("load", function () {
window.addEventListener('message', function (event) {
debugger;
var domainOrigin = document.origin;
var domainPath = document.location.href;
if (event.origin !== domainOrigin) return;
...
}, false);
});
but to no avail! Any ideas what I may be missing? I've got the same scenario working just fine when sending a message to an iframe but I have a use case where I need to launch a separate browser and send a message to it.
I'm currently testing this on the latest version of Chrome.
Thanks.

Related

chrome extension passing multiple message to external site by sharing local storage

**
RESOLVED
**
I'm developing a chrome extension. reading on stackoverflow I was able to share the local storage between different domains and to send a data from the extension to my external site.
what I would like to do, however, is to send more than one message to the external site. how can i adapt the code i am using? i am not very familiar with js, sorry
This is the code on popup.html -> extension (function perfectly)
window.onload = function() {
var receiver = document.getElementById('receiver').contentWindow;
var btn = document.getElementById('send');
function sendMessage(e) {
e.preventDefault();
receiver.postMessage(document.getElementById('D1').value, 'http://externalsite');
}
btn.addEventListener('click', sendMessage);
}
This is the code on external site -> receiver
window.onload=function(){ var messageEle=document.getElementById('message');
window.addEventListener('message',receiveMessage);
function receiveMessage(e){
if(e.origin!=="chrome-extension://ldjfmalmmomhpjmoeemlaingagdhagjl")
return;
messageEle.value = e.data;
}
}
What i need is send more of
receiver.postMessage(document.getElementById('D1').value, 'http://externalsite');
for example
receiver.postMessage(document.getElementById('D1').value, 'http://externalsite');
receiver.postMessage(document.getElementById('D2').value, 'http://externalsite');
receiver.postMessage(document.getElementById('D3').value, 'http://externalsite');
Thanks a lot
for helping other, i resolve in this mode
in popup.html code on extension
window.onload = function() {
var receiver = document.getElementById('receiver').contentWindow;
var data = {
domanda1: (document.getElementById('D1').value),
domanda2: (document.getElementById('D2').value),
domanda3: (document.getElementById('D3').value)
};
var btn = document.getElementById('send');
function sendMessage(e) {
e.preventDefault();
receiver.postMessage(data, 'externaldomain');
}
btn.addEventListener('click', sendMessage);
}
and in the receiver page -external site- with code
window.onload=function(){
var domanda1=document.getElementById('domanda1');
var domanda2=document.getElementById('domanda2');
var domanda3=document.getElementById('domanda3');
window.addEventListener('message',receiveMessage);
function receiveMessage(e){
if(e.origin!=="chrome-extension://ldjfmalmmomhpjmoeemlaingagdhagjl")
return;
domanda1.value = e.data.domanda1;
domanda2.value = e.data.domanda2;
domanda3.value = e.data.domanda3;
}
}
ps = thanks to wOxxOm for help

postMessage is not working with dynamically added iframe in firefox addon using xul

I am creating a firefox addon using xul. I have added a dynamic iframe using following script:
//addon script:
let chromeUrl = 'https://myserver/downloadProduct.html';
Components.utils.import('resource://gre/modules/Services.jsm');//Services
let activeWindow = Services.wm.getMostRecentWindow('navigator:browser');
let mainDocument = activeWindow.document;
let iframeEl;
iframeEl = mainDocument.createElement('iframe');
iframeEl.id = "d";
iframeEl.setAttribute('src',chromeUrl);
iframeEl.setAttribute("tooltip", "aHTMLTooltip");
iframeEl.setAttribute("autocompleteenabled", true);
iframeEl.setAttribute("autocompletepopup", "PopupAutoComplete");
iframeEl.setAttribute("disablehistory",true);
iframeEl.setAttribute('type', 'content');
iframeEl.setAttribute('height', '32px');
window.document.documentElement.insertBefore(iframeEl, window.document.documentElement.window);
window.addEventListener("message", receiveMessage,false);
Above script is successfully adding a new iframe on page. Now I want to receive messages from iframe to my addon. I have created a postMessage event in iframe script, script as follows:
//iFrame Script:
<script type="text/javascript">
$(document).ready(function () {
$("#Download").click(function () {
parent.postMessage({ Action: "DOWNLOADED", Result: null }, "*");
})
$("#NotNow").click(function () {
parent.postMessage({ Action: "NOT_NOW", Result: null }, "*");
})
$("#Never").click(function () {
parent.postMessage({ Action: "DO_NOT_SHOW", Result: null }, "*");
})
});
</script>
But I am not able to receive message in my firefox addon.
Can anybody help?
Solution is:
window.document.getElementById("iframeId").contentWindow.document.getElementById("elementId").addEventListener('click', function() {
//Do something
}, false);
This script can be added just after adding dynamic iframe on the page.

Redirect javascript failing in all but Chrome

Trying to have a webpage manage a redirect, if a deeplink fails to open. If the deeplink opens, great. if it doesn't within 2 seconds, I want it to go to my website.
<script type="javascript">
setTimeout(function () { window.location = "http://mywebsite.com"; }, 25);
window.location = "my://app";
</script>
I've tested in Chrome and it works, but Firefox, IE, and Safari all block the script.
Anyone have any idea on how to handle this?
window.location.assign("http:mywebsite.com") may be a better alternative as I believe calling that function fires some additional events that may make the lifecycle of the page easy to manage.
Also in about all except Chrome you can use an IFrame to attempt to launch your protocol handler. This will help prevent the page going to about:blank and/or your script stopping due to navigating away from the page.
var createIframe = function(id, url, timeout, callback) {
var iframe;
iframe = document.createElement("iframe");
iframe.hidden = true;
iframe.id = id;
iframe.src = url;
var data = {}
data.id = id;
data.iframe = iframe;
return setTimeout(callback, timeout, null, data);
}
createIframe('tempFrame', 'http://mywebsite.com', 25, function(err, data) {
if(!err && data){
var iframe = data.iframe;
var id = data.id;
iframe = document.getElementById(id);
iframe.parent.removeChild(iframe);
}
else {
console.log('There was an error createing and removeing the iframe');
}
}

'load' event not firing when iframe is loaded in Chrome

I am trying to display a 'mask' on my client while a file is dynamically generated server side. Seems like the recommend work around for this (since its not ajax) is to use an iframe and listen from the onload or done event to determine when the file has actually shipped to the client from the server.
here is my angular code:
var url = // url to my api
var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
e.load(function() {
$scope.$apply(function() {
$scope.exporting = false; // this will remove the mask/spinner
});
});
angular.element('body').append(e);
This works great in Firefox but no luck in Chrome. I have also tried to use the onload function:
e.onload = function() { //unmask here }
But I did not have any luck there either.
Ideas?
Unfortunately it is not possible to use an iframe's onload event in Chrome if the content is an attachment. This answer may provide you with an idea of how you can work around it.
I hate this, but I couldn't find any other way than checking whether it is still loading or not except by checking at intervals.
var timer = setInterval(function () {
iframe = document.getElementById('iframedownload');
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
// Check if loading is complete
if (iframeDoc.readyState == 'complete' || iframeDoc.readyState == 'interactive') {
loadingOff();
clearInterval(timer);
return;
}
}, 4000);
You can do it in another way:
In the main document:
function iframeLoaded() {
$scope.$apply(function() {
$scope.exporting = false; // this will remove the mask/spinner
});
}
var url = // url to my api
var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
angular.element('body').append(e);
In the iframe document (this is, inside the html of the page referenced by url)
window.onload = function() {
parent.iframeLoaded();
}
This will work if the main page, and the page inside the iframe are in the same domain.
Actually, you can access the parent through:
window.parent
parent
//and, if the parent is the top-level document, and not inside another frame
top
window.top
It's safer to use window.parent since the variables parent and top could be overwritten (usually not intended).
you have to consider 2 points:
1- first of all, if your url has different domain name, it is not possible to do this except when you have access to the other domain to add the Access-Control-Allow-Origin: * header, to fix this go to this link.
2- but if it has the same domain or you have added Access-Control-Allow-Origin: * to the headers of your domain, you can do what you want like this:
var url = // url to my api
var e = angular.element("<iframe style='display:none' src=" + url + "></iframe>");
angular.element(document.body).append(e);
e[0].contentWindow.onload = function() {
$scope.$apply(function() {
$scope.exporting = false; // this will remove the mask/spinner
});
};
I have done this in all kinds of browsers.
I had problems with the iframe taking too long to load. The iframe registered as loaded while the request wasn't handled. I came up with the following solution:
JS
Function:
function iframeReloaded(iframe, callback) {
let state = iframe.contentDocument.readyState;
let checkLoad = setInterval(() => {
if (state !== iframe.contentDocument.readyState) {
if (iframe.contentDocument.readyState === 'complete') {
clearInterval(checkLoad);
callback();
}
state = iframe.contentDocument.readyState;
}
}, 200)
}
Usage:
iframeReloaded(iframe[0], function () {
console.log('Reloaded');
})
JQuery
Function:
$.fn.iframeReloaded = function (callback) {
if (!this.is('iframe')) {
throw new Error('The element is not an iFrame, please provide the correct element');
}
let iframe = this[0];
let state = iframe.contentDocument.readyState;
let checkLoad = setInterval(() => {
if (state !== iframe.contentDocument.readyState) {
if (iframe.contentDocument.readyState === 'complete') {
clearInterval(checkLoad);
callback();
}
state = iframe.contentDocument.readyState;
}
}, 200)
}
Usage:
iframe.iframeReloaded(function () {
console.log('Reloaded');
})
I've just noticed that Chrome is not always firing the load event for the main page so this could have an effect on iframes too as they are basically treated the same way.
Use Dev Tools or the Performance api to check if the load event is being fired at all.
I just checked http://ee.co.uk/ and if you open the console and enter window.performance.timing you'll find the entries for domComplete, loadEventStart and loadEventEnd are 0 - at least at this current time:)
Looks like there is a problem with Chrome here - I've checked it on 2 PCs using the latest version 31.0.1650.63.
Update: checked ee again and load event fired but not on subsequent reloads so this is intermittent and may possibly be related to loading errors on their site. But the load event should fire whatever.
This problem has occurred on 5 or 6 sites for me now in the last day since I noticed my own site monitoring occasionally failed. Only just pinpointed the cause to this. I need some beauty sleep then I'll investigate further when I'm more awake.

Post Message sending to the frame

I have a hidden frame that Accepted message, but I do not have to send by clicking. I'm calling the function that performs and actions, including sending a message. Function settimeout not satisfied by their speed.
this.request = function (requestData) {
$(function () {
dataOrign = requestData;
var iframe = $('iframe#postFrame');
setTimeout(function () {
var parseData = JSON.stringify(requestData);
iframe[0].contentWindow.postMessage({ request: parseData }, '*');
}, 1000);
});
};
How can i send postMessage with minimal time? In this situation?
For most browsers, you can listen for the load event (some example found here) for that iframe to do the postMessage.
E.g.
$('iframe#postFrame').on('load', function(e) {
// do postMessage here
});
However it appears that the setTimeout/setInterval method is unavoidable for older browsers (IE7/8).
UPDATE
If you would like to write it as a function, you could do this:
var request = function(requestData, $iframe) {
if ($iframe.length > 0 && $iframe.get(0).document.readyState === 'completed') {
// do postMessage
}
};
Then you can just use it this way:
request(data, $('iframe#postFrame'));

Categories

Resources