From fb7d38ede063d3b96cdff3f69cb687d1f98eefb5 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Thu, 18 Feb 2021 21:05:30 +0100 Subject: [PATCH 1/9] add bulk selection by click and drag over table rows --- src/pretix/static/pretixcontrol/js/ui/main.js | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index 092f3f83d..e672b9271 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -673,6 +673,78 @@ $(function () { $("input[data-toggle-table]").each(function (ev) { var $toggle = $(this); + var $table = $toggle.closest("table"); + var $rows = $table.find("tbody tr"); + var $checkboxes = $rows.find("td:first-child input[type=checkbox]"); + var firstIndex, lastIndex, currentIndex, selectionChecked, onChangeSelectionHappened = false; + var updateSelection = function(a, b, checked) { + if (a > b) { + //[a, b] = [b, a];// ES6 not ready yet for pretix + var tmp = a; + a = b; + b = tmp; + } + for (var i = a; i <= b; i++) { + var checkbox = $checkboxes.get(i); + if (!checkbox.hasAttribute("data-inital")) checkbox.setAttribute("data-inital", checkbox.checked); + if (checked === undefined || checked === null) checkbox.checked = checkbox.getAttribute("data-inital") === "true"; + else checkbox.checked = checked; + } + }; + var onChangeSelection = function(ev) { + onChangeSelectionHappened = true; + + var row = ev.target.closest("tr"); + currentIndex = 0; + while(row = row.previousSibling) { + if (row.tagName) currentIndex++; + } + + if (currentIndex > firstIndex && currentIndex > lastIndex) { + // special case: selection direction changed + if (lastIndex < firstIndex) { + // reset all selected checkboxes before setting new lastIndex + updateSelection(lastIndex, firstIndex); + } + lastIndex = currentIndex; + + } else if (currentIndex < firstIndex && currentIndex < lastIndex) { + // special case: selection direction changed + if (lastIndex > firstIndex) { + // reset all selected checkboxes before setting new lastIndex + updateSelection(firstIndex, lastIndex); + } + lastIndex = currentIndex; + } + + if (currentIndex != lastIndex) updateSelection(currentIndex, lastIndex); + 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 = currentIndex = firstIndex; + + ev.preventDefault(); + $rows.on("pointerenter", onChangeSelection); + }).on("pointerup", function(ev) { + if (onChangeSelectionHappened) { + ev.preventDefault(); + onChangeSelectionHappened = false; + $checkboxes.removeAttr("data-inital"); + update(); + } + $rows.off("pointerenter", onChangeSelection); + }); + var update = function () { var all_true = true; var all_false = true; From c9f89dc920088f367e53484b16e1e02c47325b2d Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Fri, 19 Feb 2021 07:33:01 +0100 Subject: [PATCH 2/9] simplified selection algorithm --- src/pretix/static/pretixcontrol/js/ui/main.js | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index e672b9271..7c9069c77 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -676,7 +676,7 @@ $(function () { var $table = $toggle.closest("table"); var $rows = $table.find("tbody tr"); var $checkboxes = $rows.find("td:first-child input[type=checkbox]"); - var firstIndex, lastIndex, currentIndex, selectionChecked, onChangeSelectionHappened = false; + var firstIndex, lastIndex, selectionChecked, onChangeSelectionHappened = false; var updateSelection = function(a, b, checked) { if (a > b) { //[a, b] = [b, a];// ES6 not ready yet for pretix @@ -695,29 +695,21 @@ $(function () { onChangeSelectionHappened = true; var row = ev.target.closest("tr"); - currentIndex = 0; + var currentIndex = 0; while(row = row.previousSibling) { if (row.tagName) currentIndex++; } - - if (currentIndex > firstIndex && currentIndex > lastIndex) { - // special case: selection direction changed - if (lastIndex < firstIndex) { - // reset all selected checkboxes before setting new lastIndex - updateSelection(lastIndex, firstIndex); - } - lastIndex = currentIndex; - - } else if (currentIndex < firstIndex && currentIndex < lastIndex) { - // special case: selection direction changed - if (lastIndex > firstIndex) { - // reset all selected checkboxes before setting new lastIndex - updateSelection(firstIndex, lastIndex); - } - lastIndex = currentIndex; + var dCurrent = currentIndex - firstIndex; + var dLast = lastIndex - firstIndex; + if (dCurrent*dLast < 0) { + // direction of selection changed => reset all previously selected + updateSelection(lastIndex, firstIndex); } - - if (currentIndex != lastIndex) updateSelection(currentIndex, lastIndex); + else if (Math.abs(dCurrent) < Math.abs(dLast)) { + // selection distance decreased => reset unselected + updateSelection(currentIndex, lastIndex); + } + lastIndex = currentIndex; updateSelection(firstIndex, currentIndex, selectionChecked); ev.preventDefault(); @@ -731,7 +723,7 @@ $(function () { while(row = row.previousSibling) { if (row.tagName) firstIndex++; } - lastIndex = currentIndex = firstIndex; + lastIndex = firstIndex; ev.preventDefault(); $rows.on("pointerenter", onChangeSelection); From 78f2581bb8f997c861f6c58721fe40c5cab1b8c4 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Fri, 19 Feb 2021 11:00:38 +0100 Subject: [PATCH 3/9] added labels to batch-select checkboxes --- .../control/templates/pretixcontrol/subevents/index.html | 4 ++-- src/pretix/static/pretixcontrol/scss/_forms.scss | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pretix/control/templates/pretixcontrol/subevents/index.html b/src/pretix/control/templates/pretixcontrol/subevents/index.html index 1a343bf2e..bae15dd0a 100644 --- a/src/pretix/control/templates/pretixcontrol/subevents/index.html +++ b/src/pretix/control/templates/pretixcontrol/subevents/index.html @@ -59,7 +59,7 @@ {% if "can_change_event_settings" in request.eventpermset %} - + {% endif %} @@ -88,7 +88,7 @@ {% if "can_change_event_settings" in request.eventpermset %} - + {% endif %} diff --git a/src/pretix/static/pretixcontrol/scss/_forms.scss b/src/pretix/static/pretixcontrol/scss/_forms.scss index 18279f046..6439ef507 100644 --- a/src/pretix/static/pretixcontrol/scss/_forms.scss +++ b/src/pretix/static/pretixcontrol/scss/_forms.scss @@ -613,3 +613,10 @@ table td > .checkbox input[type="checkbox"] { border-bottom: 1px solid $input-border; padding-bottom: 5px; } + +.batch-select-label { + display: block; + width: 100%; + height: 1.5em; + cursor: pointer; +} From d5950821e2eab68ef3d42fa62a40ed102d86c261 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Fri, 19 Feb 2021 11:02:42 +0100 Subject: [PATCH 4/9] optimized update() to only check the least number of checkboxes --- src/pretix/static/pretixcontrol/js/ui/main.js | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index 7c9069c77..93c36fe8a 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -738,22 +738,20 @@ $(function () { }); var update = function () { - var all_true = true; - var all_false = true; - $toggle.closest("table").find("td:first-child input[type=checkbox]").each(function () { - if ($(this).prop("checked")) { - all_false = false; - } else { - all_true = false; + 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); + return; } - }); - 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); } + $toggle.prop("checked", all_same).prop("indeterminate", false); }; $(this).closest("table").find("td:first-child input[type=checkbox]").change(update); From c6c0f928911b07c2409b28b0873efd057b68a7d6 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Fri, 19 Feb 2021 11:03:47 +0100 Subject: [PATCH 5/9] =?UTF-8?q?moved=20update()-event=20to=20checkboxes?= =?UTF-8?q?=E2=80=99=20change-event,=20added=20row-highlight=20if=20select?= =?UTF-8?q?ed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pretix/static/pretixcontrol/js/ui/main.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index 93c36fe8a..90ac2b204 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -689,6 +689,8 @@ $(function () { if (!checkbox.hasAttribute("data-inital")) checkbox.setAttribute("data-inital", checkbox.checked); if (checked === undefined || checked === null) checkbox.checked = checkbox.getAttribute("data-inital") === "true"; else checkbox.checked = checked; + + $(checkbox).trigger("change"); } }; var onChangeSelection = function(ev) { @@ -732,7 +734,6 @@ $(function () { ev.preventDefault(); onChangeSelectionHappened = false; $checkboxes.removeAttr("data-inital"); - update(); } $rows.off("pointerenter", onChangeSelection); }); @@ -754,9 +755,12 @@ $(function () { $toggle.prop("checked", all_same).prop("indeterminate", false); }; - $(this).closest("table").find("td:first-child input[type=checkbox]").change(update); + $checkboxes.change(function() { + $(this).closest("tr").toggleClass("warning", this.checked); + update(); + }); $(this).change(function (ev) { - $(this).closest("table").find("td:first-child input[type=checkbox]").prop("checked", $(this).prop("checked")); + $checkboxes.prop("checked", this.checked).trigger("change"); }); }); From 4203087eff5d78f3673d712332e033bec8fc46f6 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Mon, 22 Feb 2021 17:46:04 +0100 Subject: [PATCH 6/9] removed .warning from selected $rows as it interferes with .table-select-all --- src/pretix/static/pretixcontrol/js/ui/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index b6920a5ba..ab354a142 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -776,14 +776,14 @@ $(function () { var debounceUpdate; $checkboxes.change(function() { - $(this).closest("tr").toggleClass("warning", this.checked); + //$(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 (!$toggle.prop("indeterminate")) $checkboxes.prop("checked", this.checked).trigger("change"); + 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); }); From 40dbae76ca9920c184a79de141aaf1919628e0ea Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Mon, 22 Feb 2021 17:47:03 +0100 Subject: [PATCH 7/9] remove call to console.log --- src/pretix/static/pretixcontrol/js/ui/main.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index ab354a142..264bd20b0 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -757,7 +757,6 @@ $(function () { }); var update = function () { - console.log("update!"); var all_same; var checkboxes = $checkboxes.toArray(); var i = checkboxes.length; From 8a169d04963eda349e651113f301daf7814d5778 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Mon, 22 Feb 2021 18:13:18 +0100 Subject: [PATCH 8/9] fix bug when releasing outside of table --- src/pretix/static/pretixcontrol/js/ui/main.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index 264bd20b0..db7869e74 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -747,15 +747,18 @@ $(function () { ev.preventDefault(); $rows.on("pointerenter", onChangeSelection); - }).on("pointerup", function(ev) { - if (onChangeSelectionHappened) { - ev.preventDefault(); - onChangeSelectionHappened = false; - $checkboxes.removeAttr("data-inital"); - } - $rows.off("pointerenter", onChangeSelection); + + $(document).one("pointerup", function(ev) { + if (onChangeSelectionHappened) { + ev.preventDefault(); + onChangeSelectionHappened = false; + $checkboxes.removeAttr("data-inital"); + } + $rows.off("pointerenter", onChangeSelection); + }); }); + var update = function () { var all_same; var checkboxes = $checkboxes.toArray(); From 1bfa4c6fda76d30183e7cbfe1076acb810b4a930 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Mon, 22 Feb 2021 18:16:46 +0100 Subject: [PATCH 9/9] update toggle-state after release/pointerup instead of during updateSelection --- src/pretix/static/pretixcontrol/js/ui/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index db7869e74..73b6d3bce 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -707,8 +707,6 @@ $(function () { if (!checkbox.hasAttribute("data-inital")) checkbox.setAttribute("data-inital", checkbox.checked); if (checked === undefined || checked === null) checkbox.checked = checkbox.getAttribute("data-inital") === "true"; else checkbox.checked = checked; - - $(checkbox).trigger("change"); } }; var onChangeSelection = function(ev) { @@ -753,6 +751,8 @@ $(function () { ev.preventDefault(); onChangeSelectionHappened = false; $checkboxes.removeAttr("data-inital"); + + update(); } $rows.off("pointerenter", onChangeSelection); });