JavaScript 高級程序設(shè)計(第16章 HTML5 腳本編程)

第16章 HTML5 腳本編程

1.跨文檔消息傳遞

跨文檔消息傳送(cross-document messaging),有時候簡稱為 XDM,指的是在來自不同域的頁面間傳遞消息。

(1) postMessage()方法接收兩個參數(shù):一條消息和一個表示消息接收方來自哪個域的字符串。

//注意:所有支持 XDM 的瀏覽器也支持 iframe 的 contentWindow 屬性
var iframeWindow = document.getElementById("myframe").contentWindow;
iframeWindow.postMessage("A secret", "http://www.wrox.com");

(2) 接收到 XDM 消息時,會觸發(fā) window 對象的 message 事件。這個事件是以異步形式觸發(fā)的,因此 從發(fā)送消息到接收消息(觸發(fā)接收窗口的 message 事件)可能要經(jīng)過一段時間的延遲。

(3) 觸發(fā) message 事件后,傳遞給 onmessage 處理程序的事件對象包含以下三方面的重要信息。

  1. data:作為 postMessage()第一個參數(shù)傳入的字符串?dāng)?shù)據(jù)。
  2. origin:發(fā)送消息的文檔所在的域,例如"http://www.wrox.com"。
  3. source:發(fā)送消息的文檔的 window 對象的代理。這個代理對象主要用于在發(fā)送上一條消息的 窗口中調(diào)用 postMessage()方法。如果發(fā)送消息的窗口來自同一個域,那這個對象就是 window。
EventUtil.addHandler(window, "message", function(event){
//確保發(fā)送消息的域是已知的域
if (event.origin == "http://www.wrox.com"){
//處理接收到的數(shù)據(jù)
 processMessage(event.data);
////可選:向來源窗口發(fā)送回執(zhí)
event.source.postMessage("Received!", "http://p2p.wrox.com");
}
})

2. 原生拖放

(1) 拖放事件

拖動某元素時,將依次觸發(fā)下列事件:
(1) dragstart
(2) drag
(3) dragend

(1) 按下鼠標(biāo)鍵并開始移動鼠標(biāo)時,會在被拖放的元素上觸發(fā) dragstart 事件。此時光標(biāo)變成“不能放”符號(圓環(huán)中有一條反斜線),表示不能把元素放到自己上面。拖動開始時,可以通過 ondragstart 事件處理程序來運(yùn)行 JavaScript 代碼。
(2) 觸發(fā) dragstart 事件后,隨即會觸發(fā) drag 事件,而且在元素被拖動期間會持續(xù)觸發(fā)該事件。這 個事件與 mousemove 事件相似,在鼠標(biāo)移動過程中,mousemove 事件也會持續(xù)發(fā)生。
(3) 當(dāng)拖動停止時(無 論是把元素放到了有效的放置目標(biāo),還是放到了無效的放置目標(biāo)上),會觸發(fā) dragend 事件。
上述三個事件的目標(biāo)都是被拖動的元素。

當(dāng)某個元素被拖動到一個有效的放置目標(biāo)上時,下列事件會依次發(fā)生:
(1) dragenter
(2) dragover
(3) dragleave 或 drop

(1) 只要有元素被拖動到放置目標(biāo)上,就會觸發(fā) dragenter 事件(類似于 mouseover 事件)。
(2) 緊隨其后的是 dragover 事件,而且在被拖動的元素還在放置目標(biāo)的范圍內(nèi)移動時,就會持續(xù)觸發(fā)該事件。
(3) 如果元素被拖出了放置目標(biāo),dragover 事件不再發(fā)生,但會觸發(fā) dragleave 事件(類似于 mouseout 事件)。如果元素被放到了放置目標(biāo)中,則會觸發(fā) drop 事件而不是 dragleave 事件。
上述三個事件的目標(biāo)都是作為放置目標(biāo)的元素。

(2) 自定義放置目標(biāo)

重寫 dragenter 和 dragover 事件的默認(rèn)行為,可以把任何元素變成有效的放置 目標(biāo)。

var droptarget = document.getElementById("droptarget");
EventUtil.addHandler(droptarget, "dragover", function(event){ 
EventUtil.preventDefault(event);
});
EventUtil.addHandler(droptarget, "dragenter", function(event){ 
EventUtil.preventDefault(event);
});

(3) dataTransfer對象

dataTransfer 對象,它是事件對象的一個屬性,用于從被拖動元素向放置目標(biāo)傳遞字符串格式的數(shù)據(jù)。

  1. dataTransfer 對象有兩個主要方法:getData()setData()。
//設(shè)置和接收文本數(shù)據(jù) 
event.dataTransfer.setData("text", "some text");
var text = event.dataTransfer.getData("text"); 

//設(shè)置和接收 URL
event.dataTransfer.setData("URL", "http://www.wrox.com/"); 
var url = event.dataTransfer.getData("URL");
  1. 保存在 dataTransfer 對象中的數(shù)據(jù)只能在drop 事件處理程序中讀取。如果在 ondrop 處理程序中沒有讀到數(shù)據(jù),那就是 dataTransfer 對象已經(jīng)被 銷毀,數(shù)據(jù)也丟失了。

(4) dropEffect與effectAllowed

dataTransfer 對象的兩個屬性:dropEffect 和 effectAllowed。

1.dropEffect 屬性可以知道被拖動的元素能夠執(zhí)行哪種放置行為。這個屬性有下列 4 個可能的值。

  • "none":不能把拖動的元素放在這里。這是除文本框之外所有元素的默認(rèn)值。
  • "move":應(yīng)該把拖動的元素移動到放置目標(biāo)。
  • "copy":應(yīng)該把拖動的元素復(fù)制到放置目標(biāo)。
  • "link":表示放置目標(biāo)會打開拖動的元素(但拖動的元素必須是一個鏈接,有 URL)。
    要使用 dropEffect 屬性,必須在 ondragenter 事件處理程序中針對放置目標(biāo)來設(shè)置它。
  1. effectAllowed 屬性表示允許拖動元素的哪種 dropEffect,effectAllowed 屬性可能的值如下:
  • "uninitialized":沒有給被拖動的元素設(shè)置任何放置行為。 >* "none":被拖動的元素不能有任何行為。
  • "copy":只允許值為"copy"的 dropEffect。
  • "link":只允許值為"link"的 dropEffect。
  • "move":只允許值為"move"的 dropEffect。
  • "copyLink":允許值為"copy"和"link"的 dropEffect。
  • "copyMove":允許值為"copy"和"move"的 dropEffect。
  • "linkMove":允許值為"link"和"move"的 dropEffect。
  • "all":允許任意 dropEffect。
    必須在 ondragstart 事件處理程序中設(shè)置 effectAllowed 屬性。

(5) 可拖動

draggable 屬性,表 示元素是否可以拖動。圖像和鏈接的 draggable 屬性自動被設(shè)置成了 true,而其他元素這個屬性 的默認(rèn)值都是 false。要想讓其他元素可拖動,或者讓圖像或鏈接不能拖動,都可以設(shè)置這個屬性。 例如:

<!-- 讓這個圖像不可以拖動 -->
<img src="smile.gif" draggable="false" alt="Smiley face">
<!-- 讓這個元素可以拖動 -->
<div draggable="true">...</div>

(6) 其他成員

HTML5 規(guī)范規(guī)定 dataTransfer 對象還應(yīng)該包含下列方法和屬性。

  1. addElement(element):為拖動操作添加一個元素。添加這個元素只影響數(shù)據(jù)(即增加作為拖動源而響應(yīng)回調(diào)的對象),不會影響拖動操作時頁面元素的外觀。在寫作本書時,只有 Firefox 3.5+實現(xiàn)了這個方法。
  2. clearData(format):清除以特定格式保存的數(shù)據(jù)。實現(xiàn)這個方法的瀏覽器有 IE、Fireforx 3.5+、Chrome 和 Safari 4+。
  3. setDragImage(element, x, y):指定一幅圖像,當(dāng)拖動發(fā)生時,顯示在光標(biāo)下方。這個方法接收的三個參數(shù)分別是要顯示的 HTML 元素和光標(biāo)在圖像中的 x、y 坐標(biāo)。其中,HTML 元素 可以是一幅圖像,也可以是其他元素。是圖像則顯示圖像,是其他元素則顯示渲染后的元素。 實現(xiàn)這個方法的瀏覽器有 Firefox 3.5+、Safari 4+和 Chrome。
  4. types:當(dāng)前保存的數(shù)據(jù)類型。這是一個類似數(shù)組的集合,以"text"這樣的字符串形式保存著 數(shù)據(jù)類型。實現(xiàn)這個屬性的瀏覽器有 IE10+、Firefox 3.5+和 Chrome。

3. 媒體元素

<audio>和<video>元素:


<!-- 嵌入視頻 -->
<video src="conference.mpg" id="myVideo">Video player not available.</video>
<!-- 嵌入音頻 -->
<audio src="song.mp3" id="myAudio">Audio player not available.</audio>

(1) 使用這兩個元素時,至少要在標(biāo)簽中包含 src 屬性,指向要加載的媒體文件。
(2) 還可以設(shè)置 width 和 height 屬性以指定視頻播放器的大小,而為 poster 屬性指定圖像的 URI 可以在加載視頻內(nèi)容期間 顯示一幅圖像。
(3) 另外,如果標(biāo)簽中有 controls 屬性,則意味著瀏覽器應(yīng)該顯示 UI 控件,以便用戶直 接操作媒體。
(4) 位于開始和結(jié)束標(biāo)簽之間的任何內(nèi)容都將作為后備內(nèi)容,在瀏覽器不支持這兩個媒體元素 的情況下顯示。

(1) 屬性

(2)事件

(3) 自定義媒體播放器

<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";
    }
});
//定時更新當(dāng)前時間 
setInterval(function(){
    curtime.innerHTML = player.currentTime;
}, 250);

(4) 檢測編解碼器的支持情況

這兩個媒體元素都有一個 canPlayType()方法,該方法接收一種格式/編解碼器字符串,返回 "probably"、"maybe"或""( 空字符串)。

var audio = document.getElementById("audio-player");
//很可能"maybe"
if (audio.canPlayType("audio/mpeg")){
//進(jìn)一步處理
 }
//可能是"probably"
if (audio.canPlayType("audio/ogg; codecs=\"vorbis\"")){
//進(jìn)一步處理 
}

(5) Audio類型

var audio = new Audio("sound.mp3");
EventUtil.addHandler(audio, "canplaythrough", function(event){
        audio.play();
    });

4. 歷史狀態(tài)管理

HTML5 通過更新 history 對象為管理歷史狀態(tài)提供了方便。

1.history.pushState()方法,該方法可以接收三個參數(shù):狀態(tài)對象、新狀態(tài)的標(biāo)題和可選的相對 URL。

history.pushState({name:"Nicholas"}, "Nicholas' page", "nicholas.html");

(1) 執(zhí)行 pushState()方法后,新的狀態(tài)信息就會被加入歷史狀態(tài)棧,而瀏覽器地址欄也會變成新的 相對 URL。但是,瀏覽器并不會真的向服務(wù)器發(fā)送請求,即使?fàn)顟B(tài)改變之后查詢 location.href 也會 返回與地址欄中相同的地址。
(2) 按下“后退” 按鈕,會觸發(fā) window 對象的 popstate 事件。popstate 事件的事件對象有一個 state 屬性,這個 屬性就包含著當(dāng)初以第一個參數(shù)傳遞給 pushState()的狀態(tài)對象。

EventUtil.addHandler(window, "popstate", function(event){
var state = event.state;
if (state){ //第一個頁面加載時 state 為空
        processState(state);
    }
});
  1. 要更新當(dāng)前狀態(tài),可以調(diào)用 replaceState(),傳入的參數(shù)與 pushState()的前兩個參數(shù)相同。 調(diào)用這個方法不會在歷史狀態(tài)棧中創(chuàng)建新狀態(tài),只會重寫當(dāng)前狀態(tài)。
history.replaceState({name:"Greg"}, "Greg's page");
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容