【问题标题】:HTML - Click on button causes list to scroll on top for unknown reasonsHTML - 单击按钮会导致列表由于未知原因滚动到顶部
【发布时间】:2018-05-03 16:34:10
【问题描述】:

我正在使用 Tampermonkey 向 Unity Documentation 添加一些自定义按钮。

如果我使用的是 html <button>,我注意到一个奇怪的问题。每次单击按钮时,滚动列表都会滚动到顶部,并且代码仅在第二次单击时执行。


但是,如果我将 <button> 替换为 <div>,那么一切正常。


为什么<button> 的行为如此怪异?

下面是tampermonkey 复制脚本。

// ==UserScript==
// @name         Unity Documentation (bugtest)
// @namespace    https://docs.unity3d.com
// @version      1.0
// @description  test
// @author       Edward Black
// @match        *://docs.unity3d.com/*
// @grant        GM_addStyle
// ==/UserScript==

GM_addStyle('.confirmBox { z-index: 100; width: 275px; background-color: greenyellow; border: 1px solid black; }');
GM_addStyle('.confirmBoxButtons { margin-top: 5px; }');
GM_addStyle('.confirmBoxClose { position: absolute; height: 20px; width: 20px; background-color: white; color:black; border: 0.5px solid black; text-align: center; right: 0px; }');
GM_addStyle('.confirmBoxClose:hover { background-color: black; color:white; cursor: pointer; }');
GM_addStyle('.confirmBoxBtn { background-color: white; color:black; width: 100px; border: 1px solid black; }');
GM_addStyle('.confirmBoxBtn:hover { background-color: black; color:white; cursor: pointer; }');

$(document).ready(function() {

    setTimeout(function() {
        prepareCustomContextMenue();
        $("div.mCSB_container").delegate("#theButton", "click", function() {
            alert("Hello from Button");
        });
        $("div.mCSB_container").delegate("#theDiv", "click", function() {
            alert("Hello from Div");
        });
        $("div.mCSB_container").delegate(".confirmBoxClose", "click", function() {
            $(".confirmBox").remove();
        });

    }, 4000);


});

function prepareCustomContextMenue()
{
    $("div.mCSB_container").find("a").each(function(j, obj) {

        $(obj).on("contextmenu", function(){
            return false;
        });
        $(obj).on("mousedown", function(e){
            if( e.button == 2 ) {

                console.log('Right mouse button!');
                showConfirmBox(this);

                return false;
            }
            return true;
        });
    });
}

function showConfirmBox(container)
{
    $(".confirmBox").remove();

    var elm = '<li><div class="confirmBox">'+
                  '<div class="confirmBoxClose">x</div>' +

                  '<div class="confirmBoxButtons">' +
                      '<button id="theButton" class="confirmBoxBtn"> This is a button </button>' +
                      '<div id="theDiv" class="confirmBoxBtn"> This is a div </div>' +
                  '</div>' +
              '</div></li>';

    $parent = $(container).parent();
    $(elm).appendTo($parent);
}

说明


等到网站加载完成(大约 4 秒,直到网站加载指示器消失)然后右键单击左侧滚动列表中的链接,该链接应尽可能向下(这样您可以看到单击按钮后列表实际上是向上滚动的)。 现在应该会出现一个容器:

现在单击名为This is a button&lt;button&gt; 并注意滚动列表滚动到顶部并且按钮中的代码未执行(应显示警报)。再次按下按钮,注意代码现在已执行,并且在警报上按下 Ok 后,滚动列表再次滚动到顶部。

接下来单击名为This is a div&lt;div&gt; 并注意一切正常。

【问题讨论】:

    标签: javascript jquery html greasemonkey tampermonkey


    【解决方案1】:

    按钮默认会提交页面,导致刷新。

    <button id="theButton" class="confirmBoxBtn"> This is a button </button>
    

    按钮的默认“类型”是“提交”,它会自行发布。将按钮“类型”更新为“按钮”。

    <button type="button" id="theButton" class="confirmBoxBtn"> This is a button </button>
    

    同样 delagate() 从 jQuery 3.0 开始,已被弃用。更新

     $("#theButton").on("click", function(e) {
          // remove default of the click
          e.preventDefault();
          // stop propagation
          e.stopPropagation();
         alert("Hello from Button");
     });
    

    【讨论】:

    • 您可能还需要停止传播
    • 我似乎看不到您遇到的问题。上面的页面是您要更新的页面吗?
    【解决方案2】:

    该脚本存在几个问题,正如 Jim-miraidev 指出的那样,您需要使用 jQuery 的 .on().stopPropagation().preventDefault()

    但这里的首要问题是页面还有其他几个事件在起作用(尤其是clickmouseup)。用户脚本代码导致页面的 flexbox 滚动状态变得混乱。
    (图表 A:仅在触发 mousedown 事件的第一次点击之后立即发生滚动。)

    因此,解决此问题的一种简单方法是捕获所有 3 个(可能)冲突事件

    $("div.mCSB_container").on ("click mousedown mouseup", "#theButton", function (zEvent) {
        zEvent.preventDefault ();
        zEvent.stopPropagation ();
    
        if (zEvent.type == "mousedown") {
            console.log ("Hello from Button");
        }
    } );
    

    请注意,浏览器按顺序触发事件:mousedown、mouseup、click。

    【讨论】:

    • 但我仍然想知道为什么它可以毫无问题地与&lt;div&gt; 一起使用。啊,这就是如何使用on(),我认为它就像@Jim-miraidev`发布的那样工作。谢谢!
    • Jim-miraidev 的代码是有效的,但它没有解决问题的问题。此外,对于一直被删除的元素(这是脚本的另一个问题),这不是一个好方法。至于 div 的问题,如果必须的话,请打开另一个问题,但是有一些事情正在发生,我现在不想深入探讨。
    猜你喜欢
    • 1970-01-01
    • 2018-12-09
    • 2015-01-12
    • 1970-01-01
    • 2021-05-04
    • 2021-07-11
    • 2014-11-24
    • 1970-01-01
    • 2021-11-11
    相关资源
    最近更新 更多