HTML - 单击按钮导致列表滚动到顶部,原因不明
HTML - Click on button causes list to scroll on top for unknown reasons
我正在使用 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 秒,直到站点加载指示器消失)然后 右键单击 左侧滚动列表中的 link,这应该尽可能向下(这样你可以看到点击按钮后列表实际上是向上滚动的)。
现在应该出现一个容器:
现在单击名为 This is a button
的 <button>
并注意滚动列表滚动到顶部并且按钮中的代码未执行(应显示警报)。再次按下按钮,请注意代码现在已执行,并且在警报上按下“确定”后滚动列表再次滚动到顶部。
接下来单击名为 This is a div
的 <div>
并注意一切正常。
按钮默认会提交页面,导致刷新。
<button id="theButton" class="confirmBoxBtn"> This is a button </button>
按钮的默认 "type" 是 "submit",它是自己发布的。将按钮 "type" 更新为 "button"。
<button type="button" id="theButton" class="confirmBoxBtn"> This is a button </button>
从 jQuery 3.0 开始,delagate() 也已被弃用。
的更新
$("#theButton").on("click", function(e) {
// remove default of the click
e.preventDefault();
// stop propagation
e.stopPropagation();
alert("Hello from Button");
});
该脚本有几个问题,正如 Jim-miraidev 指出的那样,您需要使用 jQuery 的 .on()
、.stopPropagation()
和 .preventDefault()
.
但这里的优先级问题是 该页面还有其他几个事件在起作用(尤其是 click
和 mouseup
)。用户脚本代码导致页面的 flexbox 滚动状态变得混乱。
(图表 A:滚动仅在触发 showConfirmBox()
的 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。
我正在使用 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 秒,直到站点加载指示器消失)然后 右键单击 左侧滚动列表中的 link,这应该尽可能向下(这样你可以看到点击按钮后列表实际上是向上滚动的)。 现在应该出现一个容器:
现在单击名为 This is a button
的 <button>
并注意滚动列表滚动到顶部并且按钮中的代码未执行(应显示警报)。再次按下按钮,请注意代码现在已执行,并且在警报上按下“确定”后滚动列表再次滚动到顶部。
接下来单击名为 This is a div
的 <div>
并注意一切正常。
按钮默认会提交页面,导致刷新。
<button id="theButton" class="confirmBoxBtn"> This is a button </button>
按钮的默认 "type" 是 "submit",它是自己发布的。将按钮 "type" 更新为 "button"。
<button type="button" id="theButton" class="confirmBoxBtn"> This is a button </button>
从 jQuery 3.0 开始,delagate() 也已被弃用。
的更新 $("#theButton").on("click", function(e) {
// remove default of the click
e.preventDefault();
// stop propagation
e.stopPropagation();
alert("Hello from Button");
});
该脚本有几个问题,正如 Jim-miraidev 指出的那样,您需要使用 jQuery 的 .on()
、.stopPropagation()
和 .preventDefault()
.
但这里的优先级问题是 该页面还有其他几个事件在起作用(尤其是 click
和 mouseup
)。用户脚本代码导致页面的 flexbox 滚动状态变得混乱。
(图表 A:滚动仅在触发 showConfirmBox()
的 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。