简体   繁体   English

HTML-单击按钮会使列表在未知原因的顶部滚动

[英]HTML - Click on button causes list to scroll on top for unknown reasons

I am using tampermonkey to add some custom buttons to the Unity Documentation . 我正在使用tampermonkey向Unity文档中添加一些自定义按钮。

I noticed a strange problem If I am using a html <button> . 我注意到一个奇怪的问题,如果我使用的是html <button> Everytime when I click on the button, then the scroll list is scrolling to the top and the code is only executed on the second click. 每当我单击按钮时,滚动列表就会滚动到顶部,并且仅在第二次单击时才执行代码。


However, If I replace <button> with <div> then everything is working perfectly fine. 但是,如果我将<button>替换为<div>那么一切工作都很好。


Why is <button> behaving so weird? 为什么<button>如此怪异?

Below is the tampermonkey script for reproduction. 下面是用于复制的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);
}

Instructions 说明


Wait until the site loaded completly (about 4 seconds until the site load indicator disapeared) then right click on a link in the scroll list at left, which should be as far as possible down (so you can see that the list is actually scrolling up after clicking on the button). 等待站点完全加载(大约4秒钟,直到站点加载指示符消失),然后右键单击左侧滚动列表中的链接,该链接应尽可能向下(这样您就可以看到列表实际上在向上滚动)单击按钮后)。 Now a container should appear: 现在应该出现一个容器:

在此处输入图片说明

Now click on the <button> named This is a button and notice that the scroll list scrolls to the top and the code from the button is not executed (alert should show). 现在,单击名为“ This is a button<button> ,注意滚动列表滚动到顶部,并且该按钮中的代码未执行(警告应显示)。 Press again on the button and notice that the code is now executed and the scroll list scrolls to top again after pressing Ok on the alert. 再次按按钮,注意代码现在已执行,并且在警报上单击“确定”后,滚动列表再次滚动到顶部。

Next click on the <div> named This is a div and note that everything works as expected. 接下来,单击名为“ This is a div<div> ,注意所有操作均按预期进行。

There are several issues with that script and, as Jim-miraidev pointed out, you need to use jQuery's .on() , .stopPropagation() , and .preventDefault() . 该脚本存在多个问题,正如Jim-miraidev所指出的,您需要使用jQuery的.on() .stopPropagation().preventDefault()

But the priority problem here is that the page has several other events at play (especially click and mouseup ). 但是这里的优先权问题是页面上还有其他几个事件 (尤其是clickmouseup在起作用 The userscript code is causing the page's flexbox scroll state to get confused. 用户脚本代码导致页面的flexbox滚动状态变得混乱。
(Exhibit A: the scroll only happens on first click immediately after the mousedown event that fires showConfirmBox() .) (图表A:滚动仅在触发showConfirmBox()mousedown事件之后立即在第一次单击时发生。)

So, an easy way to patch this is to capture all 3 of the (potentially) conflicting events : 因此,修补此问题的一种简单方法是捕获所有3个(潜在)冲突事件

$("div.mCSB_container").on ("click mousedown mouseup", "#theButton", function (zEvent) {
    zEvent.preventDefault ();
    zEvent.stopPropagation ();

    if (zEvent.type == "mousedown") {
        console.log ("Hello from Button");
    }
} );

Note that browsers fire the events in the order: mousedown, mouseup, click. 请注意,浏览器按以下顺序触发事件:mousedown,mouseup,click。

Buttons default will submit the page, causing a refresh. 默认情况下,按钮将提交页面,从而刷新页面。

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

The default "type" for a button is "submit", which self posts. 按钮的默认“类型”是“提交”,它会自行发布。 Update the button "type" to "button". 将按钮“类型”更新为“按钮”。

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

Also delagate() as of jQuery 3.0, has been deprecated. 从jQuery 3.0开始,delagate()也已弃用。 Update for 更新为

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM