跨文档消息传递(XDM)

跨文档消息传递(cross-document messaging)指的是在来自不同域的页面间传递消息。例如,www.wrox.com域中的页面与位于一个内嵌框架中的p2p.wrox.com域中的页面通信。

XDM的核心是postMessage()方法。对于XDM而言,就是将信息发送至包含在当前页面中的iframe元素,或者由当前页面弹出的窗口。
这个方法接受两个参数,一个消息字符串和一个表示消息接受方来自哪个域的字符串。如果内嵌框架的来源不符合参数,则什么也不做,传递“*”代表匹配所有文档。

  1. var iframeWindow = document.getElementById("myframe").contentWindow;
  2. iframeWindow.postMessage("A secret", "http://www.wrox.com");

原生拖放

拖放事件

通过拖放事件,可以控制拖放相关的各个方面,其中最关键的地方在于确定那里发生了拖放事件,有些事件是在被拖动的元素上产生的,有些是在放置目标上触发的。
拖动某元素时将依次在被拖动的元素上触发下列事件:

  • dragstart:按下鼠标且鼠标移动开始时
  • drag:在元素被拖动的过程中持续触发
  • dragend:当拖动停止时,无论把元素放到有效的放置目标上还是无效的上,都会触发dragend事件。

在拖动的过程中,被拖动的元素的外观是可以改变的,一般浏览器会默认创建一个半透明的副本,这个副本始终跟随光标移动。
当某个元素被放置到有效的放置目标的时候,下列事件会在放置目标会依次发生:

  • dragenter:元素被拖动到放置目标上,就回触发一次dragenter
  • dragover:元素在放置目标上继续被拖动时,会持续触发这个事件
  • dragleave或drop:如果元素又被拖离了目标范围,触发dragleave,dragover事件不再触发,如果直接放置在了目标中,会触发drop事件。

自定义放置目标

所有元素都支持放置目标事件,但有些元素是默认不允许放置的,如果拖动元素经过不允许放置的的元素,是不会触发drop事件的,重写其dragenter和dragover事件可以使其变为可放置的:

  1. EventUtil.addHandler(dropDiv, "dragover", function(event){
  2. EventUtil.preventDefault(event);
  3. });
  4. EventUtil.addHandler(dropDiv, "dragenter", function(event){
  5. EventUtil.preventDefault(event);
  6. });
  7. EventUtil.addHandler(dropDiv, "drop", function(event){
  8. alert("droped");
  9. });

dataTransfer对象

为了在拖放操作时实现数据的交换,引入了dataTransfer对象(25章也有这个示例),这是事件对象的一个属性,这个对象有两个方法:getData()和 setData()。这两个方法都需要一个代表数据类型的参数,在HTML5中,这个是MIME类型,为了向后兼容,还可以是”text”和”URL”,只不过他们其实是被映射为MIME类型”text/plain”和”text/uri-list”。setData还需要一个对应的数据作为参数。在这个对象中,对不同的MIME可以同时存储多个值。
这个对象只在drop事件中读取。
setData在拖动开始时设置,拖动文本,链接或图像时,浏览器会自动调用这个方法保存文字或URL。我们自己也可以在dragstart事件中调用来保存我们自己的数据。
getData在drop事件中调用,获取相关数据。

  1. event.dataTransfer.setData("URL", "http://www.wrox.com/");
  2. var url = dataTransfer.getData("url")||dataTransfer.getData("text/uri-list");

dropEffect与effectAllowed

利用dataTransfer对象,不光能传送数据,还能确定被拖动元素以及作为放置目标的元素能够接收什么操作。
dropEffect属性可以知道被拖动元素能执行哪种放置行为:

  • none
  • move
  • copy
  • link
    这个属性要在开始拖动ondragstart时设置

effectAllowed表示允许拖动元素的哪种dropEffect。

  • uninitialized
  • none
  • copy
  • link
  • move
  • copyLink
  • copyMove
  • linkMove
  • all

这个也要在ondragstart时设置

可拖动

  1. <div draggable="true">...</div>

其他成员

HTML5规范规定dataTransfer对象还有下列方法和属性:

  • addElement(element)
  • clearData(format)
  • setDragImage(element, x, y)
  • types

媒体元素

新增audio /video标签

属性

事件

自定义媒体播放器

其实就是利用pause/play/currentTime等相关属性方法来封装一个播放器

检测编解码器的支持情况

利用canPlayType方法来检测是否支持某种MIME类型的媒体:

if(audio.canPlayType('audio/mpeg')){ //返回'probably'/'maybe'、'' 三个值之一
    //...
}

Audio类型

audio类型有一个元素JS的构造函数Audio,可以在任何时候播放音频, 并且: 通过 new Audio创建的实例不必插入到文档中就可以播放.

历史状态管理

在现在的Web应用中,用户的每次操作并不一定会打开一个新的页面,前进和后退按钮在这里也就失去了作用。HTML5通过更新history对象为管理历史状态提供了方便。

hashchange事件可以知道URL的参数什么时候发生了变化,这时使用history.pushState()可以在不加载新页面的情况下改变浏览器的URL,该方法接收3个参数:状态对象,新状态的标题和可选的相对URL。

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

这个方法执行后,新的状态会被加入历史状态栈,浏览器的地址栏也会变成新的相对URL。但其实并没有像服务器发送数据。其中的第一个参数是用来初始化这个页面的数据用的。

这时后退按钮就能使用了,这时点击后退按钮会触发window对象的popstate事件,这个事件有个属性叫state,就是pushState的第一个参数。回到上一个页面,读取上一个页面的state来初始化上一个页面。比如你回到的是nicholas.html,那你读到的state的name就是Nicholas。
浏览器加载的第一个页面木有状态,其state是null。
还有个方法是replaceState()这个方法接收pushState的前两个参数,重写当前状态,不在历史栈中创建新状态。

history.replaceState({name:"Greg"}, "Greg's page");

这时以后再返回这个页面读到的state.name就是Greg了。
要注意,push进去的每个状态服务器上都要有个真的页面,要不一刷新就404了。
按照逻辑这个pushState应该是在每个web页面刚加载时就push进去,把初始化这个页面的每个数据一起push进去。在当前页面如果有什么即时的修改在下次进入这个页面也该体现的,就使用replaceState。


本章完