Presale: improve clientside handling of max-count for add-on products

* Fix typo in error message

* Use exclusive checkboxes for addon items with max_count == 1 and !multi_allowed

* combine exclusive items + variations

* move exclusive to containing fieldset

* fix add-on-exclusive

* add max_count check

* fix plus/minus-stepper buttons bubbling

* Update src/pretix/static/pretixpresale/js/ui/main.js

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
Mira
2024-03-14 09:17:42 +01:00
committed by GitHub
parent 7592a8a575
commit 304d290f22
4 changed files with 42 additions and 13 deletions

View File

@@ -123,7 +123,7 @@ var form_handlers = function (el) {
var controls = document.getElementById(this.getAttribute("data-controls"));
var currentValue = parseFloat(controls.value);
controls.value = Math.max(controls.min, Math.min(controls.max || Number.MAX_SAFE_INTEGER, (currentValue || 0) + step));
controls.dispatchEvent(new Event("change"));
controls.dispatchEvent(new Event("change", { bubbles: true }));
});
el.find(".btn-checkbox input").on("change", function (e) {
$(this).closest(".btn-checkbox")
@@ -149,11 +149,41 @@ var form_handlers = function (el) {
).find("canvas").attr("role", "img").attr("aria-label", this.getAttribute("data-desc"));
});
el.find("input[data-exclusive-prefix]").each(function () {
var $others = $("input[name^=" + $(this).attr("data-exclusive-prefix") + "]:not([name=" + $(this).attr("name") + "])");
$(this).on('click change', function () {
if ($(this).prop('checked')) {
$others.prop('checked', false).trigger('change');
el.find("fieldset[data-addon-max-count]").each(function() {
// usually addons are only allowed once one per item
var multipleAllowed = this.hasAttribute("data-addon-multi-allowed");
var $inputs = $(".availability-box input", this);
var max = parseInt(this.getAttribute("data-addon-max-count"));
var desc = $(".addon-count-desc", this).text().trim();
this.addEventListener("change", function (e) {
var variations = e.target.closest(".variations");
if (variations && !multipleAllowed && e.target.checked) {
// uncheck all other checkboxes inside this variations
$(".availability-box input:checked", variations).not(e.target).prop("checked", false).trigger("change");
}
if (max === 1) {
if (e.target.checked) {
$inputs.filter(":checked").not(e.target).prop("checked", false).trigger("change");
}
return;
}
var total = $inputs.toArray().reduce(function(a, e) {
return a + (e.type == "checkbox" ? (e.checked ? parseInt(e.value) : 0) : parseInt(e.value) || 0);
}, 0);
if (total > max) {
if (e.target.type == "checkbox") {
e.target.checked = false;
} else {
e.target.value = e.target.value - (total - max);
}
$(e.target).trigger("change").closest(".availability-box").tooltip({
"title": desc,
}).tooltip('show');
e.preventDefault();
} else {
$(".availability-box", this).tooltip('destroy')
}
});
});