《Javascript 高階程式設計(第三版)》筆記0x1D HTML5 指令碼程式設計
目錄
跨文件訊息傳遞
跨文件訊息傳送(cross-document messaging),有時候簡稱為 XDM,指的是在來自不同域的頁面間傳遞訊息。
XDM 的核心是 postMessage()方法。接收兩個引數:一條訊息和一個表示訊息接收方來自哪個域的字串。第二
個引數對保障安全通訊非常重要,可以防止瀏覽器把訊息傳送到不安全的地方。
//注意:所有支援 XDM 的瀏覽器也支援 iframe 的 contentWindow 屬性 var iframeWindow = document.getElementById("myframe").contentWindow; iframeWindow.postMessage("A secret", "http://www.wrox.com");
接收到 XDM 訊息時,會觸發 window 物件的 message 事件。這個事件是以非同步形式觸發的,因此從傳送訊息到接收訊息(觸發接收視窗的 message 事件)可能要經過一段時間的延遲。
EventUtil.addHandler(window, "message", function(event){ //確保傳送訊息的域是已知的域 if (event.origin == "http://www.wrox.com"){ //處理接收到的資料 processMessage(event.data); //可選:向來源視窗傳送回執 event.source.postMessage("Received!", "http://p2p.wrox.com"); } });
原生拖放
拖放事件
拖動某元素時,將依次觸發下列事件:
(1) dragstart
(2) drag
(3) dragend
當某個元素被拖動到一個有效的放置目標上時,下列事件會依次發生:
(1) dragenter
(2) dragover
(3) dragleave 或 drop
自定義放置目標
//假設有一個 ID 為"droptarget"的<div>元素,可以用如下程式碼將它變成一個放置目標
var droptarget = document.getElementById("droptarget");
EventUtil.addHandler(droptarget, "dragover", function(event){
EventUtil.preventDefault(event);
});
EventUtil.addHandler(droptarget, "dragenter", function(event){
EventUtil.preventDefault(event);
});
dataTransfer物件
//在拖放操作時實現資料交換
//設定和接收文字資料
event.dataTransfer.setData("text", "some text");
var text = event.dataTransfer.getData("text");
//設定和接收 URL
event.dataTransfer.setData("URL", "http://www.wrox.com/");
var url = event.dataTransfer.getData("URL");
//跨瀏覽器
var dataTransfer = event.dataTransfer;
//讀取 URL
var url = dataTransfer.getData("url") ||dataTransfer.getData("text/uri-list");
//讀取文字
var text = dataTransfer.getData("Text");
dropEffect與effectAllowed
利用 dataTransfer 物件,可不光是能夠傳輸資料,還能通過它來確定被拖動的元素以及作為放置目標的元素能夠接收什麼操作。為此,需要訪問 dataTransfer 物件的兩個屬性: dropEffect 和effectAllowed。
通過 dropEffect 屬性可以知道被拖動的元素能夠執行哪種放置行為。這個屬性有下列 4個可能的值。
"none":不能把拖動的元素放在這裡。這是除文字框之外所有元素的預設值。
"move":應該把拖動的元素移動到放置目標。
"copy":應該把拖動的元素複製到放置目標。
"link":表示放置目標會開啟拖動的元素(但拖動的元素必須是一個連結,有 URL)。
dropEffect屬性只有搭配 effectAllowed 屬性才有用。effectAllowed屬性表允許拖動元素的哪種 dropEffect,effectAllowed 屬性可能的值如下。
"uninitialized":沒有給被拖動的元素設定任何放置行為。
"none":被拖動的元素不能有任何行為。
"copy":只允許值為"copy"的 dropEffect。
"link":只允許值為"link"的 dropEffect。
"move":只允許值為"move"的 dropEffect。
"copyLink":允許值為"copy"和"link"的 dropEffect。
"copyMove":允許值為"copy"和"move"的 dropEffect。
"linkMove":允許值為"link"和"move"的 dropEffect。
"all":允許任意 dropEffect。
可拖動
文字只有在被選中的情況下才能拖動,而影象和連結在任何時候都可以拖動。讓其他元素可以拖動也是可能的。 HTML5 為所有 HTML 元素規定了一個 draggable 屬性,表示元素是否可以拖動。
<!-- 讓這個影象不可以拖動 -->
<img src="smile.gif" draggable="false" alt="Smiley face">
<!-- 讓這個元素可以拖動 -->
<div draggable="true">...</div>
其他成員
HTML5 規範規定 dataTransfer 物件還應該包含下列方法和屬性。
addElement(element):為拖動操作新增一個元素。新增這個元素隻影響資料(即增加作為拖動源而響應回撥的物件),不會影響拖動操作時頁面元素的外觀。
clearData(format):清除以特定格式儲存的資料。
setDragImage(element, x, y):指定一幅影象,當拖動發生時,顯示在游標下方。這個方法接收的三個引數分別是要顯示的 HTML 元素和游標在影象中的 x、 y 座標。其中, HTML 元素可以是一幅影象,也可以是其他元素。是影象則顯示影象,是其他元素則顯示渲染後的元素。
types:當前儲存的資料型別。這是一個類似陣列的集合,以"text"這樣的字串形式儲存著資料型別。
媒體元素
<!-- 嵌入視訊 -->
<video id="myVideo">
<source src="conference.webm" type="video/webm; codecs='vp8, vorbis'">
<source src="conference.ogv" type="video/ogg; codecs='theora, vorbis'">
<source src="conference.mpg">
Video player not available.
</video>
<!-- 嵌入音訊 -->
<audio id="myAudio">
<source src="song.ogg" type="audio/ogg">
<source src="song.mp3" type="audio/mpeg">
Audio player not available.
</audio>
屬性
事件
自定義媒體播放器
<div class="mediaplayer">
<div class="video">
<video id="player" src="movie.mov" poster="mymovie.jpg"
width="300" height="200">
Video player not available.
</video>
</div>
<div class="controls">
<input type="button" value="Play" id="video-btn">
<span id="curtime">0</span>/<span id="duration">0</span>
</div>
</div>
//取得元素的引用
var player = document.getElementById("player"),
btn = document.getElementById("video-btn"),
curtime = document.getElementById("curtime"),
duration = document.getElementById("duration");
//更新播放時間
duration.innerHTML = player.duration;
//為按鈕新增事件處理程式
EventUtil.addHandler(btn, "click", function(event){
if (player.paused){
player.play();
btn.value = "Pause";
} else {
player.pause();
btn.value = "Play";
}
});
//定時更新當前時間
setInterval(function(){
curtime.innerHTML = player.currentTime;
}, 250);
檢測編解碼器的支援情況
var audio = document.getElementById("audio-player");
//很可能"maybe"
if (audio.canPlayType("audio/mpeg")){
//進一步處理
}
//可能是"probably"
if (audio.canPlayType("audio/ogg; codecs=\"vorbis\"")){
//進一步處理
}
Audio型別
var audio = new Audio("sound.mp3");
EventUtil.addHandler(audio, "canplaythrough", function(event){
audio.play();
});
歷史狀態管理
通過hashchange事件,可以知道 URL 的引數什麼時候發生了變化,即什麼時候該有所反應。而通過狀態管理API,能夠在不載入新頁面的情況下改變瀏覽器的URL。為此,需要使用history.pushState()方法,該方法可以接收三個引數:狀態物件、新狀態的標題和可選的相對 URL。
history.pushState({name:"Nicholas"}, "Nicholas' page", "nicholas.html");
pushState()會建立新的歷史狀態,會發現“後退”按鈕也能使用了。按下“後退”按鈕,會觸發 window 物件的 popstate 事件。popstate 事件的事件物件有一個 state 屬性,這個屬性就包含著當初以第一個引數傳遞給 pushState()的狀態物件。
EventUtil.addHandler(window, "popstate", function(event){
var state = event.state;
if (state){ //第一個頁面載入時 state 為空
processState(state);
}
});
要更新當前狀態,可以呼叫 replaceState(),傳入的引數與 pushState()的前兩個引數相同。呼叫這個方法不會在歷史狀態棧中建立新狀態,只會重寫當前狀態。
history.replaceState({name:"Greg"}, "Greg's page");