mirror of
https://github.com/pretix/pretix.git
synced 2026-08-29 13:44:40 +00:00
Merge pull request #1931 from pretix/bulk-select-with-drag-over
add bulk selection by click and drag over table rows
This commit is contained in:
@@ -67,7 +67,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{% if "can_change_event_settings" in request.eventpermset %}
|
{% if "can_change_event_settings" in request.eventpermset %}
|
||||||
<input type="checkbox" data-toggle-table/>
|
<label aria-label="{% trans "select all rows for batch-operation" %}" class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{% if "can_change_event_settings" in request.eventpermset %}
|
{% if "can_change_event_settings" in request.eventpermset %}
|
||||||
<input type="checkbox" name="subevent" class="" value="{{ s.pk }}"/>
|
<label aria-label="{% trans "select row for batch-operation" %}" class="batch-select-label"><input type="checkbox" name="subevent" class="" value="{{ s.pk }}"/></label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -690,47 +690,104 @@ $(function () {
|
|||||||
// Tables with bulk selection, e.g. subevent list
|
// Tables with bulk selection, e.g. subevent list
|
||||||
$("input[data-toggle-table]").each(function (ev) {
|
$("input[data-toggle-table]").each(function (ev) {
|
||||||
var $toggle = $(this);
|
var $toggle = $(this);
|
||||||
|
var $table = $toggle.closest("table");
|
||||||
var update = function () {
|
var $selectAll = $table.find(".table-select-all");
|
||||||
var all_true = true;
|
var $rows = $table.find("tbody tr");
|
||||||
var all_false = true;
|
var $checkboxes = $rows.find("td:first-child input[type=checkbox]");
|
||||||
$toggle.closest("table").find("tbody td:first-child input[type=checkbox]").each(function () {
|
var firstIndex, lastIndex, selectionChecked, onChangeSelectionHappened = false;
|
||||||
if ($(this).prop("checked")) {
|
var updateSelection = function(a, b, checked) {
|
||||||
all_false = false;
|
if (a > b) {
|
||||||
} else {
|
//[a, b] = [b, a];// ES6 not ready yet for pretix
|
||||||
all_true = false;
|
var tmp = a;
|
||||||
}
|
a = b;
|
||||||
});
|
b = tmp;
|
||||||
if (all_true) {
|
|
||||||
$toggle.prop("checked", true).prop("indeterminate", false);
|
|
||||||
} else if (all_false) {
|
|
||||||
$toggle.prop("checked", false).prop("indeterminate", false);
|
|
||||||
} else {
|
|
||||||
$toggle.prop("checked", false).prop("indeterminate", true);
|
|
||||||
}
|
}
|
||||||
var is_incomplete = $toggle.prop("indeterminate") || !$toggle.prop("checked")
|
for (var i = a; i <= b; i++) {
|
||||||
$toggle.closest("table").find(".table-select-all").toggleClass(
|
var checkbox = $checkboxes.get(i);
|
||||||
"hidden", is_incomplete
|
if (!checkbox.hasAttribute("data-inital")) checkbox.setAttribute("data-inital", checkbox.checked);
|
||||||
)
|
if (checked === undefined || checked === null) checkbox.checked = checkbox.getAttribute("data-inital") === "true";
|
||||||
if (is_incomplete) {
|
else checkbox.checked = checked;
|
||||||
$toggle.closest("table").find(".table-select-all input").prop(
|
|
||||||
"checked", false
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
var onChangeSelection = function(ev) {
|
||||||
|
onChangeSelectionHappened = true;
|
||||||
|
|
||||||
$(this).closest("table").find("td:first-child input[type=checkbox]").change(update);
|
var row = ev.target.closest("tr");
|
||||||
$(this).change(function (ev) {
|
var currentIndex = 0;
|
||||||
$(this).closest("table").find("tbody td:first-child input[type=checkbox]").prop("checked", $(this).prop("checked"));
|
while(row = row.previousSibling) {
|
||||||
var is_incomplete = $(this).prop("indeterminate") || !$(this).prop("checked")
|
if (row.tagName) currentIndex++;
|
||||||
$(this).closest("table").find(".table-select-all").toggleClass(
|
|
||||||
"hidden", is_incomplete
|
|
||||||
)
|
|
||||||
if (is_incomplete) {
|
|
||||||
$(this).closest("table").find(".table-select-all input").prop(
|
|
||||||
"checked", false
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
var dCurrent = currentIndex - firstIndex;
|
||||||
|
var dLast = lastIndex - firstIndex;
|
||||||
|
if (dCurrent*dLast < 0) {
|
||||||
|
// direction of selection changed => reset all previously selected
|
||||||
|
updateSelection(lastIndex, firstIndex);
|
||||||
|
}
|
||||||
|
else if (Math.abs(dCurrent) < Math.abs(dLast)) {
|
||||||
|
// selection distance decreased => reset unselected
|
||||||
|
updateSelection(currentIndex, lastIndex);
|
||||||
|
}
|
||||||
|
lastIndex = currentIndex;
|
||||||
|
updateSelection(firstIndex, currentIndex, selectionChecked);
|
||||||
|
|
||||||
|
ev.preventDefault();
|
||||||
|
};
|
||||||
|
$table.on("pointerdown", function(ev) {
|
||||||
|
if (!ev.target.closest("td:first-child")) return;
|
||||||
|
var row = ev.target.closest("tr");
|
||||||
|
selectionChecked = !row.querySelector("td:first-child input").checked;
|
||||||
|
|
||||||
|
firstIndex = 0;
|
||||||
|
while(row = row.previousSibling) {
|
||||||
|
if (row.tagName) firstIndex++;
|
||||||
|
}
|
||||||
|
lastIndex = firstIndex;
|
||||||
|
|
||||||
|
ev.preventDefault();
|
||||||
|
$rows.on("pointerenter", onChangeSelection);
|
||||||
|
|
||||||
|
$(document).one("pointerup", function(ev) {
|
||||||
|
if (onChangeSelectionHappened) {
|
||||||
|
ev.preventDefault();
|
||||||
|
onChangeSelectionHappened = false;
|
||||||
|
$checkboxes.removeAttr("data-inital");
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
$rows.off("pointerenter", onChangeSelection);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var update = function () {
|
||||||
|
var all_same;
|
||||||
|
var checkboxes = $checkboxes.toArray();
|
||||||
|
var i = checkboxes.length;
|
||||||
|
while (i--) {
|
||||||
|
if (all_same === undefined) {
|
||||||
|
all_same = checkboxes[i].checked;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (all_same != checkboxes[i].checked) {
|
||||||
|
$toggle.prop("checked", false).prop("indeterminate", true).trigger("change");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$toggle.prop("checked", all_same).prop("indeterminate", false).trigger("change");
|
||||||
|
};
|
||||||
|
|
||||||
|
var debounceUpdate;
|
||||||
|
$checkboxes.change(function() {
|
||||||
|
//$(this).closest("tr").toggleClass("warning", this.checked);
|
||||||
|
// when changing the $toggle’s checked-property, lots of change events
|
||||||
|
// get triggered => debounce
|
||||||
|
if (debounceUpdate) window.clearTimeout(debounceUpdate);
|
||||||
|
debounceUpdate = window.setTimeout(update, 10);
|
||||||
|
});
|
||||||
|
$toggle.change(function (ev) {
|
||||||
|
if (!this.indeterminate) $checkboxes.prop("checked", this.checked);//.trigger("change");
|
||||||
|
$selectAll.toggleClass("hidden", !this.checked).prop("hidden", !this.checked);
|
||||||
|
if (!this.checked) $selectAll.find("input").prop("checked", false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -614,6 +614,14 @@ table td > .checkbox input[type="checkbox"] {
|
|||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.batch-select-label {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 1.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.bulk-edit-field-group {
|
.bulk-edit-field-group {
|
||||||
.field-toggle {
|
.field-toggle {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|||||||
Reference in New Issue
Block a user