了解HTML5和“她”的 API (二)
Communication(通信)
Cross Document Messaging (跨文档消息通信)
postMessage API origin security(源安全)
chatFrame.contentWindow.postMessage('hello','http://www.a.com/'); window.addEventListener('message',messageHandler,true); function messageHandler(e){ switch(e.origin){ case 'http://www.a.com/': //处理消息 processMessage(e.data); break; defaule: //消息来源无法识别 //忽略消息 } } //消息事件是一个拥有data(数据)和origin(源)属性的DOM事件。 //data属性是发送方传递的实际消息 //origin属性是发送来源
//判断浏览器是否支持postMessage API if(typeof window.postMessage === 'undefined'){ //不支持postMessage } //发送消息 window.postMessage('hello','http://www.a.com/'); chatFrame.contentWindow.postMessage('hello','http://www.a.com/'); //监听 var originWhiteList = ['http://www.a.com/','http://www.b.com/','http://www.c.com/']; function checkWhiteList(origin){ for(var i = 0, n = originWhiteList.length; i < n; i++){ if(origin === originWhiteList[i]) return true; } return false; } function messageHandler(e){ if(checkWhiteList(e.origin)){ //处理消息 processMessage(e.data); }else{ //忽略消息 } }
HTML5定义的MessageEvent接口也是HTML5 WebSockets和HTML5 Web Workers的一部分。
HTML5的通信功能中用于接收消息的API与MessageEvent接口是一致的。
XMLHttpRequest Level 2
跨源XMLHttpRequests
跨源HTTP请求包括一个origin头部,为服务器提供HTTP请求的源信息。
构建基于非同源服务的web应用程序
进度事件(Progress events)
//检测浏览器是否支持XMLHttpRequest level 2 var xhr = new XMLHttpRequest(); if(typeof xhr.withCredentials === 'undefined'){ //支持cross origin XMLHttpRequest }else{ //不支持 } //使用进度事件 xhr.onprogress = function(e){ if(e.lengthComputable){ var ratio = e.loaded / e.total; //处理进度信息 } } xhr.upload.onprogress = function(e){ if(e.lengthComputable){ var ratio = e.loaded / e.total; //处理进度信息 } } xhr.onload = function(e){ //完成 finished } xhr.onerror = function(e){ //错误 error } //跨源请求 xhr.open('GET','http://www.a.com/',true); xhr.send();
Framebusting
//Framebusting技术保证某些内容不被加载到iframe中 if(window !== window.top){ window.top.location = location; } var framebustTimer; var timeout = 3000; if(window !== window.top){ framebustTimer = setTimeout(function(){ window.top.location = location; },timeout); } window.addEventListener('message',function(e){ switch(e.origin){ case trustedFramer: clearTimeout(framebustTimer); break; } },true);
WebSockets(双工通信协议)
WebSockets定义了一个全双工通信信道,通过web上的一个socket即可进行通信。
以前的实时web应用:客户端轮询、服务器推送
commet: 服务器主动以异步方式向客户端推送数据。
轮询:浏览器会定期发送HTTP请求,并随时接收响应。
长轮询:浏览器向服务器发送一个请求,服务器会在一段时间内将其保持在打开状态。
为了建立WebSocket通信,客户端和服务器在初始连接时,将HTTP协议升级到WebSocket协议。
一旦连接建立成功,就可以在全双工通信模式下在客户端和服务器之间来回传送WebSocket消息。
//检测浏览器是否支持WebSocket if(window.WebSocket){ //支持WebSocket }else{ //不支持 } //WebSocket连接 (ws://) //安全的WebSocket连接 (wss://) var url = 'ws://www.a.com:8080/websocket'; var w = new WebSocket(url); w.onopen = function(e){ //打开 发送消息 //var a = new Uint8Array([8,6,5,4,3,2,1]); //w.send(a.buffer); w.send('hello'); } w.binaryType = 'arraybuffer'; w.onmessage = function(e){ //e.data } w.onclose = function(e){ //关闭 } w.onerror = function(e){ //错误 }
Forms(表单)
新的输入型控件
- url
- number
- range
- Date pickers (date, month, week, time, datetime, datetime-local)
- search
- color
新的函数和特性
新的 form 属性:
- autocomplete
- novalidate
新的 input 属性:
- autocomplete
- autofocus
- form
- form overrides (formaction, formenctype, formmethod, formnovalidate, formtarget)
- height 和 width
- list
- min, max 和 step
- multiple
- pattern (regexp)
- placeholder
- required
Drag and Drop(拖放)
开始拖放:单击和拖动鼠标指针,拖动的项或区域叫拖动源(drag source);释放鼠标指针完成操作,到达的项或目标区域被称为放置目标(drop target)。
拖放事件
dragstart //开始拖动页面中某个元素时(在拖动源上调用 设置数据类型 dataTransfer setData) drag //拖动中持续发生的事件(在拖动源上调用) dragenter //拖动跨入页面中的新元素时(新元素上调用) dragleave //拖动离开触发dragenter事件的元素时(新元素上调用) dragover //拖动过程中移动到某个元素上是时(停留的目标调用) drop //释放鼠标时,在当前停留的目标上调用(处理数据 dataTransfer getData) dragend //在拖动源上触发,表示拖动完成
设置元素可拖动
1. 设置元素可拖放 draggable="true" 2. 拖动什么 - ondragstart setData() 3. 放到何处 - ondragover 4. 进行放置 - ondrop getData() function dragstart(e){ //e.effectAllowed = 'copy'; e.dataTransfer.setData('text',e.target.textContent); //e.dataTransfer.setData('text',e.target.id); } function dragover(e){ e.stopPorpagation(); e.preventDefault(); return false; } function drop(e){ e.stopPorpagation(); e.preventDefault(); var data = e.dataTransfer.getData("text"); //data.. return false; }
传输和控制
dataTransfer对象用于获取和设置时间的放置数据
dataTransfer对象的属性和方法: setData(format,data) //在ondragstart中调用,注册一个MIME类型格式的传输项 getData(format) //获取指定类型的注册数据项 types //以数组形式返回所有当前注册的格式 items //返回所有项及其相关格式的列表 files //返回放置相关的所有文件 clearData() //不带参数清空所有注册的数据,给格式参数仅清除特定的注册数据 setDragImage(element,x,y) //使用已存在的图像元素作为拖动图像 addElement(elemnet) //提供一个页面元素 并作为拖动反馈 effectAllowed //设置某种操作可被选用 (none,copy,copyLink,copyMove,link,linkMove,mouv,all) dropEffect //确定当前操作的哪一种类型 或者强制执行某种操作类型
拖放文件
File API能够在网页中异步读取文件,将文件上传至服务器并跟踪上传状态,还可以将文件转换成页面元素。
dataTransfer.files: name //带有扩展名的文件全名 type //文件的MIME类型 size 以字节为单位的文件大小 lastModifiedDate //最后一次修改文件内容的时间戳
在浏览器外拖放文件到浏览器内,不会触发拖放源的dragstart,drag,dragend事件,因为拖放源不是浏览器web内的元素,而是系统文件。
在拖放系统文件时,可以在浏览器web中的放置区域绑定dragenter,dragover,dragleave,drop事件。
var dropfile = function(opts){ this.fileArea = document.getElementById(opts.fileArea); this.textArea = document.getElementById(opts.textArea); this.imageArea = document.getElementById(opts.imageArea); this.init(); }; dropfile.prototype = { init: function(){ this.textArea.innerHTML = '拖放文件区域'; this.bind(); }, bind: function(){ var _this = this; this.fileArea.addEventListener('dragenter',function(e){ _this.dragEnter(e); },false); this.fileArea.addEventListener('dragover',function(e){ _this.dragOver(e); },false); this.fileArea.addEventListener('dragleave',function(e){ _this.dragLeave(e); },false); this.fileArea.addEventListener('drop',function(e){ _this.drop(e) },false); }, dragEnter: function(e){ var files = e.dataTransfer.files; if(files){ this.textArea.innerHTML = '拖动了'+ files.length +'个文件'; }else{ this.textArea.innerHTML = '没有拖动的文件'; } e.stopPropagation(); e.preventDefault(); return false; }, dragOver: function(e){ e.stopPropagation(); e.preventDefault(); return false; }, dragLeave: function(e){ this.textArea.innerHTML = '拖放文件区域'; }, drop: function(e){ e.stopPropagation(); e.preventDefault(); var files = e.dataTransfer.files; this.readFileInfo(files); this.readFileByImage(files); }, readFileByImage: function(files){ var _this = this; [].forEach.call(files,function(file){ if (!!file.type.match(/image/)) { var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function (e) { _this.imageArea.innerHTML += '<img src='+ reader.result +' title="'+ file.name +'" />'; }; } }); }, readFileInfo: function(files){ var message = '<ol>'; [].forEach.call(files,function(file){ message += '<li>'; message += '文件名称:'+ file.name +'
'; message += '文件类型:'+ file.type +'
'; message += '文件大小:'+ file.size +'
'; message += '文件最后修改时间:'+ file.lastModifiedDate +'
'; message += '</li>'; }); message += '</ol>'; this.textArea.innerHTML = message; } } window.onload = function(){ new dropfile({ fileArea: 'fileArea', textArea: 'textArea', imageArea: 'imageArea' }); }