JS学习15(HTML5脚本编程)

HTML5不仅定义了新的HTML标记,也定义了很多新的JS API。

跨文档消息传送(XDM)

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

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

接受消息时会触发window对象的message事件,这个事件是以异步形式触发的。其事件处理程序包含如下信息:

  • data:postMessage()的字符串数据
  • origin:发送消息的文档所在的域
  • source:发送消息的文档的window对象的代理,这个代理对象主要用于在发送上一条的窗口中调用postMessage()方法来回复,如果发送消息的窗口来自同一个域,那这个对象就是window。
EventUtil.addHandler(window, "message", function(event){
    alert(event.origin);
    alert(event.data);
    alert(event.source.parentVar);
    event.source.postMessage("Received!", "http://p2p.wrox.com");
});

source大多数情况下只是window对象的代理,并非实际的window对象,除了发送返回消息,不建议访问这个对象的其它属性。
发送的数据后来被改成了可以是任何数据结构,但是并非所有浏览器都实现了,建议还是只传字符串,结构化数据使用JSON.stringify()和JSON.parse()。

原生拖放

在框架间,窗口间,甚至应用间拖放网页元素。

拖放事件

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

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

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

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

自定义放置目标

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

EventUtil.addHandler(dropDiv, "dragover", function(event){
    EventUtil.preventDefault(event);
});
EventUtil.addHandler(dropDiv, "dragenter", function(event){
    EventUtil.preventDefault(event);
});
EventUtil.addHandler(dropDiv, "drop", function(event){
    alert("droped");
});

dataTransfer对象

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

event.dataTransfer.setData("URL", "http://www.wrox.com/");
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时设置

可拖动

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

支持这个属性的有IE 10+ Firefox 4+ Safari 5+ Chrome

其它成员

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

媒体元素

新增标签audio、video标签。

<video src="conference.mpg" id="myVideo">Video player not available.</video>

如果为了编码格式的兼容有多个源:

<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>

属性

这两个元素提供了完善的JS接口:
autoplay
buffered
bufferedBytes
bufferingRate
bufferingThrottled
controls
currentLoop
currentSrc
currentTime
defaultPlaybackRate
duration
ended
loop
muted
networkState
paused
playbackRate
played
readyState
seekable
seeking
src
start
totalBytes
videoHeight
videoWidth
volume

事件

abort
canplay
canplaythrough
canshowcurrentframe
dataunavailable
durationchange
emptied
empty
ended
error
load
loadeddata
loadedmetadata
loadstart
pause
play
playing
progress
ratechange
seeked
seeking
stalled
timeupdate
volumechange
waiting

自定义媒体播放器

由于有如此全面的API,使得自定义媒体播放器成为可行。

<div class="mediaplayer">
    <div class="video">
        <video id="player" src="movie.mov" poster="img/paypal2.png"
               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);

检测编解码器的支持情况

canPlayType()这个方法用来检测,它接收格式,编码字符串返回"probably"、"maybe"、""。

//只传入格式,并不知道编码的情况下,真返回的是maybe,假返回“”
if (audio.canPlayType("audio/mpeg")){
//      
}
//都传入时可能性增加了,真就返回"probably"
if (audio.canPlayType("audio/ogg; codecs=\"vorbis\"")){
//      
}

Audio类型

Audio还有一个原生的JS构造函数,不需要将其加入文档中,直接就可以播放:

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

历史状态管理

在现在的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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容