第16章 HTML5脚本编程
1.跨文档消息传送(cross-document messaging),简称为 XDM,指的是在来自不同域的页面间传递消息,核心是 postMessage()方法,目的是向另一个地方传递数据,“另一个地方”指的 是包含在当前页面中的<iframe>元素,或者由当前页面弹出的窗口。
2.postMessage()方法接收两个参数:一条消息和一个表示消息接收方来自哪个域的字符串(防止把消息发送到不安全的地方)
第一个参数最好还是只传字符串。如果想传入结构化的数据,最佳选择是先在要传入的数据上调用 JSON.stringify(),通过 postMessage()传入得到的字符串,然 后再在 onmessage 事件处理程序中调用 JSON.parse()。
var iframeWindow = document.getElementById("myframe").contentWindow;
iframeWindow.postMessage("A secret", "http://www.wrox.com");
3.接收到 XDM 消息时,会异步触发 window 对象的 message 事件,传递给 onmessage 处理程序的event包含:
- data:作为 postMessage()第一个参数传入的字符串数据。
- origin:发送消息的文档所在的域,例如"http://www.wrox.com"。
- source:发送消息的文档的 window 对象的代理。(不能通过这个代理对象访问 window 对象的其他任何信息)只通过这个代理调用 postMessage()。
-
接收到消息后验证发送窗口的来源是至关重要,基本的检测模式:
EventUtil.addHandler(window, "message", function(event){ //确保发送消息的域是已知的域 if (event.origin == "http://www.wrox.com"){ //处理接收到的数据 processMessage(event.data); //可选:向来源窗口发送回执 event.source.postMessage("Received!", "http://p2p.wrox.com"); } });
4.拖动某元素时,将依次触发下列事件:目标都是被拖动的元素
(1) dragstart:按下鼠标键并开始移动鼠标时触发。
(2) drag:触发 dragstart 事件后,随即会触发 drag 事件,而且在元素被拖动期间会持续触发该事件。
(3) dragend:当拖动停止时触发。
5.当某个元素被拖动到一个有效的放置目标上时,下列事件会依次发生: 目标都是作为放置目标的元素
(1) dragenter:只要有元素被拖动到放置目标上,就会触发。
(2) dragover:触发 dragstart 事件后,随即会触发dragover 事件,而且在被拖动的元素还在放置目标的范围内移动时持续触发。(拖出了放置目标,dragover 事件不再发生)
(3) dragleave 或 drop:被拖出了放置目标触发dragleave;被放到了放置目标中,则会触发 drop
6.可以把任何元素变成有效的放置 目标,方法是重写 dragenter 和 dragover 事件的默认行为。
var droptarget = document.getElementById("droptarget");
EventUtil.addHandler(droptarget, "dragover", function(event){ EventUtil.preventDefault(event);
});
EventUtil.addHandler(droptarget, "dragenter", function(event){ EventUtil.preventDefault(event);
});
7.dataTransfer 对象用于从被拖动元素向放置目标传递字符串格式的数据,只能在 drop 事件处理程序中读取,有两个主要方法:getData()和 setData(),getData()方法唯一的一个参数,是 一个字符串,表示保存的数据类型,取值为"text"或"URL"。
//设置和接收文本数据
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");
将数据保存为文本和保存为 URL 是有区别的。如果将数据保存为文本格式,那么数据不会得到任何特殊处理。而如果将数据保存为 URL,浏览器会将其当成网页中的链接。换句话说,如果你把它放置 到另一个浏览器窗口中,浏览器就会打开该 URL。
8.访问 dataTransfer 对象的两个属性:dropEffect 和 effectAllowed确定被拖动的元素以及作为放 置目标的元素能够接收什么操作。
通过 dropEffect 属性可以知道被拖动的元素能够执行哪种放置行为。这个属性有下列 4 个可能的值:
要使用 dropEffect 属性,必须在 ondragenter 事件处理程序中针对放置目标来设置它。
- "none":不能把拖动的元素放在这里。这是除文本框之外所有元素的默认值。
- "move":应该把拖动的元素移动到放置目标。
- "copy":应该把拖动的元素复制到放置目标。
- "link":表示放置目标会打开拖动的元素(但拖动的元素必须是一个链接,有 URL)。
dropEffect 属性只有搭配 effectAllowed 属性才有用。
effectAllowed 属性表示允许拖动元素的哪种 dropEffect,effectAllowed 属性可能的值如下:
必须在 ondragstart 事件处理程序中设置 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。
9.默认情况下,图像、链接和文本是可以拖动的,要想让其他元素能否拖动,设置draggable 属性为true/false。
10.HTML5 新增了两个与媒体相关的标签<audio>和<video>,并非所有浏览器都支持所有媒体格式,所以使用一或多个<source>元素指定多个不同的媒体来源。
<!-- 嵌入视频 -->
<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>
11.简单的视频播放器
<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);
12 .canPlayType()方法检测浏览器是否支持某种格式和编解码器。
var audio = document.getElementById("audio-player");
//很可能"maybe"
if (audio.canPlayType("audio/mpeg")){
//进一步处理 }
//可能是"probably"
if (audio.canPlayType("audio/ogg; codecs=\"vorbis\"")){
//进一步处理 }
13. <audio>元素还有一个原生的 JavaScript 构造函数 Audio,可以在任何时候播放音频。
var audio = new Audio("sound.mp3");
EventUtil.addHandler(audio, "canplaythrough", function(event){
audio.play();
});
14.历史状态管理:
hashchange 事件可以知道 URL 的参数发生了变化(第13章提及)
- 使用 history.pushState()方法能够在不加载新页面的情况下改变浏览器的 URL,方法接收三个参数:状态对象(尽可能提供初始化页面所需的各种信息)、新状态的标题和可选的相对 URL 。执行 pushState()方法后,新的状态信息就会被加入历史状态栈,而浏览器地址栏也会变成新的相对URL。但是,浏览器并不会真的向服务器发送请求。
请确保使用 pushState()创造的每一个“假” URL,在 Web 服务器上都有一个真的、实际存在的 URL 与之对应。否则,单击“刷 新”按钮会导致 404 错误。
history.pushState({name:"Nicholas"}, "Nicholas' page", "nicholas.html");
- 按下“后退” 按钮,会触发 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");