mirror of
https://github.com/pretix/pretix.git
synced 2026-05-08 15:44:02 +00:00
Allow dependencies between questions (#1202)
- [x] data model - [x] api - [x] backend editor - [x] backend validation logic - [x] frontend display logic - [x] frontend validation logic - [x] test checkout step - [x] test modify order in frontend - [x] test modify order in backend - [x] validation tests - [x] correctly evaluate dependency tree in frontend? - [x] copy events
This commit is contained in:
@@ -6,6 +6,7 @@ function gettext(msgid) {
|
||||
}
|
||||
return msgid;
|
||||
}
|
||||
|
||||
function ngettext(singular, plural, count) {
|
||||
if (typeof django !== 'undefined' && typeof django.ngettext !== 'undefined') {
|
||||
return django.ngettext(singular, plural, count);
|
||||
@@ -14,7 +15,7 @@ function ngettext(singular, plural, count) {
|
||||
}
|
||||
|
||||
var form_handlers = function (el) {
|
||||
el.find(".datetimepicker").each(function() {
|
||||
el.find(".datetimepicker").each(function () {
|
||||
$(this).datetimepicker({
|
||||
format: $("body").attr("data-datetimeformat"),
|
||||
locale: $("body").attr("data-datetimelocale"),
|
||||
@@ -37,7 +38,7 @@ var form_handlers = function (el) {
|
||||
}
|
||||
});
|
||||
|
||||
el.find(".datepickerfield").each(function() {
|
||||
el.find(".datepickerfield").each(function () {
|
||||
var opts = {
|
||||
format: $("body").attr("data-dateformat"),
|
||||
locale: $("body").attr("data-datetimelocale"),
|
||||
@@ -71,7 +72,7 @@ var form_handlers = function (el) {
|
||||
}
|
||||
});
|
||||
|
||||
el.find(".timepickerfield").each(function() {
|
||||
el.find(".timepickerfield").each(function () {
|
||||
var opts = {
|
||||
format: $("body").attr("data-timeformat"),
|
||||
locale: $("body").attr("data-datetimelocale"),
|
||||
@@ -90,7 +91,7 @@ var form_handlers = function (el) {
|
||||
}
|
||||
};
|
||||
$(this).datetimepicker(opts);
|
||||
});
|
||||
});
|
||||
|
||||
el.find("script[data-replace-with-qr]").each(function () {
|
||||
var $div = $("<div>");
|
||||
@@ -104,7 +105,10 @@ var form_handlers = function (el) {
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
el.find("input[name*=question], select[name*=question]").change(questions_toggle_dependent);
|
||||
questions_toggle_dependent();
|
||||
};
|
||||
|
||||
|
||||
$(function () {
|
||||
@@ -130,7 +134,7 @@ $(function () {
|
||||
$("#voucher-box").slideDown();
|
||||
$("#voucher-toggle").slideUp();
|
||||
});
|
||||
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$("#ajaxerr").on("click", ".ajaxerr-close", ajaxErrDialog.hide);
|
||||
@@ -140,7 +144,7 @@ $(function () {
|
||||
$('.toggle-variation-description').click(function () {
|
||||
$(this).parent().find('.addon-variation-description').slideToggle();
|
||||
});
|
||||
|
||||
|
||||
// Copy answers
|
||||
$(".js-copy-answers").click(function (e) {
|
||||
e.preventDefault();
|
||||
@@ -153,7 +157,7 @@ $(function () {
|
||||
// Subevent choice
|
||||
if ($(".subevent-toggle").length) {
|
||||
$(".subevent-list").hide();
|
||||
$(".subevent-toggle").css("display", "block").click(function() {
|
||||
$(".subevent-toggle").css("display", "block").click(function () {
|
||||
$(".subevent-list").slideToggle(300);
|
||||
});
|
||||
}
|
||||
@@ -165,7 +169,7 @@ $(function () {
|
||||
var update_cart_form = function () {
|
||||
var is_enabled = $(".product-row input[type=checkbox]:checked, .variations input[type=checkbox]:checked, .product-row input[type=radio]:checked, .variations input[type=radio]:checked").length;
|
||||
if (!is_enabled) {
|
||||
$(".input-item-count").each(function() {
|
||||
$(".input-item-count").each(function () {
|
||||
if ($(this).val() && $(this).val() !== "0") {
|
||||
is_enabled = true;
|
||||
}
|
||||
@@ -185,18 +189,18 @@ $(function () {
|
||||
|
||||
// Invoice address form
|
||||
$("input[data-required-if]").each(function () {
|
||||
var dependent = $(this),
|
||||
dependency = $($(this).attr("data-required-if")),
|
||||
update = function (ev) {
|
||||
var enabled = (dependency.attr("type") === 'checkbox' || dependency.attr("type") === 'radio') ? dependency.prop('checked') : !!dependency.val();
|
||||
if (!dependent.is("[data-no-required-attr]")) {
|
||||
dependent.prop('required', enabled);
|
||||
}
|
||||
dependent.closest('.form-group').toggleClass('required', enabled);
|
||||
};
|
||||
update();
|
||||
dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("change", update);
|
||||
dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("dp.change", update);
|
||||
var dependent = $(this),
|
||||
dependency = $($(this).attr("data-required-if")),
|
||||
update = function (ev) {
|
||||
var enabled = (dependency.attr("type") === 'checkbox' || dependency.attr("type") === 'radio') ? dependency.prop('checked') : !!dependency.val();
|
||||
if (!dependent.is("[data-no-required-attr]")) {
|
||||
dependent.prop('required', enabled);
|
||||
}
|
||||
dependent.closest('.form-group').toggleClass('required', enabled);
|
||||
};
|
||||
update();
|
||||
dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("change", update);
|
||||
dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("dp.change", update);
|
||||
});
|
||||
|
||||
$("input[data-display-dependency]").each(function () {
|
||||
@@ -219,16 +223,16 @@ $(function () {
|
||||
dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("dp.change", update);
|
||||
});
|
||||
|
||||
form_handlers($("body"));
|
||||
form_handlers($("body"));
|
||||
|
||||
// Lightbox
|
||||
lightbox.init();
|
||||
});
|
||||
|
||||
function copy_answers(idx) {
|
||||
var elements = $('*[data-idx="'+idx+'"] input, *[data-idx="'+idx+'"] select, *[data-idx="'+idx+'"] textarea');
|
||||
function copy_answers(idx) {
|
||||
var elements = $('*[data-idx="' + idx + '"] input, *[data-idx="' + idx + '"] select, *[data-idx="' + idx + '"] textarea');
|
||||
var firstAnswers = $('*[data-idx="0"] input, *[data-idx="0"] select, *[data-idx="0"] textarea');
|
||||
elements.each(function(index){
|
||||
elements.each(function (index) {
|
||||
var input = $(this),
|
||||
tagName = input.prop('tagName').toLowerCase(),
|
||||
attributeType = input.attr('type'),
|
||||
@@ -250,14 +254,20 @@ function copy_answers(idx) {
|
||||
break;
|
||||
case "checkbox":
|
||||
case "radio":
|
||||
input.prop("checked", firstAnswers.filter("[name$=" + suffix + "]").prop("checked"));
|
||||
if (input.attr('value')) {
|
||||
input.prop("checked", firstAnswers.filter("[name$=" + suffix + "][value=" + input.attr('value') + "]").prop("checked"));
|
||||
} else {
|
||||
input.prop("checked", firstAnswers.filter("[name$=" + suffix + "]").prop("checked"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
input.val(firstAnswers.filter("[name$=" + suffix + "]").val());
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
input.val(firstAnswers.filter("[name$=" + suffix + "]").val());
|
||||
}
|
||||
}
|
||||
});
|
||||
questions_toggle_dependent(true);
|
||||
}
|
||||
|
||||
|
||||
71
src/pretix/static/pretixpresale/js/ui/questions.js
Normal file
71
src/pretix/static/pretixpresale/js/ui/questions.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/*global $ */
|
||||
|
||||
function questions_toggle_dependent(ev) {
|
||||
function q_should_be_shown($el) {
|
||||
if (!$el.attr('data-question-dependency')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var dependency_name = $el.attr("name").split("_")[0] + "_" + $el.attr("data-question-dependency");
|
||||
var dependency_value = $el.attr("data-question-dependency-value");
|
||||
var $dependency_el;
|
||||
|
||||
if ($("select[name=" + dependency_name + "]").length) {
|
||||
// dependency is type C
|
||||
$dependency_el = $("select[name=" + dependency_name + "]");
|
||||
if (!$dependency_el.closest(".form-group").hasClass("dependency-hidden")) { // do not show things that depend on hidden things
|
||||
return q_should_be_shown($dependency_el) && $dependency_el.val() === dependency_value;
|
||||
}
|
||||
} else if ($("input[type=checkbox][name=" + dependency_name + "]").length) {
|
||||
// dependency type is B or M
|
||||
if (dependency_value === "True" || dependency_value === "False") {
|
||||
$dependency_el = $("input[name=" + dependency_name + "]");
|
||||
if (!$dependency_el.closest(".form-group").hasClass("dependency-hidden")) { // do not show things that depend on hidden things
|
||||
if (dependency_value === "True") {
|
||||
return q_should_be_shown($dependency_el) && $dependency_el.prop('checked');
|
||||
} else {
|
||||
return q_should_be_shown($dependency_el) && !$dependency_el.prop('checked');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$dependency_el = $("input[value=" + dependency_value + "][name=" + dependency_name + "]");
|
||||
if (!$dependency_el.closest(".form-group").hasClass("dependency-hidden")) { // do not show things that depend on hidden things
|
||||
return q_should_be_shown($dependency_el) && $dependency_el.prop('checked');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$("[data-question-dependency]").each(function () {
|
||||
var $dependent = $(this).closest(".form-group");
|
||||
var is_shown = !$dependent.hasClass("dependency-hidden");
|
||||
var should_be_shown = q_should_be_shown($(this));
|
||||
|
||||
if (should_be_shown && !is_shown) {
|
||||
$dependent.stop().removeClass("dependency-hidden");
|
||||
if (!ev) {
|
||||
$dependent.show();
|
||||
} else {
|
||||
$dependent.slideDown();
|
||||
}
|
||||
$dependent.find("input.required-hidden, select.required-hidden, textarea.required-hidden").each(function () {
|
||||
$(this).prop("required", true).removeClass("required-hidden");
|
||||
});
|
||||
} else if (!should_be_shown && is_shown) {
|
||||
if ($dependent.hasClass("has-error") || $dependent.find(".has-error").length) {
|
||||
// Do not hide things with invalid validation
|
||||
return;
|
||||
}
|
||||
$dependent.stop().addClass("dependency-hidden");
|
||||
if (!ev) {
|
||||
$dependent.hide();
|
||||
} else {
|
||||
$dependent.slideUp();
|
||||
}
|
||||
$dependent.find("input[required], select[required], textarea[required]").each(function () {
|
||||
$(this).prop("required", false).addClass("required-hidden");
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user