二月 20th, 2010

js和swf交互时不同浏览器中的顺序

JAcld, 前端开发, by army.

接上篇,继续做的测试,有了点新发现。解说测试之前,先说明下用flash检测大写锁定键是否开启的原理。

前提要求是:普通的input文本输入框(无论是text还是password),用户输入还是以html的input组件为基础,并非在其上加入透明的flash输入框或者其它技术平台的组件;无干扰性,用户输入没有任何其它干扰的感觉。

以此,唯一的解决办法就是js结合swf来控制。input的各种事件侦听(获得焦点、失去焦点、按键触发)都只能由js来完成,而对当前键盘状态的检测则交给flash来处理。它们之间有个很大的障碍——flash对当前键盘状态的识别必须首先获得焦点,而我们在input中输入内容的时候焦点却在input上,这成为最大的矛盾

利用js控制页面焦点可以解决这一问题,除了webkit内核的浏览器。我们可以写出如下的伪代码:

oInput.onfocus = function() {
	oSwf.focus(); //flash获得焦点
	oSwf.detect(); //flash进行检测,并根据检测结果调用某个js函数
	setTimeout(function() {
		oInput.focus(); //input重新获得焦点,无干扰用户输入
	}, 0);
}

你可能困扰为何要用setTimeout来使input重新获得焦点,这是为了让用户输入时感觉不到焦点在input和flash之间走了一圈,就好象什么事都没有发生一样。至于为什么一定要用setTimeout,那是为了模拟线程同步,确保重新获得焦点这一操作发生在最后。

就几行代码看上去很简单,实际上有几个隐蔽的信息藏在其中。在flash获得焦点并进行检测之后,input重新获得焦点,试问:这样会不会再次触发onfocus?答案是肯定的,如果不做任何处理的话,这将是个死循环;另外,input还应该侦听onblur,没道理用户在离开输入框之后还在进行提示(除非你能忍受),那么onblur这个侦听函数也会进行不断重复;更恐怖的在下面,我为每一步标上了序号,以表示它们的执行步骤:

function result() {
	//1
	//调用的结果函数,用以让提示区域显示或隐藏
}
oInput.onfocus = function() {
	//2
	oSwf.focus(); //flash获得焦点
	oSwf.detect(); //flash进行检测,并根据检测结果调用结果函数
	//3
	setTimeout(function() {
		//4
		oInput.focus(); //input重新获得焦点,无干扰用户输入
	}, 0);
	//5
}
oInput.onblur = function() {
	//6
	//失去焦点后该怎么做,略
}

猜一猜这个步骤顺序是多少?你永远也答不对,因为即使在trident(ie为代表)和gecko(firefox为代表)两种内核下,它们也不相同(别提webkit了,搞定那个bug先)。

在trident中,input被用户激活后(比如说用鼠标点击),先触发focus,因此2会先执行;接下来flash获得焦点,再调用结果方法,1会被执行;继续回到onfocus方法,顺序走完3和5;onblur被触发,执行一下6;最后是setTimeout那里的4。

很奇怪的现象,因为在2时,input失去焦点而swf获得焦点,此时并没有触发onblur去执行6,反而是先执行的1;之后还有没执行完的3和5;在接下来才能轮到6。由此我们可以观察出一些trident内核的优先级顺序设计的端倪。

再来看看gecko,input被激活后,依然会先触发focus,2第一个执行;接下来也是flash获得焦点,不过在这之前input要先失去焦点,因此先触发了onblur,执行了6;然后flash进行判断,并调用结果方法,执行了1;再往后就类似了,3和5搞定后setTimeout的4最后。

探索完原理后,才有可能继续开发。我也只“刨根问底”到这个程度上,欢迎有兴趣的同学继续“往祖坟上刨”,彻底翻出来赤裸裸的现实。后续如果有新的进展,我会继续把它写出来。:)

Back Top

回复自“js和swf交互时不同浏览器中的顺序”

  1. 没有任何评论。
  1. 没有任何引用。

发表回复

Back Top