触屏RIA开发之为zepto升级,模拟用户行为

首先,老习惯,先介绍背景:

  在开发html5的音乐播放RIA时,在Ios的safari里本小姐发现了一个诡异的问题:

1 //代码前提是引用了zepto.js
2 var audio = $("audio")[0];
3 audio.src="test.mp3";
4 audio.bind("tap",function(e){
5         audio.play();
6 })

  zepto的tap居然失效了!!!怎么回事呢?加了很多断点后,发现tap事件并没有失效,而是在tap的回调函数里的audio.play()失效了,android的chrome啊,uc啊,还有PC端都是没有问题的,唯独safari,T^T,郁闷啊。。。。仔细研究了zepto的源码,发现zepto中所有事件,都运用了跳出线程的setTimeout函数。那么,就有了如下猜测:

  由于有setTimeout的关系,浏览器将这个事件的触发看做了js代码行为,而不是用户行为,而对于HTML5的媒体标签(<audio><video>)safari有诡异的安全限制:不是用户的直接行为环境下,不能调用媒体标签的API。如果这个假设成立,那么直接绑定touchend事件,audio.play()应该可以执行。

     接下来的验证,证明了本小姐的推测~那么,怎么解决这个问题呢。

     那就是,为zepto升级,模拟用户行为:

  大概思路就是,当用户触发一个事件的时候,我们创建一个dom对象,并为他绑定个事件,并模拟用户的方式触发这个事件。

  铛铛铛铛~~~~代码如下:

 1 function simuEvent(callback) {
 2     var a = document.createElement('A');
 3     a.on('click',function handler(e) {
 4         this.off('click', handler);
 5         callback();
 6     }, false);
 7     var e = document.createEvent('MouseEvent');
 8     e.initMouseEvent('click', true, true, this, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
 9     a.dispatchEvent(e);
10 }

  那么如何使用呢?

  如果需要绑定和媒体标签的API有关的事件,在绑定事件时,回调函数中使用就可以了,最初的代码修改如下:

1 //代码前提是引用了zepto.js
2 var audio = $("audio")[0];
3 audio.src="test.mp3";
4 audio.bind("tap",function(e){
5          simuEvent(function(e2){ 
6                audio.play(); 
7           });
8 })

这下,就可以绕过safari诡异的安全机制了,欺骗了傻乎乎的浏览器,哈哈。

posted @ 2012-08-31 19:30  毛绒猫猫  阅读(1310)  评论(0编辑  收藏  举报