- From: huangxueqing <huangxueqing@baidu.com>
- Date: Sat, 9 Jun 2012 13:02:00 +0800
- To: '孙东国' <sundongguo@gmail.com>, "'Kang-Hao (Kenny) Lu'" <kennyluck@w3.org>
- CC: 'W3C HTML5 中文興趣小組' <public-html-ig-zh@w3.org>
我从原生webkit windows(对应safari windows版本)介绍浏览器实现的细节。 WebKit对于input element的拖拽处理逻辑是: 假设从input element A拖拽文本data到input element B,从内核事件来说,分别触发了DragEnter、DragOver和Drop,其中重点是Drop事件。 下面分析Drop事件: 1、webkit会判断当前的drag是不是一个move操作,判断的依据是: 1)、drag source和drag target必须属于相同的document; 2)、selection是editable; 3)、selection是range; 4)、当前是否按下了ctrl键(指Windows平台,也就是说,如果在drag的时候按下了ctrl键,只是copy而不是move)。 2、对于move操作,webkit向input element A、B分别dispatch content change event(不是触发js事件),这就会导致input element A的value被清空,而input element B的value为data; 3、webkit会设置新的selection,同时对input element B设置焦点(focus); 4、对input element B设置焦点之前需要检查old focus node(也就是input element A),如果old focus node的value变化了,需要触发change事件(js事件);webkit使用一个成员变量来保存node最后一次触发chenge事件的value,由于A还未触发过change事件,所以A的这个成员是空的,但是,由于第2步导致A的value被清空了,所以webkit认为A的内容没有发生变化(最后一次change事件保存下来的value和当前A的value都是空),这个就会导致A的onchange事件不会被触发; 5、此时焦点落在B上,并且B的onchange事件也不会被触发; 6、当B失去焦点后,如第4步所说,会检查old focus node(也就是B),因为B从未触发过onchange事件,因此最后一次onchange事件保存下来的value是空,而第2步已经给B的value设置了data。所以触发B的onchange事件。 因此:原生的webkit windows版本对于input element A ---------> input element B 1、A ----> B 不触发A的onchange事件,如果B失去焦点,触发B的onchange事件; 2、B ----> A 触发B的onchange事件,如果A失去焦点,触发A的onchange事件; 3、A ----> B 触发A的onchange事件,如果B失去焦点,触发B的onchange事件。 可见1、3的行为不一致,个人认为这是webkit的bug,因为onchange事件的触发依赖于最后一次触发onchange事件设置的value和当前input element的value。 -----邮件原件----- 发件人: 孙东国 [mailto:sundongguo@gmail.com] 发送时间: 2012年6月7日 23:23 收件人: Kang-Hao (Kenny) Lu 抄送: W3C HTML5 中文興趣小組 主题: Re: 文字框裡的文字拖曳問題 配合图来把问题说的清楚些,以下情况在 Firefox 12.0 中文版出现。 --------------------图例如下-------------------- 输入框:[ ] 文字内容:□□□□□○○○○○(使用两种形状以便区分) 选定的部分:□□■■■○○○○○(后第 3 - 5 个字符被选中) -------------------------------------------------- 假设有两个输入框 A 和 B,他们都监听了 change 事件,A 已经有内容。 A [□□□□□ ] B [ ] -------------------------------------------------- 选中 A 中的三个字符。 A [□□■■■ ] B [ ] -------------------------------------------------- 拖拽到 B 中,结果如下。 A [□□■■■ ] B [□□□ ] 此时焦点仍在 A 中,B 的 change 事件未触发。 -------------------------------------------------- 在 B 中再输入两个字符,然后使 B 失去焦点。 A [□□□□□ ] B [□□□○○ ] 这时 B 会触发 change 事件。 -------------------------------------------------- 然后,在 A 中选择中间三个字符。 A [□■■■□ ] B [□□□○○ ] -------------------------------------------------- 再在 B 中选择最后两个字符。 A [□□□□□ ] B [□□□●● ] 注意此时焦点在 B 中,A 看起来没有 selection 了,但实际它还是存在的,稍后可以看到。 -------------------------------------------------- 拖拽 B 选中的内容,往 A 里放。 A [□|□□□|□ ] B [□□□●● ] 你会发现,光标在刚才的 A 的选区范围内是“Can not drop"状态,也就是说只有在选区的两侧,才可以 drop。 在 A 的内容的最前边 drop。 -------------------------------------------------- 结果: A [○○□□ ] B [□□□●● ] 当然,这次 A 的 change 事件也没有被触发。 -------------------------------------------------- IE 系列也有不触发 change 事件的问题,但拖拽行为与 Firefox 不同,问题也没有 Firefox 严重。
Received on Monday, 11 June 2012 07:43:33 UTC