当元素已经被移除时检测点击
Detect click when elements have already been removed
我试图检测是否在 DatePicker 控件上发生了点击,但我无法准确确定事件目标元素是否是 DatePicker 的一部分。
经过大量调试后,我意识到主要问题是 DatePicker 的各个部分与文档分离,因此它们根本不是任何元素的子元素。
感谢 this other question 我了解到原因是在切换月份时删除并替换了 DatePicker 的一部分,所以我从 event.target
获得的元素被分离了(它是已移除块的一部分)。
那么,如何判断这次点击是在我的控制范围内呢?我正在尝试以不可知论的方式写出正在使用的内容类型,尽管针对 DatePickers 的特定修复是可以的。
到目前为止,我所做的是检查我的元素是否包含 DatePicker,以及事件目标是否已分离。如果是这样,我假设点击发生在 DatePicker 上。这并不完美,因为页面上可能还有另一个 DatePicker。此外,被分离的事件目标不一定与 DatePicker 相关。
这是我目前所拥有的示例:
$(document).on("click", function (event) {
const stuff = $("something");
if (stuff.is($(event.target)))
return; // click was on stuff
if ($(event.target).closest(stuff).length)
return; // click was on descendents of stuff
if (stuff.is(":active, :focus"))
return; // stuff is active or focused
if (stuff.find(":active, :focus").length)
return; // a descendent of stuff is active or focused
if (stuff.is(".hasDatepicker") || stuff.find(".hasDatepicker").length) {
// stuff is or has a date picker
if (!$(event.target).closest($(document)).length) {
// event target is detached, and there's a date picker in stuff
// so have to assume click was on stuff's date picker
return;
}
}
// click was not within stuff's elements
}
我不明白你的意思:
« DatePicker 的片段与文档分离,因此它们根本不是任何元素的子元素。»
这是错误的。您可以在页面中看到的所有元素都在 DOM 中(因此文档 "attached")。
但有时,不会很长时间,这里就是这种情况。
日期选择器元素在打开时创建并附加到 body
。
当它关闭时,它的元素都被删除了。
下面的代码检索被点击的元素,它 tagName
、它的 class
、它的 id
和它的 innerHTML
。
我什至在文档中重新创建了它们...
;)
它使用 delegation
,因为@Roamer 在评论中根据需要正确提及。
$(document).on("mouseup",".ui-datepicker",function(e){
var target = e.target;
var tag = target.tagName.toLowerCase();
var classes = target.className;
var ID = target.id;
var resultString = "<"+tag+" id='"+ID+"' class='"+classes+"'>"+target.innerHTML+"</"+tag+"><br>";
console.log(resultString);
var result = $(resultString);
$("#result").append(result);
});
遗憾的是,我的示例中的 CSS 在 SO 代码段中效果不佳。
所以它在 CodePen.
我使用了 mouseup
事件,因为 click
不起作用...
可能是由于 return false
在 Datepicker 的某处。
你要找的大概是$(".selector").datepicker("widget")
Returns a jQuery object containing the datepicker.
This method does not accept any arguments.
Code examples:
Invoke the widget method:
var widget = $( ".selector" ).datepicker( "widget" );
现在您可以从原始元素中获取实际的日期选择器 UI,您可以随心所欲地使用它,即检查点击是否在其上。
以下是我将如何使用上述方法解决此问题:
$(function() {
$('#thedate').datepicker({
dateFormat: 'dd-mm-yy',
altField: '#thealtdate',
altFormat: 'yy-mm-dd'
});
$(document).on('mousedown',function(event) {
// only evaluate if the click was NOT on the element or any of its descendants
if (!$(event.target).closest('#some-container').length && !$(event.target).is('#some-container')) {
// now lets check for any elements in our container that have datepickers
var $contanier = $('#some-container');
var $elementsWithDatePickers = $contanier.find('.hasDatepicker');
var clickedChildDatePicker = false;
$elementsWithDatePickers.each(function() {
// for each datepicker found, check that the click was also not on it or any of its descendants
var $widget = $(this).datepicker("widget");
if ($(event.target).is($widget) || $(event.target).closest($widget[0]).length > 0) {
clickedChildDatePicker = true;
return false;
}
});
if (!clickedChildDatePicker) {
$contanier.hide();
}
}
})
});
#other{
background-color:#ccc;
padding: 45px;
}
#some-container{
background-color:#fff;
padding: 45px;
}
<link href="https://code.jquery.com/ui/1.8.21/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<div id="other">
<div id="some-container">
Date :
<div id="thedate">
</div>
<br />
</div>
click here to hide container
</div>
我试图检测是否在 DatePicker 控件上发生了点击,但我无法准确确定事件目标元素是否是 DatePicker 的一部分。
经过大量调试后,我意识到主要问题是 DatePicker 的各个部分与文档分离,因此它们根本不是任何元素的子元素。
感谢 this other question 我了解到原因是在切换月份时删除并替换了 DatePicker 的一部分,所以我从 event.target
获得的元素被分离了(它是已移除块的一部分)。
那么,如何判断这次点击是在我的控制范围内呢?我正在尝试以不可知论的方式写出正在使用的内容类型,尽管针对 DatePickers 的特定修复是可以的。
到目前为止,我所做的是检查我的元素是否包含 DatePicker,以及事件目标是否已分离。如果是这样,我假设点击发生在 DatePicker 上。这并不完美,因为页面上可能还有另一个 DatePicker。此外,被分离的事件目标不一定与 DatePicker 相关。
这是我目前所拥有的示例:
$(document).on("click", function (event) {
const stuff = $("something");
if (stuff.is($(event.target)))
return; // click was on stuff
if ($(event.target).closest(stuff).length)
return; // click was on descendents of stuff
if (stuff.is(":active, :focus"))
return; // stuff is active or focused
if (stuff.find(":active, :focus").length)
return; // a descendent of stuff is active or focused
if (stuff.is(".hasDatepicker") || stuff.find(".hasDatepicker").length) {
// stuff is or has a date picker
if (!$(event.target).closest($(document)).length) {
// event target is detached, and there's a date picker in stuff
// so have to assume click was on stuff's date picker
return;
}
}
// click was not within stuff's elements
}
我不明白你的意思:
« DatePicker 的片段与文档分离,因此它们根本不是任何元素的子元素。»
这是错误的。您可以在页面中看到的所有元素都在 DOM 中(因此文档 "attached")。
但有时,不会很长时间,这里就是这种情况。
日期选择器元素在打开时创建并附加到 body
。
当它关闭时,它的元素都被删除了。
下面的代码检索被点击的元素,它 tagName
、它的 class
、它的 id
和它的 innerHTML
。
我什至在文档中重新创建了它们...
;)
它使用 delegation
,因为@Roamer 在评论中根据需要正确提及。
$(document).on("mouseup",".ui-datepicker",function(e){
var target = e.target;
var tag = target.tagName.toLowerCase();
var classes = target.className;
var ID = target.id;
var resultString = "<"+tag+" id='"+ID+"' class='"+classes+"'>"+target.innerHTML+"</"+tag+"><br>";
console.log(resultString);
var result = $(resultString);
$("#result").append(result);
});
遗憾的是,我的示例中的 CSS 在 SO 代码段中效果不佳。 所以它在 CodePen.
我使用了 mouseup
事件,因为 click
不起作用...
可能是由于 return false
在 Datepicker 的某处。
你要找的大概是$(".selector").datepicker("widget")
Returns a jQuery object containing the datepicker. This method does not accept any arguments.
Code examples: Invoke the widget method:
var widget = $( ".selector" ).datepicker( "widget" );
现在您可以从原始元素中获取实际的日期选择器 UI,您可以随心所欲地使用它,即检查点击是否在其上。
以下是我将如何使用上述方法解决此问题:
$(function() {
$('#thedate').datepicker({
dateFormat: 'dd-mm-yy',
altField: '#thealtdate',
altFormat: 'yy-mm-dd'
});
$(document).on('mousedown',function(event) {
// only evaluate if the click was NOT on the element or any of its descendants
if (!$(event.target).closest('#some-container').length && !$(event.target).is('#some-container')) {
// now lets check for any elements in our container that have datepickers
var $contanier = $('#some-container');
var $elementsWithDatePickers = $contanier.find('.hasDatepicker');
var clickedChildDatePicker = false;
$elementsWithDatePickers.each(function() {
// for each datepicker found, check that the click was also not on it or any of its descendants
var $widget = $(this).datepicker("widget");
if ($(event.target).is($widget) || $(event.target).closest($widget[0]).length > 0) {
clickedChildDatePicker = true;
return false;
}
});
if (!clickedChildDatePicker) {
$contanier.hide();
}
}
})
});
#other{
background-color:#ccc;
padding: 45px;
}
#some-container{
background-color:#fff;
padding: 45px;
}
<link href="https://code.jquery.com/ui/1.8.21/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<div id="other">
<div id="some-container">
Date :
<div id="thedate">
</div>
<br />
</div>
click here to hide container
</div>