Why my postMessage does not working properly? - javascript

I have a index page contains the iframe element, this iframe refer to another DOMAIN page.
and i need to get the data from iframe page, so i applied the postmessage concept.
but it does not working.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Using PostMessage for Cross-Domain Access to an Iframe</title>
<meta name="description" content="Example demonstrates using postMessage to interact with an iframe on another domain and obtain information about its objects and properties." />
<script type="text/javascript">
// check for browser support
if ( window.addEventListener ) {
// when DOM is ready assign button onclick handlers
window.addEventListener('DOMContentLoaded', function() {
// where to send messages with postMessage
var target_origin = 'Myiframe.html';
// get reference to form to attach button onclick handlers
var form = document.getElementById('demoForm');
// get reference to iframe window
var win = document.getElementById('ifrm').contentWindow;
// 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.display.value = 'The iframe\'s height is: ' + ht;
}
// to increment and display counter variable in iframed document
form.elements['button2'].onclick = function() {
win.postMessage( {'task': 'ctr'}, target_origin );
}
// to get value of form element in iframed document
form.elements.button3.onclick = function() {
win.postMessage( {'task': 'val'}, target_origin );
}
// to invoke function in iframed document
form.elements.button4.onclick = function() {
win.postMessage( {'task': 'clear'}, target_origin );
}
}, false);
// message handler
window.addEventListener('message', function (e) {
// check message origin
if ( e.origin === 'Myiframe.html' ) {
var task = e.data['task']; // task received in postMessage
// get reference to demo form
var form = document.getElementById('demoForm');
switch ( task ) { // postMessage tasks
// display counter received in postMessage
case 'ctr' :
form.display.value = 'counter in iframe is: ' + e.data['counter'];
break;
// display text box value received in postMessage
case 'val' :
form.display.value = 'The greeting is: ' + e.data['val'];
break;
case 'clear' :
// nothing to do for this one
break;
//default:
}
}
}, false);
}
</script>
</head>
<body>
<form id="demoForm" action="#">
<p>
<input name="button1" type="button" value="Button 1" />
<input name="button2" type="button" value="Button 2" />
<input name="button3" type="button" value="Button 3" />
<input name="button4" type="button" value="Button 4" />
</p>
<p><input type="text" name="display" size="30" readonly="readonly" /></p>
</form>
<iframe name="ifrm" id="ifrm" src="Myiframe.html"></iframe>
</body>
</html>
Myiframe.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>untitled</title>
<meta name="robots" content="noindex" />
<script type="text/javascript">
// example variable and function for cross-document demo
counter = 0;
function clearGreeting() {
document.forms['iframeDemoForm'].elements['greeting'].value = '';
}
// check for browser support
if ( window.addEventListener ) {
// message handler
window.addEventListener('message', function(e) {
// check message origin
if ( e.origin === 'index.html' ) {
var task = e.data['task']; // task received in postMessage
var msg; // for postMessage reply to e.source
switch ( task ) { // postMessage tasks
// increment counter variable and send
case 'ctr' :
msg = { 'task': 'ctr', 'counter': ++counter };
e.source.postMessage(msg , e.origin );
break;
// send value of entry in text box (validate first)
case 'val' :
var re = /[^-a-zA-Z!,'?\s]/g; // to filter out unwanted characters
var fld = document.forms['iframeDemoForm'].elements['greeting'];
var val = fld.value.replace(re, '');
var msg = {'task': 'val', 'val': val};
e.source.postMessage(msg , e.origin );
break;
// clear text box by calling function
case 'clear' :
clearGreeting();
break;
//default:
}
}
}, false);
}
</script>
</head>
<body>
<h1>Iframe</h1>
<ul>
<li>Button 1 sets iframe style height</li>
<li>Button 2 increments global variable in iframed document</li>
<li>Button 3 transfers Greeting below to text box above iframe</li>
<li>Button 4 clears Greeting text box below (calls function in iframe)</li>
</ul>
<form action="#" id="iframeDemoForm">
<label for="greeting">Enter a Greeting: </label>
<input type="text" name="greeting" id="greeting" value="Hello there!" />
</form>
<script type="text/javascript">
(function() {
// disable submission of all forms on this page
for (var i=0, len=document.forms.length; i<len; i++) {
document.forms[i].onsubmit = function() { return false; };
}
}());
</script>
<p id="demoInfo"><span class="news">Note</span>: This page is part of a tutorial on postMessage and is intended to display in an iframe. Click here to see it in its proper context.</p>
<script type="text/javascript">
// if not in iframe, display link to tutorial
if ( self === top ) {
document.getElementById('demoInfo').style.display = 'block';
}
</script>
</body>
</html>
I appled some operation when buttoon is fired, ut nothing will work except the first button.
what i make mistake and guide me plz

The target origin is not specified properly.
Refer origin specifications here, https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage .
The origin of the window that sent the message at the time postMessage was called. This string is the concatenation of the protocol and "://", the host name if one exists, and ":" followed by a port number if a port is present and differs from the default port for the given protocol. Examples of typical origins are https://example.org (implying port 443), http://example.net (implying port 80), and http://example.com:8080. Note that this origin is not guaranteed to be the current or future origin of that window, which might have been navigated to a different location since postMessage was called.

Related

Trying to make a notepad like script in HTML/JS

Edit: Just confirming: I want what the user typed to be saved so that when he reloads/leaves the webpage and comes back what he wrote earlier is still there.
I tried using cookies but it only put one line of Default(variable) when I reloaded the page. Im trying to get it to work with localStorage now but it sets the textarea to "[object HTMLTextAreaElement]" or blank when I reload. I read that this error can be caused by forgetting to add the .value after getElementById() but I did not make this mistake. I am hosting and testing the webpage on Github(pages). What am I doing wrong? here is the code(ignore the comments also it might not work in jsfiddle bc it localstorage didn't work there for me):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>le epic web page</title>
</head>
<body><!--
= "\n"-->
<textarea id="txt" rows="4" cols="50" oninput="save();"></textarea>
<script>
var Default="P1 Homework: \nP2 Homework: \nP3 Homework: \nP4 Homework: \n";
if(localStorage.getItem("P") == ""){
document.getElementById("txt").value=Default;
localStorage.setItem("P")=Default;
}else{
document.getElementById("txt").value=localStorage.getItem("P");
}
//update cookie (called when typed)
function save(){
var txt=document.getElementById("txt").value;
//txt=txt.replace(/\r\n|\r|\n/g,"</br>");
localStorage.setItem("P",txt);//set cookie to innerHTML of textArea, expires in 1 day
}
//when page closed/reloaded
window.onbeforeunload = function(){
localStorage.setItem("P",txt);//update cookie when page is closed https://stackoverflow.com/a/13443562
}
</script>
</body>
</html>
When you are exiting the page, you are referencing the text element and storing that in localstorage. Since localStorage is a string it converts the html element reference into the text you see.
window.onbeforeunload = function(){
localStorage.setItem("P",txt);
}
You are doing it correctly with save, so just call save with the beforeunload event
window.addEventListener('beforeunload', save);
Another bug in the code is the line
if(localStorage.getItem("P") == ""){
when localStorage is not set, it returns null. So the check would need to be a truthy check ( or you can check for nullv)
if(!localStorage.getItem("P")){
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>le epic web page</title>
</head>
<body>
<textarea id="txt" rows="4" cols="50" oninput="save();"></textarea>
</body>
<script>
const Default =
"P1 Homework: \nP2 Homework: \nP3 Homework: \nP4 Homework: \n";
if (
localStorage.getItem("P") === "" ||
localStorage.getItem("P") === null ||
localStorage.getItem("P") === undefined
) {
localStorage.setItem("P", Default);
} else {
let currentValue = document.getElementById("txt");
currentValue.value = localStorage.getItem("P");
}
function save() {
let txt = document.getElementById("txt").value;
localStorage.setItem("P", txt);
}
window.onbeforeunload = function () {
let txt = document.getElementById("txt").value;
localStorage.setItem("P", txt);
};
</script>
</html>

Problem: Javascript iframe send the postMessage() before iframe completed loading

I have iframe in parent.html. Child.html sending the postMessage('documnent.cookie','*') to the parent window.
The problem is postMessage() send 'null'. postMessage() is triggered before iframe loading is completely done. I have to postMessage() to Parent window only if iframe completely loads the data.
Here is my code: parent.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<body id="Body" style="background-color:Silver">
<iframe id ="CA_FRAME_0" src="http://localhost/ibmcognos/bi/child.html" style="display:none"></iframe>
<script type="text/javascript">
window.addEventListener("message", function (e){
if(e.data == null){
alert('fail');
}else{
alert('sucess');
document.cookie="key=" +e.data + ";expires=0;path=/";
}
}, false);
</script>
<div id="arcContainer" class="arcContainer"></div>
<script type="text/javascript">
ARCPLAN.language = "XXX";
ARCPLAN.application = "lv02";
ARCPLAN.startDocName = "application.apa";
ARCPLAN.arcCgiSite = "http://localhost/.....";
</script>
</body>
</html>
//child.html
<!DOCTYPE html> <html> <head>
<title>COOKIE</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> </head> <body>
<script type="text/javascript">
function getCookie(name) { var arg = name + "="; var alen = arg.length; var clen = document.cookie.length; var i = 0; while(i < clen) { var j = i
+ alen; if(document.cookie.substring(i, j) == arg)
return getCookieVal(j); i = document.cookie.indexOf(" ", i) + 1; if(i == 0)
break; } return null; }
function getCookieVal(offset) { var endstr = document.cookie.indexOf(";", offset); if(endstr == -1) endstr = document.cookie.length; return document.cookie.substring(offset, endstr); }
**parent.postMessage(getCookie("key"), "*");** </script>
**<iframe id ="CA_FRAME" src="http://localhost/ibmcognos/bi/" style="display: none;" ></iframe>** - *this url make the redirect from here and set the cookie, it takes time*
</body> </html>
Kindly provide me some suggestions. Thanks.
In this case we have a webpage A need to load another webpage B through iframe.
page A is loaded. we can add a custom event to listen page B load event.
page A code:
const iframeWin = document.getElementById('h5-iframe').contentWindow;
window.addEventListener(
'message',
(e) => {
const { data } = e;
console.log('receive page load', data);
if (data.pageLoaded) {
iframeWin.postMessage(youdata, '*');
}
},
false,
);
page B code:
window.addEventListener(
'message',
(e) => {
console.log('receive youdata', data);
const { data } = e;
},
false,
);
// after register listen function send this message to page A.
window.parent.postMessage({ pageLoaded: true }, '*');
Add an onload event to your iFrame:
<iframe id ="CA_FRAME" src="http://localhost/ibmcognos/bi/" onload="onCaFrameLoad(this)" style="display: none;"></iframe>
Then you can run JS code only after the frame has completely loaded:
function onCaFrameLoad() {
// wrap your post in this function
};
This way, the code will only run once the frame has finished loading.
PoC:
parent.html
<html>
<body>
PARENT- I get data from child
<br /><br />
<iframe id ="CA_FRAME_0" src="child.html"></iframe>
</body>
</html>
child.html
<html>
<body>
CHILD - I send data to parent - but only after CA_FRAME has loaded
<br /><br />
<iframe id ="CA_FRAME" src="inner.html" onload="onCaFrameLoad(this)"></iframe>
<script>
function onCaFrameLoad() {
alert('iframe has loaded! now you can send data to the parent');
};
</script>
</body>
</html>
inner.html
<html>
<body>
INNER - I load all my content, then the onCaFrameLoad function in child.html runs
<script>
alert('My Name is INNER - I load all my content first');
</script>
</body>
</html>

No transaction response when showReceipt is set to false in Accept Hosted approach (Authorize.net)

I'm trying to integrate authorize.net accept hosted page using the iframe approach in SAP Hybris. The iframe is supposed to send back a response when the showReceipt is set to false according to the documentation. But as of now it seems to be stuck after pay button is clicked.
I have been trying the approach in the documentation. Then tried out the solution in How to implement Authorize.NET Hosted Payments iFrame & Laravel .
This is the hostedOrderPage which is where the iframe displays:
<script type="text/javascript">
$(document).ready(function(){
window.CommunicationHandler = {};
function parseQueryString(str) {
var vars = [];
var arr = str.split('&');
var pair;
for (var i = 0; i < arr.length; i++) {
pair = arr[i].split('=');
vars[pair[0]] = unescape(pair[1]);
}
return vars;
}
window.CommunicationHandler.onReceiveCommunication = function (argument) {
console.log('communication handler enter');
var params = parseQueryString(argument.qstr)
switch(params['action']){
case "cancel" :
console.log('cancel'); break;
case "transactResponse" :
console.log("transaction response received");
console.log(transResponse.totalAmount);
}
}
//send the token
$('#send_hptoken').submit();
});
</script>
<div id="item_container_holder">
<div class="item_container">
<div id="iframe_holder" class="center-block" style="width:90%;max-width: 1000px" data-mediator="payment-form-loader">
<iframe id="load_payment" class="embed-responsive-item" name="load_payment" width="750" height="900" frameborder="0" scrolling="no">
</iframe>
<form:form id="send_hptoken" action="https://test.authorize.net/payment/payment" method="post" target="load_payment">
<input type="hidden" name="token" value="${token}" />
</form:form>
</div>
</div>
</div>
This is the iframecommunicator:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IFrame Communicator</title>
<script type="text/javascript">
function callParentFunction(str) {
if (str && str.length > 0 && window.parent.parent
&& window.parent.parent.CommunicationHandler && window.parent.parent.CommunicationHandler.onReceiveCommunication) {
var referrer = document.referrer;
window.parent.parent.CommunicationHandler.onReceiveCommunication({qstr : str , parent : referrer});
}
}
function receiveMessage(event) {
if (event && event.data) {
callParentFunction(event.data);
}
}
if (window.addEventListener) {
window.addEventListener("message", receiveMessage, false);
} else if (window.attachEvent) {
window.attachEvent("onmessage", receiveMessage);
}
if (window.location.hash && window.location.hash.length > 1) {
callParentFunction(window.location.hash.substring(1));
}
</script>
</head>
<body></body>
</html>
It seems nothing is logged into the console. If there is a response coming it should enter the switch case 'transactResponse' in the hostedOrderPage and log it to the console.
I had a similar problem. Make sure Test Mode is off on the Sandbox account first. Also I believe I had to add Content-Security-Policy for all the related domains plus frame-ancestors 'self' to the Header of the form. I build a string for the local domain and the remote domain, in my case it was test.authorize.net, and add that as a attribute. I build the forms dynamically.
See this link at the Dev forms for more information about the CSC issue.

Silence net::ERR_CONNECTION_REFUSED

Connecting to a non-existent web socket server results in loud errors being logged to the console, usually to the tune of ... net::ERR_CONNECTION_REFUSED.
Anyone have an idea for a hackaround to silence this output? XMLHttpRequest won't work since it yields the same verbose error output if the server is not reachable.
The goal here is to test if the server is available, if it is then connect to it, otherwise use a fallback, and to do this without spamming the console with error output.
Chrome itself is emitting these messages, and there is no way to block them. This is a function of how chrome was built; whenever a ResourceFetcher object attempts to fetch a resource, its response is passed back to its context, and if there's an error, the browser prints it to the console - see here.
Similar question can be found here.
If you'd like, you can use a chrome console filter as this question discusses to block these errors in your console, but there is no way to programmatically block the messages.
I don't know why do you want to prevent this error output. I guess you just want to get rid of them when debugging. So I provide a work around here may be just useful for debugging.
Live demo: http://blackmiaool.com/soa/43012334/boot.html
How to use it?
Open the demo page, click the "boot" button, it will open a new tab. Click the "test" button in the new tab and check the result below. If you want to get a positive result, change the url to wss://echo.websocket.org.
Why?
By using post message, we can make browser tabs communicate with each other. So we can move those error output to a tab that we don't concern.
P.S. You can refresh the target page freely without loosing the connection between it and boot page.
P.P.S You can also use storage event to achieve this.
boot.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>boot page</title>
</head>
<body>
<button onclick="boot()">boot</button>
<p>BTW, you can boot the page without the button if you are willing to allow the "pop-up"</p>
<script>
var targetWindow;
function init() {
targetWindow
}
function boot() {
targetWindow = window.open("target.html");
}
boot();
window.addEventListener('message', function(e) {
var msg = e.data;
var {
action,
url,
origin,
} = msg;
if (action === "testUrl") {
let ws = new WebSocket(url);
ws.addEventListener("error", function() {
targetWindow.postMessage({
action: "urlResult",
url,
data: false,
}, origin);
ws.close();
});
ws.addEventListener("open", function() {
targetWindow.postMessage({
action: "urlResult",
url,
data: true,
}, origin);
ws.close();
});
}
});
</script>
</body>
</html>
target.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>target page</title>
</head>
<body>
<h4>input the url you want to test:</h4>
<textarea type="text" id="input" style="width:300px;height:100px;">
</textarea>
<br>
<div>try <span style="color:red">wss://echo.websocket.org</span> for success result(may be slow)</div>
<button onclick="test()">test</button>
<div id="output"></div>
<script>
var origin = location.origin;
var testUrl = origin.replace(/^https?/, "ws") + "/abcdef"; //not available of course
document.querySelector("#input").value = testUrl;
function output(val) {
document.querySelector("#output").textContent = val;
}
function test() {
if (window.opener) {
window.opener.postMessage({
action: "testUrl",
url: document.querySelector("#input").value,
origin,
}, origin);
} else {
alert("opener is not available");
}
}
window.addEventListener('message', function(e) {
var msg = e.data;
if (msg.action === "urlResult") {
output(`test ${msg.url} result: ${msg.data}`);
}
});
</script>
</body>
</html>

Document.writeln in a New frame not window.open

How can I write new lines on a frame in the same window? For now I have it creating a new Window with window.open. But now I need it in a frame.
I have an html with the two frames(form and result) and I need to write in the second by pressing a button on the first frame.
HTML
<html>
<head>
<title> Create Curriculum</title>
<meta charset="UTF-8"/>
</head>
<frameset rows="50%,50%">
<frame id="form" src="from.html"/>
<frame id="curri" src=""/>
</frameset>
You intercat with the form adding info to the inputs and saving the information. There's also a button that generates the curriculum using the info entered below.
JAVASCRIPT:
function genCurriculum() {
//I want to capture the second frame with id "curri"
var curri = parent.document.getElementById("curri");
curri.document.writeln("<h2>Head of the curriculum...</h2>");
//The others writeln for creating the curriculum
}
I want to know how to write in the frame, not in a new window.
And NOT using Jquery, just pure JavaScript. (Teacher requirement)
Is this jsfiddle what you want to have happen?
Html:
<form>
<input name="nextLine" type="text" />
<button type="button">
<span>Add a line</span>
</button>
</form>
<iframe height="100" width="200"></iframe>
JavaScript:
(function () {
'use strict';
var button, iframe, input;
function addLine (cD, input, val) {
return function () {
var body, line;
body = cD.getElementsByTagName('body')[0]
line = cD.createElement('p');
line.innerText = val.toString() + ': ' + input.value;
body.appendChild(line);
val += 1;
}
}
button = document.getElementsByTagName('button')[0];
iframe = document.getElementsByTagName('iframe')[0];
input = document.getElementsByTagName('input')[0];
button.addEventListener('click', addLine(iframe.contentDocument, input, 0), true);
}());

Categories