iT邦幫忙

DAY 18
8

HTML5試試看系列 第 18

[HTML5試試看-18] 溝通 - cross document message

HTML5為了在不同情境下使用,設計了幾種溝通的方式,包含文件之間溝通的cross-document messaging、channel messaging,還有與伺服器溝通的server sent event以及web socket。今天先試試看最簡單的cross-document messaging。
先看一下所有溝通機制會使用的事件定義:

 interface MessageEvent : Event {
   readonly attribute any data;
   readonly attribute DOMString origin;
   readonly attribute DOMString lastEventId;
   readonly attribute WindowProxy source;
   readonly attribute MessagePortArray ports;
   void initMessageEvent(in DOMString typeArg, 
                         in boolean canBubbleArg, 
                         in boolean cancelableArg, 
                         in any dataArg, 
                         in DOMString  originArg, 
                         in DOMString lastEventIdArg, 
                         in WindowProxy sourceArg, 
                         in MessagePortArray portsArg);
 };

據說只有MessageEvent.data這個屬性是所有不同溝通方式會共用的,用來接收訊息。對於cross-document messaging,會用到的還有:

  1. MessageEvent.origin(channel message也會用到)
  2. MessageEvent.source
  3. MessageEvent.ports(channel message也會用到)

不過光這樣看不出要怎麼用,先寫個小程式來試試看:

<html lang="zh-TW">

<meta http-equiv="Content-Type" content="text/html; charset=utf8">
<style>
	div {
		border: solid 2px #336699;
		margin: 10px;
		padding: 5px;
		border-radius: 5px;
		vertical-align: top;
		text-align: center;
		display: inline-block;
	}
	.container {
		background: #88BBFF;
		width: 520px;
	}
	#msg {
		background: #99CCFF;
		border: dotted 1px #4477AA;
		width: 480px;
		margin: 0px;
		text-align: left;
		font-size: 12px;
	}
</style>
<script>
function init() {
	var form = document.getElementById('form1');
	var input = document.getElementById('input');
	var target = document.getElementById('target');
	form.onsubmit = function(){
		try {
			target.contentWindow.postMessage(input.value, 'http://www.fillano.idv.tw');
		} catch(e) {
			alert(e);
		} finally {
			input.value = '';
			input.focus();
			return false;
		}
	};
	window.addEventListener('message', function(e) {
		var str = '<li>';
		str += '[' + e.origin + ']';
		str += '[' + e.source + ']';
		str += '[' + e.ports + ']';
		str += ' : ';
		str += e.data;
		str += '</li>\n';
		document.getElementById('msg').innerHTML += str;
	}, false);
}
</script>


<div><div class="container"><form id="form1"><input type="text" size="30" id="input"></form></div><br>
<div class="container">Returned Messages.<div id="msg"></div></div></div>
<iframe src="http://www.fillano.idv.tw/test631a.html" id="target" width="520" height="600" scrolling="no" frameborder="1"></iframe>


<script>
init();
</script>

然後iframe裡面的test631a.html:

<html lang="zh-TW">

<meta http-equiv="Content-Type" content="text/html; charset=utf8">
<style>
	div {
		border: solid 2px #336699;
		margin: 10px;
		padding: 5px;
		border-radius: 5px;
		vertical-align: top;
		text-align: center;
		display: inline-block;
	}
	#container {
		background: #88BBFF;
		width: 480px;
	}
	#panel {
		background: #99CCFF;
		border: dotted 1px #4477AA;
		width: 90%;
		margin: 0px;
		text-align: left;
		font-size: 12px;
	}
</style>


<div id="container">Received messages.<div id="panel"></div></div>


<script>
window.addEventListener('message', function(e) {
	var str = '<li>';
	str += '[' + e.origin + ']';
	str += '[' + e.source + ']';
	str += '[' + e.ports + ']';
	str += ' : ';
	str += e.data;
	str += '</li>\n';
	document.getElementById('panel').innerHTML += str;
	e.source.postMessage('got it at '+(new Date())+'.', e.origin);
}, false);
</script>

測試很簡單,從input輸入文字,就會顯示在iframe,然後回傳"got it"及時間。目前最新的瀏覽器都可以支援,包括Firefox4, Chrome7, IE9, Opera, Safari...開心

利用這樣的方式,就可以做到跟iframe裡面的網頁做雙向半雙工的訊息傳遞。(標準是這樣說,不過要測試他是不是半雙工可能會有點困難)另外,有一些點需要注意:

  1. postMessage的第二個參數,必須跟收訊息的網頁網址domain匹配,否則訊息收不到
  2. cross document可以跨domain傳送訊息,所以為了安全,最好在接收/傳送時利用MessageEvent.origin來確定送出者的domain是否符合預期
  3. postMessage的第三個參數,可以用來傳送MessagePort,這是讓兩個不同網頁可以用Channel Message溝通的方法...詳情就等明天試試Channel Messaging再說囉。
  4. 使用postMessage時必須先取得window物件,所以使用上是有限制的。因為需要用window.open或是iframe才能取得另外一個文件的window物件

參賽文章


上一篇
[HTML5試試看-17] 互動機制 - drag and drop 與 File API
下一篇
[HTML5試試看-19] 溝通 - channel message
系列文
HTML5試試看30

尚未有邦友留言

立即登入留言