1、跨文档消息传递
- 跨文档消息传送(cross-documentmessaging),有时候简称为XDM,指的是在来自不同域的页面间传递消息。
- XDM 的核心是postMessage()方法。
- postMessage()方法接收两个参数:一条消息和一个表示消息接收方来自哪个域的字符串。第二个参数对保障安全通信非常重要,可以防止浏览器把消息发送到不安全的地方。
//注意:所有支持XDM 的浏览器也支持iframe 的contentWindow 属性
var iframeWindow = document.getElementById("myframe").contentWindow;
iframeWindow.postMessage("A secret", "http://www.wrox.com");
//如果来源匹配,消息会传递到内嵌框架中;否则,postMessage()什么也不做。
- 接收到XDM消息时,会触发window对象的message事件。这个事件是以异步形式触发的,因此从发送消息到接收消息(触发接收窗口的message事件)可能要经过一段时间的延迟。
- 触发message事件后,传递给onmessage处理程序的事件对象包含以下三方面的重要信息。
(1)data:作为postMessage()第一个参数传入的字符串数据。
(2)origin:发送消息的文档所在的域
(3)source:发送消息的文档的window对象的代理。这个代理对象主要用于在发送上一条消息的窗口中调用postMessage()方法。如果发送消息的窗口来自同一个域,那这个对象就是window。 - 在onmessage 处理程序中检测消息来源可以确保传入的消息来自已知的页面。基本的检测模式如下。
EventUtil.addHandler(window, "message", function(event){
//确保发送消息的域是已知的域
if (event.origin == "http://www.wrox.com"){
//处理接收到的数据
processMessage(event.data);
//可选:向来源窗口发送回执
event.source.postMessage("Received!", "http://p2p.wrox.com");
}
});
2、原生拖放
- HTML5 以IE 的实例为基础制定了拖放规范。Firefox 3.5、Safari 3+和Chrome 也根据HTML5 规范实现了原生拖放功能。
2.1 拖放事件
- 拖动某元素时,将依次触发下列事件。
(1) dragstart
(2) drag
(3) dragend - 当某个元素被拖动到一个有效的放置目标上时,下列事件会依次发生:
(1) dragenter
(2) dragover
(3) dragleave 或drop
2.2 自定义放置目标
- 虽然所有元素都支持放置目标事件,但这些元素默认是不允许放置的。如果拖动元素经过不允许放置的元素,无论用户如何操作,都不会发生drop 事件。
- 可以把任何元素变成有效的放置目标,方法是重写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);
});
- 在Firefox 3.5+中,放置事件的默认行为是打开被放到放置目标上的URL。
- 为了让Firefox 支持正常的拖放,还要取消drop 事件的默认行为,阻止它打开URL。
EventUtil.addHandler(droptarget, "drop", function(event){
EventUtil.preventDefault(event);
});
2.3 dataTransfer 对象
- dataTransfer 对象,它是事件对象的一个属性,用于从被拖动元素向放置目标传递字符串格式的数据。
- 因为它是事件对象的属性,所以只能在拖放事件的事件处理程序中访问dataTransfer 对象。
- 在事件处理程序中,可以使用这个对象的属性和方法来完善拖放功能。
- dataTransfer 对象有两个主要方法:getData()和setData()。
//设置和接收文本数据
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");
- 为了更好地在跨浏览器的情况下从dataTransfer 对象取得数据,最好在取得URL 数据时检测两个值,而在取得文本数据时使用"Text"。
var dataTransfer = event.dataTransfer;
//读取URL
var url = dataTransfer.getData("url") ||dataTransfer.getData("text/uri-list");
//读取文本
var text = dataTransfer.getData("Text");
2.4 dropEffect 和 effectAllowed
通过dropEffect 属性可以知道被拖动的元素能够执行哪种放置行为。这个属性有下列4个可能的值。
(1) "none":不能把拖动的元素放在这里。这是除文本框之外所有元素的默认值。
(2) "move":应该把拖动的元素移动到放置目标。
(3) "copy":应该把拖动的元素复制到放置目标。
(4) "link":表示放置目标会打开拖动的元素(但拖动的元素必须是一个链接,有URL)。要使用dropEffect属性,必须在ondragenter事件处理程序中针对放置目标来设置它。
dropEffect 属性只有搭配effectAllowed 属性才有用。
effectAllowed 属性表示允许拖动元素的哪种dropEffect,effectAllowed 属性可能的值如下。
(1) "uninitialized":没有给被拖动的元素设置任何放置行为。
(2) "none":被拖动的元素不能有任何行为。
(3) "copy":只允许值为"copy"的dropEffect。
(4) "link":只允许值为"link"的dropEffect。
(5) "move":只允许值为"move"的dropEffect。
(6) "copyLink":允许值为"copy"和"link"的dropEffect。
(7) "copyMove":允许值为"copy"和"move"的dropEffect。
(8) "linkMove":允许值为"link"和"move"的dropEffect。
(9) "all":允许任意dropEffect。必须在ondragstart 事件处理程序中设置effectAllowed 属性。
2.5 可拖动
- HTML5 为所有HTML 元素规定了一个draggable 属性,表示元素是否可以拖动
- 图像和链接的draggable属性自动被设置成了true,而其他元素这个属性的默认值都是false。
...
2.6 其他成员
- HTML5 规范规定dataTransfer 对象还应该包含下列方法和属性。
(1) addElement(element):为拖动操作添加一个元素。添加这个元素只影响数据(即增加作为拖动源而响应回调的对象),不会影响拖动操作时页面元素的外观。
(2) clearData(format):清除以特定格式保存的数据
(3) setDragImage(element, x, y):指定一幅图像,当拖动发生时,显示在光标下方。
(4) types:当前保存的数据类型。这是一个类似数组的集合,以"text"这样的字符串形式保存着数据类型。
3、媒体元素
- HTML5 新增了两个与媒体相关的标签
和
。,让开发人员不必依赖任何插件就能在网页中嵌入跨浏览器的音频和视频内容。
- 因为并非所有浏览器都支持所有媒体格式,所以可以指定多个不同的媒体来源。为此,不用在标签中指定src 属性,而是要像下面这样使用一或多个
元素。
3.1 属性
-
和
元素都提供了完善的JavaScript 接口。
- 下表列出了这两个元素共有的属性,通过这些属性可以知道媒体的当前状态。
属性 | 数据类型 | 说明 |
---|---|---|
autoplay | 布尔值 | 取得或设置autoplay标志 |
buffered | 时间范围 | 表示已下载的缓冲的时间范围的对象 |
bufferedBytes | 字节范围 | 表示已下载的缓冲的字节范围的对象 |
bufferingRate | 整数 | 下载过程中每秒钟平均接收到的位数 |
bufferingThrottled | 布尔值 | 表示浏览器是否对缓冲进行了节流 |
controls | 布尔值 | 取得或设置controls属性,用于显示或隐藏浏览器内置的控件 |
currentLoop | 整数 | 媒体文件已经循环的次数 |
currentSrc | 字符串 | 当前播放的媒体文件的URL |
currentTime | 浮点数 | 已经播放的秒数 |
defaultPlaybackRate | 浮点数 | 取得或设置默认的播放速度。默认值为1.0秒 |
duration | 浮点数 | 媒体的总播放时间(秒数) |
ended | 布尔值 | 表示媒体文件是否播放完成 |
loop | 布尔值 | 取得或设置媒体文件在播放完成后是否再从头开始播放 |
muted | 布尔值 | 取得或设置媒体文件是否静音 |
networkState | 整数 | 表示当前媒体的网络连接状态:0表示空,1表示正在加载,2表示正在加载元数据,3表示已经加载了第一帧,4表示加载完成 |
paused | 布尔值 | 表示播放器是否暂停 |
playbackRate | 浮点数 | 取得或设置当前的播放速度 |
played | 时间范围 | 到目前为止已经播放的时间范围 |
readyState | 整数 | 表示媒体是否已经就绪(可以播放了)。0表示数据不可用,1表示可以显示当前帧,2表示可以开始播放,3表示媒体可以从头到尾播放 |
seekable | 时间范围 | 可以搜索的时间范围 |
seeking | 布尔值 | 表示播放器是否正移动到媒体文件中的新位置 |
src | 字符串 | 媒体文件的来源。任何时候都可以重写这个属性 |
start | 浮点数 | 取得或设置媒体文件中开始播放的位置,以秒表示 |
totalBytes | 整数 | 当前资源所需的总字节数 |
videoHeight | 整数 | 返回视频(不一定是元素)的高度。只适用于 |
videoWidth | 整数 | 返回视频(不一定是元素)的宽度。只适用于 |
volume | 浮点数 | 取得或设置当前音量,值为0.0到1.0 |
3.2 事件
- 除了大量属性之外,这两个媒体元素还可以触发很多事件。下表列出了媒体元素相关的事件。
事件 | 触发时机 |
---|---|
abort | 下载中断 |
canplay | 可以播放时;readyState值为2 |
canplaythrough | 播放可继续,而且应该不会中断;readyState值为3 |
canshowcurrentframe | 当前帧已经下载完成;readyState值为1 |
dataunavailable | 因为没有数据而不能播放;readyState值为0 |
durationchange | duration属性的值改变 |
emptied | 网络连接关闭 |
empty | 发生错误阻止了媒体下载 |
ended | 媒体已播放到末尾,播放停止 |
error | 下载期间发生网络错误 |
loadeddata | 媒体的第一帧已加载完成 |
loadedmetadata | 媒体的元数据已加载完成 |
loadstart | 下载已开始 |
pause | 播放已暂停 |
play | 媒体已接收到指令开始播放 |
playing | 媒体已实际开始播放 |
progress | 正在下载 |
ratechange | 播放媒体的速度改变 |
seeked | 搜索结束 |
seeking | 正移动到新位置 |
stalled | 浏览器尝试下载,但未接收到数据 |
timeupdate | currentTime被以不合理或意外的方式更新 |
volumechange | volume属性值或muted属性值已改变 |
waiting | 播放暂停,等待下载更多数据 |
3.3 自定义媒体播放器
- 使用
- 组合使用属性、事件和这两个方法,很容易创建一个自定义的媒体播放器。
0/0
//取得元素的引用
var player = document.getElementById("player"),
btn = document.getElementById("video-btn"),
curtime = document.getElementById("curtime"),
duration = document.getElementById("duration");
//更新播放时间
duration.innerHTML = player.duration;
//为按钮添加事件处理程序
var EventUtil = {
addHander:function(element,type,handler)
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(element.attachEvent){
element.attachEvent("on"+type,handler,false);
}else{
element["on"+type] = handler;
}
};
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);
3.4 检测编码解码支持情况
- 两个媒体元素都有一个canPlayType()方法,该方法接收一种格式/编解码器字符串,返回"probably"、"maybe"或""( 空字符串)。
var audio = document.getElementById("audio-player");
//很可能"maybe"
if (audio.canPlayType("audio/mpeg")){
//进一步处理
}
//可能是"probably"
if (audio.canPlayType("audio/ogg; codecs=\"vorbis\"")){
3.5 Audio 类型
-
元素还有一个原生的JavaScript构造函数Audio,可以在任何时候播放音频。
- Audio 与Image 很相似,但Audio 不用像Image那样必须插入到文档中。只要创建一
个新实例,并传入音频源文件即可。
var audio = new Audio("sound.mp3");
EventUtil.addHandler(audio, "canplaythrough", function(event){
audio.play();
});
- 创建新的Audio 实例即可开始下载指定的文件。下载完成后,调用play()就可以播放音频。
4、历史状态管理
- HTML5 新增了hashchange事件,以便在URL的参数列表(及URL中“#”号后面的所有字符串)发生变化时通知开发人员。
- HTML5 通过更新history 对象为管理历史状态提供了方便
- 通过hashchange 事件,可以知道URL的参数什么时候发生了变化,即什么时候该有所反应。
- 通过状态管理API , 能够在不加载新页面的情况下改变浏览器的URL 。
- 使用history.pushState()方法,该方法可以接收三个参数:状态对象、新状态的标题和可选的相对URL。
history.pushState({name:"Nicholas"}, "Nicholas' page", "nicholas.html");
- 要更新当前状态,可以调用replaceState(),传入的参数与pushState()的前两个参数相同。调用这个方法不会在历史状态栈中创建新状态,只会重写当前状态。
history.replaceState({name:"Greg"}, "Greg's page");