forked from CGM_Public/pretix_original
Address form: Reduce useless XHR calls
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
// Responses are expected to only depend on the GET parameters passed, so we can have a little client-side cache
|
||||
// to prevent fetching the same thing many times.
|
||||
var responseCache = {};
|
||||
|
||||
$("[data-address-information-url]").each(function () {
|
||||
let xhr;
|
||||
const form = $(this);
|
||||
@@ -21,6 +25,75 @@ $(function () {
|
||||
dependents[$(this).attr("name").split("-").pop()] = $(this)
|
||||
})
|
||||
|
||||
if (!Object.values(dependents).some((el) => el.length)) {
|
||||
// No address fields found, do not create request
|
||||
return;
|
||||
}
|
||||
|
||||
const update_form = function (data) {
|
||||
var selected_state = dependents.state.prop("data-selected-value");
|
||||
if (selected_state) dependents.state.prop("data-selected-value", "");
|
||||
dependents.state.find("option:not([value=''])").remove();
|
||||
$.each(data.data, function (k, s) {
|
||||
var o = $("<option>").attr("value", s.code).text(s.name);
|
||||
if (selected_state === s.code) o.prop("selected", true);
|
||||
dependents.state.append(o);
|
||||
});
|
||||
|
||||
if (dependents.transmission_type) {
|
||||
var selected_transmission_type = dependents.transmission_type.prop("data-selected-value");
|
||||
if (selected_transmission_type) dependents.transmission_type.prop("data-selected-value", "");
|
||||
dependents.transmission_type.find("option:not([value='']):not([value='-'])").remove();
|
||||
|
||||
if (!data.transmission_type.visible) {
|
||||
selected_transmission_type = "email";
|
||||
}
|
||||
|
||||
$.each(data.transmission_types, function (k, s) {
|
||||
var o = $("<option>").attr("value", s.code).text(s.name);
|
||||
if (selected_transmission_type === s.code) {
|
||||
o.prop("selected", true);
|
||||
}
|
||||
dependents.transmission_type.append(o);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
for (var k in dependents) {
|
||||
const options = data[k],
|
||||
dependent = dependents[k];
|
||||
let visible = 'visible' in options ? options.visible : true;
|
||||
|
||||
if (dependent.is("[data-display-dependency]")) {
|
||||
const dependency = $(dependent.attr("data-display-dependency"));
|
||||
visible = visible && (
|
||||
(dependency.attr("type") === 'checkbox' || dependency.attr("type") === 'radio') ? dependency.prop('checked') : !!dependency.val()
|
||||
);
|
||||
}
|
||||
|
||||
if ('label' in options) {
|
||||
dependent.closest(".form-group").find(".control-label").text(options.label);
|
||||
}
|
||||
|
||||
const required = 'required' in options && visible && (
|
||||
(options.required === 'if_any' && isAnyRequired) ||
|
||||
(options.required === true)
|
||||
);
|
||||
dependent.closest(".form-group").toggle(visible).toggleClass('required', required);
|
||||
dependent.prop("required", required);
|
||||
|
||||
const label = dependent.closest(".form-group").find("label");
|
||||
const labelRequired = label.find(".label-required");
|
||||
if (!required) {
|
||||
labelRequired.remove();
|
||||
} else if (!labelRequired.length) {
|
||||
label.append('<i class="label-required">' + gettext('required') + '</i>')
|
||||
}
|
||||
}
|
||||
for (var k in dependents) dependents[k].prop("disabled", false);
|
||||
loader.hide();
|
||||
}
|
||||
|
||||
const update = function (ev) {
|
||||
if (xhr) {
|
||||
xhr.abort();
|
||||
@@ -45,79 +118,36 @@ $(function () {
|
||||
if (dependents.transmission_type) {
|
||||
url.searchParams.append("transmission_type_required", !dependents.transmission_type.find("option[value='-']").length);
|
||||
}
|
||||
xhr = $.getJSON(url, function (data) {
|
||||
var selected_state = dependents.state.prop("data-selected-value");
|
||||
if (selected_state) dependents.state.prop("data-selected-value", "");
|
||||
dependents.state.find("option:not([value=''])").remove();
|
||||
$.each(data.data, function (k, s) {
|
||||
var o = $("<option>").attr("value", s.code).text(s.name);
|
||||
if (selected_state === s.code) o.prop("selected", true);
|
||||
dependents.state.append(o);
|
||||
});
|
||||
|
||||
if (dependents.transmission_type) {
|
||||
var selected_transmission_type = dependents.transmission_type.prop("data-selected-value");
|
||||
if (selected_transmission_type) dependents.transmission_type.prop("data-selected-value", "");
|
||||
dependents.transmission_type.find("option:not([value='']):not([value='-'])").remove();
|
||||
|
||||
if (!data.transmission_type.visible) {
|
||||
selected_transmission_type = "email";
|
||||
}
|
||||
|
||||
$.each(data.transmission_types, function (k, s) {
|
||||
var o = $("<option>").attr("value", s.code).text(s.name);
|
||||
if (selected_transmission_type === s.code) {
|
||||
o.prop("selected", true);
|
||||
}
|
||||
dependents.transmission_type.append(o);
|
||||
if (!(url in responseCache)) {
|
||||
responseCache[url] = new Promise((resolve, reject) => {
|
||||
xhr = $.ajax({
|
||||
dataType: "json",
|
||||
url: url,
|
||||
timeout: 3000,
|
||||
success: resolve,
|
||||
}).fail(function(){
|
||||
reject();
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (var k in dependents) {
|
||||
const options = data[k],
|
||||
dependent = dependents[k];
|
||||
let visible = 'visible' in options ? options.visible : true;
|
||||
|
||||
if (dependent.is("[data-display-dependency]")) {
|
||||
const dependency = $(dependent.attr("data-display-dependency"));
|
||||
visible = visible && (
|
||||
(dependency.attr("type") === 'checkbox' || dependency.attr("type") === 'radio') ? dependency.prop('checked') : !!dependency.val()
|
||||
);
|
||||
}
|
||||
|
||||
if ('label' in options) {
|
||||
dependent.closest(".form-group").find(".control-label").text(options.label);
|
||||
}
|
||||
|
||||
const required = 'required' in options && visible && (
|
||||
(options.required === 'if_any' && isAnyRequired) ||
|
||||
(options.required === true)
|
||||
);
|
||||
dependent.closest(".form-group").toggle(visible).toggleClass('required', required);
|
||||
dependent.prop("required", required);
|
||||
|
||||
const label = dependent.closest(".form-group").find("label");
|
||||
const labelRequired = label.find(".label-required");
|
||||
if (!required) {
|
||||
labelRequired.remove();
|
||||
} else if (!labelRequired.length) {
|
||||
label.append('<i class="label-required">' + gettext('required') + '</i>')
|
||||
}
|
||||
}
|
||||
for (var k in dependents) dependents[k].prop("disabled", false);
|
||||
}).always(function() {
|
||||
loader.hide();
|
||||
}).fail(function(){
|
||||
Promise.resolve(responseCache[url]).then(function (data) {
|
||||
responseCache[url] = data;
|
||||
update_form(data);
|
||||
}).catch(function () {
|
||||
delete responseCache[url];
|
||||
// In case of errors, show everything and require nothing, we can still handle errors in backend
|
||||
for(var k in dependents) {
|
||||
for (var k in dependents) {
|
||||
const dependent = dependents[k],
|
||||
visible = true,
|
||||
required = false;
|
||||
|
||||
dependent.closest(".form-group").toggle(visible).toggleClass('required', required);
|
||||
dependent.prop("required", required);
|
||||
dependent.prop("required", required).prop("disabled", false);
|
||||
}
|
||||
}).finally(function () {
|
||||
loader.hide();
|
||||
});
|
||||
};
|
||||
update();
|
||||
|
||||
Reference in New Issue
Block a user