gpt4 book ai didi

javascript - 神秘鼠标事件关闭 jQuery UI 对话框

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:30:35 25 4
gpt4 key购买 nike

这显然是一个 SSCCE .

因此,我们的任务是编写导弹发射控制系统的前端。我们选择 Spartan 布局,因为这是非常严重的:只有一个文本输入框和一个用于输入代码的按钮:

enter image description here

为了安全起见,单击“确定”按钮后,我们将显示一个对话框,要求用户确认:

enter image description here

作为可用性的画龙点睛之笔,我们为 Enter 按钮添加了一个关键监听器,它也将导致单击“确定”按钮(使用 $.trigger()) .

不幸的是,确认对话框仅在用户单击“确定”按钮时显示,而在按 Enter 时不会显示。当我们点击 Enter 时,对话框根本不会出现。

最糟糕的是,在添加一些调试消息后,对话框似乎确实显示了几分之一毫秒,然后由于某种原因单击了“Yeap”按钮。所以当 Enter 被击中时,导弹发射立即被确认!

fiddle here .

代码如下:

function inputKeyListener(evt) {
console.log('key listener - triggered key code is: ' + evt.keyCode);
if (evt.keyCode === $.ui.keyCode.ENTER) {
evt.stopPropagation();
$('#missile-launch-button').click(); // Directly calling confirm() doesn't work either
}
}

function missileLaunchButtonClickHandler(e) {
e.stopPropagation();
confirm();
}

function confirm() {
var launchCode = $('#missile-launch-code-input').val();
const dialog = $('#missile-launch-confirmation-modal');
dialog.dialog({
closeOnEscape: false,
dialogClass: 'no-close',
open: function(event, ui) {
console.log('confirm :: open is called');
},
close: function() {
console.log('confirm :: close is called');
},
resizable: false,
height: "auto",
width: 400,
modal: true,
buttons: {
"Yeap": function() {
console.log('Confirmation button was clicked');
$(this).dialog("close");
console.log('missile launch with code [' + launchCode + '] was confirmed!');
},
"Maybe not just yet": function(ev) {
console.log('Abort button was clicked');
$(this).dialog("close");
console.log('Armageddon was averted');
}
}
});

dialog.dialog('open');
console.log('by this time the dialog should be displayed');
}


$('#missile-launch-confirmation-modal').dialog({
autoOpen: false
});


$('#missile-launch-button').click(missileLaunchButtonClickHandler);

$(document).on('keydown', inputKeyListener);
<link rel='stylesheet' href='https://code.jquery.com/ui/1.11.4/themes/vader/jquery-ui.css'>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

<div id='missile-launch-confirmation-modal' title='Confirm missile launch' </div>
<span class="ui-icon ui-icon-alert" style="float:left; margin:12px 12px 20px 0;"></span> Are you sure you want to unleash nuclear Armageddon?
</div>
</div>
<div>
<div>
<div>Enter missile launch code:</div>
<div>
<input id='missile-launch-code-input' type='text' autofocus/>
</div>
<div>
<button id='missile-launch-button' type='button'>OK</button>
</div>
</div>
</div>

更新

在上面的代码中,inputKeyListener 绑定(bind)到 document 上的 keydown。将它更窄地绑定(bind)到文本输入上的 keydown,如:

$('#missile-launch-code-input').on('keydown', inputKeyListener);

…导致完全相同的行为。

更新二

This answer建议 stopPropagation 在这里无效,因为“事件冒泡在这里并没有真正发挥作用”并解释说 preventDefault 应该用于“[阻止] 键事件到达其他页面元素(即那个按钮)”。我对这两个陈述放在一起感到有点困惑。我认为 stopPropagation 正是用来阻止“关键事件到达其他页面元素”的东西。此外还有两点混淆。

第一个混淆点是确认对话框 div 不是文本输入 div 的父 DOM 元素,所以不清楚键盘事件是如何发生的文本输入 divsibling(不是 parent)DOM 元素拦截。我认为这实际上是 stopPropagation 无效的原因,但我仍然不清楚为什么(无论 stopPropagation)事件到达位于 a 中的确认对话框按钮兄弟 div.

第二个混淆点是,如果我们记录我们在“Yeap”按钮函数处理程序中捕获的事件,例如像这样:

buttons: {
"Yeap": function(ev) {
console.log(ev);

...我们实际上在控制台中看到的是:

enter image description here

…所以这是一个鼠标事件,而不是确认对话框的键盘事件。假设(在简单点击 Enter 的情况下)我们生成的唯一 mouse 事件是在 inputKeyListener 中:

$('#missile-launch-button').click();

…这意味着是这个事件导致对话框的确认,而不是我们通过点击 Enter

获得的键盘事件

最佳答案

这似乎是 jQuery UI 的一个例子,它对自己的好处有点太有用了:当 dialog 打开时,它会把里面的第一个按钮放在焦点上,正好 catch “输入” "触发按钮的关键事件(这是当用户在按钮处于焦点状态时点击“输入”时浏览器的默认行为。)

inputKeyListener 中使用 preventDefault 可阻止键事件到达其他页面元素(即那个按钮)。 stopPropagation 是无害的,但在 inputKeyListenermissileLaunchButtonClickHandler 中没有任何有用的效果,因为事件冒泡在这里并没有真正发挥作用。

这是一个没有 preventDefault 或 stopPropagation 的演示,包含一个用于无害地捕获自动对焦的虚拟按钮,只是为了确认这是正在发生的事情:

function inputKeyListener(evt) {
console.log('key listener - triggered key code is: ' + evt.keyCode);
if (evt.keyCode === $.ui.keyCode.ENTER) {
// $('#missile-launch-button').click(); // Directly calling confirm() doesn't work either
confirm(); // Does too!
}
}

function missileLaunchButtonClickHandler(e) {
confirm();
}

function confirm() {
var launchCode = $('#missile-launch-code-input').val();
const dialog = $('#missile-launch-confirmation-modal');
dialog.dialog({
closeOnEscape: false,
dialogClass: 'no-close',
open: function(event, ui) {
console.log('confirm :: open is called');
},
close: function() {
console.log('confirm :: close is called');
},
resizable: false,
height: "auto",
width: 400,
modal: true,
buttons: {
"Hmmmm": function() {
console.log('First button inside the dialog was clicked.');
},
"Yeap": function() {
console.log('Confirmation button was clicked');
$(this).dialog("close");
console.log('missile launch with code [' + launchCode + '] was confirmed!');
},
"Maybe not just yet": function(ev) {
console.log('Abort button was clicked');
$(this).dialog("close");
console.log('Armageddon was averted');
}
}
});

dialog.dialog('open');
console.log('by this time the dialog should be displayed');
}


$('#missile-launch-confirmation-modal').dialog({
autoOpen: false
});


$('#missile-launch-button').click(missileLaunchButtonClickHandler);

$(document).on('keydown', inputKeyListener);
<link rel='stylesheet' href='https://code.jquery.com/ui/1.11.4/themes/vader/jquery-ui.css'>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

<div id='missile-launch-confirmation-modal' title='Confirm missile launch' </div>
<span class="ui-icon ui-icon-alert" style="float:left; margin:12px 12px 20px 0;"></span> Are you sure you want to unleash nuclear Armageddon?
</div>
</div>
<div>
<div>
<div>Enter missile launch code:</div>
<div>
<input id='missile-launch-code-input' type='text' autofocus/>
</div>
<div>
<button id='missile-launch-button' type='button'>OK</button>
</div>
</div>
</div>

关于 event.preventDefault 与 event.stopPropagation

为了扩展这一点,根据“更新 II”:stopPropagation 防止事件冒泡到父 DOM 节点。通常,例如,点击事件从直接点击的节点向上冒泡,遍历每个父节点。

stopPropagation 在这里不相关的原因是因为 dialog 不是输入元素的父元素:事件冒泡不会到达 dialog .所以没有理由用 stopPropagation 停止事件冒泡,因为它无论如何都不会触发任何有意义的事情。

相比之下,event.preventDefault 停止的事件与 DOM 结构无关——这些事件不关心 parent 、 sibling 、孙子女或第三代堂兄是否被两次删除; event.preventDefault 只是意味着“无论浏览器在这种情况下的默认行为是什么,都不要那样做。”例如,表单提交上的 event.preventDefault 会停止提交表单。

在这个问题中描述的情况下,如果用户在按钮处于焦点状态时按下“enter”键,则浏览器的默认行为是触发该按钮上的点击事件(是的,鼠标事件),不管按钮在 DOM 中的什么位置。所以在这里使用 event.preventDefault 可以防止默认行为,这正是您想要的。

关于javascript - 神秘鼠标事件关闭 jQuery UI 对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44010744/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com