Firefox在按住键的同时点击时的事件传播问题



我正在实现表行多选,它应该是这样工作的:单击第一行,然后按住Shift键并单击底部行,应选择其间的所有行。我还使用自定义复选框,基本上是复选框+标签的组合。我还利用了事件传播的优势,只在表上绑定事件处理程序。

问题是,在Firefox上按住Shift键时,事件不会从标签冒泡到输入。

var lastCheckedRow = null;
$("table").click(function handleRowCheckboxClick(e) {
var $t = $(e.target);
// check if target is checkbox, otherwise ignore event ( on label )
if ($t.is(":checkbox")) {
var $cb = $t.is(":checkbox") ? $t : $t.siblings("input.mof-cell-checkbox");
// if not disabled
if (!$cb.prop("disabled")) {
if ($cb.hasClass("mof-cell-checkbox")) {
if (window.getSelection().empty) {
// Chrome
window.getSelection().empty();
}
checkBoxClickHandler($cb, e.shiftKey);
}
}
}
});
function checkBoxClickHandler($checkBoxInput, wasShiftPressed) {
var isChecked = $checkBoxInput.prop("checked");
$checkBoxInput
.closest("table > tbody > tr")
.toggleClass("row-selected", isChecked);
if (
lastCheckedRow &&
lastCheckedRow.index() ==
$checkBoxInput.closest("table > tbody > tr").index()
) {
lastCheckedRow = null;
return;
}
if (!lastCheckedRow) {
lastCheckedRow = $checkBoxInput.closest("table > tbody > tr");
return;
}
if (wasShiftPressed) {
var start = $checkBoxInput.closest("table > tbody > tr").index();
var end = lastCheckedRow.index();
var $trs = $checkBoxInput
.closest("table")
.find("tbody > tr")
.slice(Math.min(start, end), Math.max(start, end) + 1);
if (
lastCheckedRow.find(".mof-cell-checkbox").prop("checked") == isChecked
) {
$trs.each(function () {
$(this).toggleClass("row-selected", isChecked);
$(this).find(".mof-cell-checkbox").prop("checked", isChecked);
});
} else {
$trs.each(function () {
$(this).toggleClass("row-selected", !isChecked);
$(this).find(".mof-cell-checkbox").prop("checked", !isChecked);
});
}
}
lastCheckedRow = $checkBoxInput.closest("table > tbody > tr");
}
.custom-checkbox {
padding-left: 0;
margin-top: -0.075rem;
margin-bottom: -0.075rem;
position: relative;
display: block;
min-height: 1.45rem;
}
.custom-control-input {
position: absolute;
z-index: -1;
opacity: 0;
}
.custom-checkbox .custom-control-label::before {
border-radius: 2px;
}
.custom-control-label::before {
position: absolute;
top: 0.1rem;
left: 0;
display: block;
width: 1.25rem;
height: 1.25rem;
pointer-events: none;
content: "";
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #dee2e6;
}
.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before {
background-color: #2196f3;
}
.custom-control-input:checked ~ .custom-control-label::before {
border: none;
}
.custom-control-input:checked ~ .custom-control-label::before {
color: #fff;
background-color: #2196f3;
}
.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
}
.custom-control-label::after {
position: absolute;
top: 0.1rem;
left: 0;
display: block;
width: 1.25rem;
height: 1.25rem;
content: "";
background-repeat: no-repeat;
background-position: center center;
background-size: 50% 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<colgroup>
<col width="30px">
</colgroup>
<tbody>
<tr>
<td>
<div class="custom-checkbox custom-control">
<input class="custom-control-input mof-cell-checkbox mof-cell-checkbox-item form-control" id="0__checkBox" type="checkbox" value="true">
<label class="custom-control-label" for="0__checkBox"></label>
</div>
</td>
<td>1
</td>
</tr>
<tr>
<td>
<div class="custom-checkbox custom-control">
<input class="custom-control-input mof-cell-checkbox mof-cell-checkbox-item form-control" id="1__checkBox" type="checkbox" value="true">
<label class="custom-control-label" for="1__checkBox"></label>
</div>
</td>
<td>2
</td>
</tr>
<tr>
<td>
<div class="custom-checkbox custom-control">
<input class="custom-control-input mof-cell-checkbox mof-cell-checkbox-item form-control" id="2__checkBox" type="checkbox" value="true">
<label class="custom-control-label" for="2__checkBox"></label>
</div>
</td>
<td>3
</td>
</tr>
</tbody>
</table>

这个演示可以在Chrome上运行,但不能在Firefox上运行。你知道为什么会发生这种事吗?非常感谢。

标签上的shift+click或ctrl+click在Firefox中不起作用。请参阅他们重新打开的错误。如果您按住shift键并单击或按住ctrl键并单击复选框的标签,则复选框不会被选中。。

要使其工作,您需要在不使用<label>标记的情况下自定义复选框。

集成了自定义复选框标签,运行良好。在最新的Chrome和Firefox中进行了测试。

var lastCheckedRow = null;
$(document).on('click', '.mof-cell-checkbox', function handleRowCheckboxClick(e) {
var $t = $(e.target);
// check if target is checkbox, otherwise ignore event ( on label )
if ($t.is(":checkbox")) {
var $cb = $t.is(":checkbox") ? $t : $t.siblings("input.mof-cell-checkbox");
// if not disabled
if (!$cb.prop("disabled")) {
if ($cb.hasClass("mof-cell-checkbox")) {
if (window.getSelection().empty) {
// Chrome
window.getSelection().empty();
}
checkBoxClickHandler($cb, e.shiftKey);
}
}
}
});
function checkBoxClickHandler($checkBoxInput, wasShiftPressed) {
var isChecked = $checkBoxInput.prop("checked");
$checkBoxInput
.closest("table > tbody > tr")
.toggleClass("row-selected", isChecked);
if (
lastCheckedRow &&
lastCheckedRow.index() ==
$checkBoxInput.closest("table > tbody > tr").index()
) {
lastCheckedRow = null;
return;
}
if (!lastCheckedRow) {
lastCheckedRow = $checkBoxInput.closest("table > tbody > tr");
return;
}
if (wasShiftPressed) {
var start = $checkBoxInput.closest("table > tbody > tr").index();
var end = lastCheckedRow.index();
var $trs = $checkBoxInput
.closest("table")
.find("tbody > tr")
.slice(Math.min(start, end), Math.max(start, end) + 1);
if (
lastCheckedRow.find(".mof-cell-checkbox").prop("checked") == isChecked
) {
$trs.each(function () {
$(this).toggleClass("row-selected", isChecked);
$(this).find(".mof-cell-checkbox").prop("checked", isChecked);
});
} else {
$trs.each(function () {
$(this).toggleClass("row-selected", !isChecked);
$(this).find(".mof-cell-checkbox").prop("checked", !isChecked);
});
}
}
lastCheckedRow = $checkBoxInput.closest("table > tbody > tr");
}
.custom-checkbox {
width: 20px;
height: 20px;
position: relative;
}
.custom-checkbox > * {
position: absolute;
}
.custom-checkbox-visible {
width: 1.25rem;
height: 1.25rem;
margin: 2px;
background-color: #dee2e6;
}
.custom-checkbox > input {
z-index: 1;
opacity: 0;
left: 50%;
top: 50%;
transform: translatex(-50%) translatey(-50%);
display: block;
cursor: pointer;
width: 20px;
height: 20px;
background-color: #dee2e6;
}
.custom-checkbox > input:checked + .custom-checkbox-visible {
background: #2196f3;
background-color: #2196f3;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center center;
background-size: 50% 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<colgroup>
<col width="30px">
</colgroup>
<tbody>
<tr>
<td>
<div class="custom-checkbox custom-control">
<input class="custom-control-input mof-cell-checkbox mof-cell-checkbox-item form-control" id="0__checkBox" type="checkbox" value="true">
<div class="custom-checkbox-visible"></div>
</div>
</td>
<td>1
</td>
</tr>
<tr>
<td>
<div class="custom-checkbox custom-control">
<input class="custom-control-input mof-cell-checkbox mof-cell-checkbox-item form-control" id="1__checkBox" type="checkbox" value="true"/>
<div class="custom-checkbox-visible"></div>
</div>
</td>
<td>2
</td>
</tr>
<tr>
<td>
<div class="custom-checkbox custom-control">
<input class="custom-control-input mof-cell-checkbox mof-cell-checkbox-item form-control" id="2__checkBox" type="checkbox" value="true">
<div class="custom-checkbox-visible"></div>
</div>
</td>
<td>3
</td>
</tr>
</tbody>
</table>

最新更新