为啥 Firefox 对“选择”标签上的“点击”事件的反应与 Webkit 和 IE 不同?

Posted

技术标签:

【中文标题】为啥 Firefox 对“选择”标签上的“点击”事件的反应与 Webkit 和 IE 不同?【英文标题】:Why does Firefox react differently from Webkit and IE to "click" event on "select" tag?为什么 Firefox 对“选择”标签上的“点击”事件的反应与 Webkit 和 IE 不同? 【发布时间】:2012-04-12 08:10:33 【问题描述】:

我意识到 Firefox 处理 <select> 标签上的 click 事件与 Webkit/IE 不同,我不知道为什么或如何解决这种差异。

具体来说,Webkit/IE 将 <select> 上的每个 click 事件视为两者点击“选择”、点击下拉<option> 之一,如下图所示:

第一次点击:

第二次点击:

在 Webkit/IE 中,click 事件只有在两次点击都完成后才会触发。

然而,在Firefox中,第一次点击<select>标签被视为一个click事件,第二次点击选择<option>被视为另一个点击 事件。因此,在 Firefox 中触发了 两个 click 事件,而在 Webkit/IE 中触发了 一个 事件。

现在在代码示例中进行演示,假设我们有:(JSfiddle link)

<select id="sel">
    <option>one</option>
    <option>two</option>
    <option>three</option>​
</select>
<script>
function select() 
    $("#sel").one("click", function(event) 
        console.log('mouse down!');
        $("#sel").one('click', function() 
            console.log('mouse down again!');
            $("#sel").off();
            select();
        );
    );

$(document).ready(function() 
    select();
);
</script>

在 Webkit/IE 中,执行上图中所示的一组操作(第一次)将给出输出:

mouse down!

在 Firefox 中,它会给出:

mouse down!
mouse down again!

为什么会这样,我该如何解决?

编辑:我尝试使用没有 jQuery 的纯 javascript,结果保持不变。

编辑 2:更多上下文,我最初回答了这个问题:onclick on option tag not working on IE and chrome 并为我的回答赢得了赏金。但是,正如操作员后来指出的那样,我的解决方案不适用于 Firefox。我决定深入挖掘来解决这个问题,因此提出了这个问题,我奖励我从该解决方案中获得的 50 赏金。本质上,问题是创建一个选择菜单,该菜单将在进行选择时触发一个事件,即使它是相同的。事实证明,这比预期的要难,如果可能的话,由于不同的浏览器实现。

编辑3:我完全了解onchange,但如果您仔细阅读,这里的问题与onchange 无关。我需要让每个选择触发一个事件即使它们是相同的选择(不会触发onchange

【问题讨论】:

您不只是在寻找 Selected 事件吗? 我在 Win7 x64 上的 Opera、Firefox(最新主干)、Chrome 和 IE 中得到“再次按下鼠标”。 @Shadow2531 您使用的是哪个版本的 Opera? Opera 11.62 仅返回 mouse down,与 OS X 10.7 上的 Safari 5.1.5 和 Chrome 相同 @KayZhu 我在 Win7 x64 上使用 Opera 11.62 Final 和 Opera 12.00.1328。 我实际上在两种浏览器中都“鼠标按下”。 Win 7 x64 上的 FF 11.0 和 Chrome 20.0.1096.1 dev-m。 【参考方案1】:

为什么不使用onchange 事件?

$("#sel").change(function()
    $('body').append("<br/> Option changed");
);

这里是fiddle

但即使选择相同,它也不会触发。解决方法是按照另一个答案中的建议使用像 Chosen 这样的插件。

编辑:从哲学上讲,select 元素不适用于此类功能。 change 事件足以满足与 select 标签相关的大多数用例。您想要的功能,即知道用户是否对元素进行了选择(即使它没有更改),不适合 select 标记的功能模型。如果他/她不想更改选择,从逻辑上讲,没有人会想点击select 元素。

为了满足您的要求,您可以在选择标签之外提供 Go button 并调用与 selectonchange 事件相同的函数 onclick元素。否则给出 hovercard/hover-menu 而不是 select

【讨论】:

onchange 是一个好的开始,但是如果你用键盘选择它会经常触发。也许您的插件将此归功于此。你知道吗? 感谢您的意见。但我的问题不是关于onchange @ aly - 你回答了自己的问题,选择时不会发射一个事件。我的问题只是关于为什么onchange 在不同的浏览器中会出现这种差异以及如何在使用它时让它消失。 由于问题是关于点击事件的,我没有答案。但问题的解决方案是使用正确的事件。这可能是onchange。正如@juzerali 所写。在学术笔记上:ecmascript 中是否准确指定了点击事件? - 唔。这可能是您问题的答案:“未指定”。 @LosManos 恕我直言,我的问题已经明确指出 onchange 根本不是一个选项,因为即使选择是 same,即没有改变。不过,感谢您的领导,我可能应该更早地查看 ECMAScript 规范的定义。我的猜测是你是对的,因为这种行为可能在不同的浏览器中定义模糊,并且解释不同。 似乎这一定是 FF 在 OSx 和 jsFiddle 上的问题。 example on mozilla's site 确实有效,但复制到 jsFiddle 中的相同 html 无效。【参考方案2】:

经过多次实验和搜索,我开始确信,不同浏览器中这种特殊的不同行为很难解决,如果可能的话。

然而,我意识到,我可以从另一方面解决问题,通过使用jQuery UI select menu 或Chosen 创建选择菜单而不是使用&lt;select&gt; 标签。这样click 事件将在&lt;ul&gt;&lt;li&gt; 标签上触发,这在我测试的所有浏览器中都是一致的。

【讨论】:

我认为答案是——由于不同的 JavaScript 引擎和实现——在这些不同的浏览器上,click 事件的行为不会相同,“解决方案”是改变HTML(就像你在这里说的)或更改 JavaScript 事件(就像 juzerali 说的)。 我认为不同之处在于 Chrome,您单击的是虚假选项列表,而在 Firefox 中,您实际上是单击选项元素。你试过if(!$(event.target).is('option')) ...;吗? @Kay Zhu - 我无法在 W7 x64 上重现 FF11 中的问题。但是,您是否尝试过在事件绑定中使用 event.stopPropagation()?我想知道它是否真的是由于选择框的呈现方式而导致的事件冒泡问题。 @kmfk 谢谢,是的,我在实验过程中确实尝试过event.stopPropagation,但也没有用.. 谢谢!我遇到了同样的问题,最终我使用了Chosen,它比普通的select 更好。根据可用性问题,最好使用本机控件,但此时设计对我来说更重要。【参考方案3】:

从本质上讲,问题在于创建一个选择菜单,该菜单将在做出选择时触发一个事件,即使它是相同的。

技术上确实(有点)这样做,但在 FF 中,它会在您单击打开和单击关闭时触发(您实际上可以一键完成,这会产生完全相同的结果在 Safari 和 Firefox 中)。但它同一个事件。 ($('#sel') 上的点击触发器触发);

$("#sel").click(function(event) 
    if($(event.target).is('option')) 
        $(this).closest('select').click();
        return true;
    
    console.log(event.target);
);

我说它“排序”这样做的原因是,如果您从选项卡上选择下拉菜单并使用箭头键,它就无法处理。我认为,如果即使选择了事件相同的项目,您也需要触发事件,您需要以不同的方式进行处理。对于作为开发人员的我来说,如果这是我的项目,那么如果我在一个选择框上选择一个项目而不用触摸鼠标,这是不可接受的(这意味着如果用户访问我的站点并进行交互)有一个没有鼠标的选择框,它不会做他甚至不知道它应该做的事情,可能会使整个事情不起作用,等等)。

我们可以让.click() 工作一整天,但这并不是真正的解决方案,即使我们实现了最初的目标。 (哦,我永远无法让 任何东西在 Chrome 中触发)。

就像我在评论中所说,我认为这与他们如何处理与选择的交互有关。几乎感觉好像 Safari 的选择实际上并没有出现在页面上......它排序创建了这个漂亮的元素,当您单击它时,它的行为和看起来就像一个 &lt;option&gt; 元素列表,但事实并非如此。可能是为什么当您第一次单击它时它也不会触发。当您单击它时,Webkit 不会将其视为“真实”元素,并且只会在您关闭它时触发单击选择,从未与“真实”选项进行过交互。

更改 HTML 可能是唯一的方法(就像 Chosen 所做的那样)。具有讽刺意味的是,某些已选择的元素(看起来像下拉菜单的元素)不能通过 Tab 键来选择……至少不能在它们的 demo page 上选择(参见“标准选择”)。但这至少迫使我点击它,因此它会触发与鼠标相关的事件。

无论如何,我讨厌未解决的问题,但看起来没有真正的解决方案可以让.click() 在所有浏览器中处理&lt;select&gt;,我们应该开始关注替代解决方案。对不起:-(

【讨论】:

以上是关于为啥 Firefox 对“选择”标签上的“点击”事件的反应与 Webkit 和 IE 不同?的主要内容,如果未能解决你的问题,请参考以下文章

我的火狐浏览器为啥打不开左上角的Firefox了,鼠标右键也没反应,怎么回事

火狐浏览器在哪儿设置falsh

火狐浏览器每次打开就跳出“error console”对话框,为啥?

在Mac上的FireFox浏览器中如何设置内容进程限制?

为啥点击 UICollectionViewCell 上的文本会消失?

Firefox中的可点击电话协议标签