重定向弹出窗口并发布消息 [英] Redirect a Popup and Post Message
问题描述
我陷入了一个问题,即我必须从弹出窗口重定向到另一个域并向其发布消息. 这是场景:-
I am stuck in a problem where i have to redirect from a popup window to a different domain and post a message to it. Here is the scenario :-
- 用户打开一个位于相同域中的新弹出窗口.(例如: http://doamin_one.com )
- 用户在弹出窗口中填写表格,然后单击提交".这应该将窗口重定向到 http://doamin_two.com ,domain_two.com应该通过发布消息接收表单数据. /li>
- User opens a new popup window which stays in same domain.(ex: http://doamin_one.com)
- User fills the form in the popup window and clicks submit. This should redirect the window to http://doamin_two.com and domain_two.com should receive form data via post message.
如果我打开新的弹出窗口并发布消息,但能够接收消息,但在重定向的情况下却不能.这是我的代码:
I am able to receive messages if i open fresh popup and do post message but not in the case of redirection. Here is my code:
function redirect(formData,popup) {
//popup=window ref object
popup.location.href="http://domain_two.com"
popup.postMessage(JSON.stringify(formData),
"http://domain_two.com");
}
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "http://domain_one.com")
return;
let data=event.data;
//....
}
推荐答案
问题代码的一个问题是,在popup
上设置了新的.location.href
之后,无需等待window
at
One issue with the code at the question is that .postMessage()
is called immediately following setting a new .location.href
at popup
without waiting for the load
event of window
at
popup.location.href="http://domain_two.com"
popup.postMessage(JSON.stringify(formData),
"http://domain_two.com");
要获得预期的结果,您可以从原始的window
('index.html')控制过程.每个window.name
都设置为唯一值.当在"http://domain_one.com"
提交<form>
时,可以将生成的FormData
转换为ArrayBuffer
并传输到index.html
,然后将popup
(a.html
)location.href
设置为"http://domain_two.com"
.在b.html
.postMessage()
的load
事件中,window
到index.html
的name
.然后,将FormData
传递给.postMessage()
,其中b.html
获取最初在b.html
提交的FormData
.
To achieve the expected result you can control the process from the original window
('index.html'). Each window.name
is set to a unique value. When the <form>
is submitted at "http://domain_one.com"
the resulting FormData
can be converted to an ArrayBuffer
and transferred to index.html
, then popup
(a.html
) location.href
is set to "http://domain_two.com"
. At load
event of b.html
.postMessage()
the name
of the window
to index.html
. Then the FormData
is passed to .postMessage()
where b.html
gets the FormData
that was originally submitted at b.html
.
(origin
检查可能需要在下面的代码中进行调整.该代码已在plnkr上进行了测试,在该代码中,跨域消息传递的模拟不是1:1,尽管应该提供一种如何实现要求的模式).
(The origin
checks might need to be adjusted at the below code. The code was tested at plnkr, where simulation of cross-domain messaging is not 1:1, though should provide a pattern for how to accomplish the requirement).
index.html(opener
)
index.html (opener
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
// open `popup`
const popup = window.open('a.html');
// create random values to assign to `name` at `a.html` and `b.html`
const [firstName, lastName] = [...Array(2)].map(_ => new Uint32Array(16));
[firstName, lastName].forEach(buffer => window.crypto.getRandomValues(buffer));
const [decoder, encoder] = [new TextDecoder(), new TextEncoder()];
const [first, last] = [firstName, lastName].map(buffer => decoder.decode(buffer));
// set `name` of `popup` (`a.html`) to `first`
popup.name = first;
let data;
window.addEventListener("message", e => {
// check `name` of `source`
if (e.source.name === first) {
console.log(e.source.name);
// store `formData`
data = decoder.decode(e.data);
console.log(e, JSON.parse(decoder.decode(e.data)));
// set `name` of `popup` to `last`
popup.name = last;
// redirect `popup` to `b.html`
popup.location.href = "b.html";
}
// check if `name` of `source` (`b.html`) is `last`
if (e.source.name === last) {
// encode the stored `formData`
let curr = encoder.encode(data);
console.log(e.source.name, e.data);
// transfer `formData` to `b.html`
e.source.postMessage(curr.buffer, e.source.location.href, [curr.buffer]);
// data = void 0;
}
})
</script>
</body>
</html>
a.html(popup
,"http://domain_one.com"
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
a
<form>
<input name="input">
<input type="submit">
</form>
<script>
document.forms[0].onsubmit = e => {
// prevent default `form` submission
e.preventDefault();
// pass `form` to `FormData`
const formData = new FormData(e.target);
// encode `formData` as a `Uint8Array`
const encoded = new TextEncoder().encode(JSON.stringify([...formData.entries()]));
console.log(encoded);
// transfer `encoded` to `opener` (`index.html`)
opener.postMessage(encoded.buffer, opener.location.href, [encoded.buffer]);
}
</script>
</body>
</html>
b.html(popup
,"http://domain_two.com"
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
b
<script>
const decoder = new TextDecoder();
let data;
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
// check `origin` of `event`
if (event.origin !== opener.location.origin)
return;
console.log(event);
// process `formData` from `popup`
data = JSON.parse(decoder.decode(event.data));
// do stuff with `formData`
p.textContent = JSON.stringify(data, null, 2);
}
// wait for `load` event to be dispatched before posting message to `opener`
onload = () => {
opener.postMessage("ok", opener.location.href);
}
</script>
<pre id="p"></pre>
</body>
</html>
这篇关于重定向弹出窗口并发布消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!