ESlint: Ignore vendored and pre-vue code (#6541)

* ESlint: Ignore vendored and pre-vue code

* Format pre-vue code with eslint where possible

---------

Co-authored-by: Kara Engelhardt <engelhardt@pretix.eu>
This commit is contained in:
Raphael Michel
2026-09-10 12:35:10 +02:00
committed by GitHub
co-authored by Kara Engelhardt
parent d9b5fa5b16
commit d85e52c83e
55 changed files with 10025 additions and 10014 deletions
@@ -1,183 +1,183 @@
/*global $, gettext*/
/* global gettext */
var bankimport_transactionlist = {
_btn_click: function (e) {
console.log(e.delegateTarget);
var trans_id = parseInt($(e.delegateTarget).attr("name").split("_")[1]);
var value = $(e.delegateTarget).val();
if (value === "discard") {
bankimport_transactionlist.discard(trans_id);
} else if (value === "accept") {
bankimport_transactionlist.accept(trans_id);
} else if (value === "retry") {
bankimport_transactionlist.retry(trans_id);
} else if (value === "assign") {
bankimport_transactionlist.assign(trans_id);
}
return false;
},
_btn_click: function (e) {
console.log(e.delegateTarget)
let trans_id = parseInt($(e.delegateTarget).attr('name').split('_')[1])
let value = $(e.delegateTarget).val()
if (value === 'discard') {
bankimport_transactionlist.discard(trans_id)
} else if (value === 'accept') {
bankimport_transactionlist.accept(trans_id)
} else if (value === 'retry') {
bankimport_transactionlist.retry(trans_id)
} else if (value === 'assign') {
bankimport_transactionlist.assign(trans_id)
}
return false
},
_action: function (id, action, success) {
$("tr[data-id=" + id + "] button").prop("disabled", true);
var data = {
"csrfmiddlewaretoken": $("[name=csrfmiddlewaretoken]").val()
};
data["action_" + id] = action;
$.ajax({
"method": "POST",
"url": $(".transaction-list").attr("data-url"),
"data": data,
"dataType": "json",
"success": function (data) {
if (data.status == "ok") {
$("tr[data-id=" + id + "]").removeClass("has-error");
if (data.comment) {
bankimport_transactionlist.comment_reset_to_text(id, data.comment, data.plain);
}
success();
} else {
$("tr[data-id=" + id + "] button").prop("disabled", false);
$("tr[data-id=" + id + "] .help-block").remove();
$("tr[data-id=" + id + "]").addClass("has-error");
$("<p>").addClass("help-block").text(data.message).appendTo($("tr[data-id=" + id + "] td.actions"));
}
}
});
},
_action: function (id, action, success) {
$('tr[data-id=' + id + '] button').prop('disabled', true)
let data = {
csrfmiddlewaretoken: $('[name=csrfmiddlewaretoken]').val()
}
data['action_' + id] = action
$.ajax({
method: 'POST',
url: $('.transaction-list').attr('data-url'),
data: data,
dataType: 'json',
success: function (data) {
if (data.status == 'ok') {
$('tr[data-id=' + id + ']').removeClass('has-error')
if (data.comment) {
bankimport_transactionlist.comment_reset_to_text(id, data.comment, data.plain)
}
success()
} else {
$('tr[data-id=' + id + '] button').prop('disabled', false)
$('tr[data-id=' + id + '] .help-block').remove()
$('tr[data-id=' + id + ']').addClass('has-error')
$('<p>').addClass('help-block').text(data.message).appendTo($('tr[data-id=' + id + '] td.actions'))
}
}
})
},
discard: function (id) {
bankimport_transactionlist._action(id, "discard", function () {
$("tr[data-id=" + id + "] td").remove();
});
},
discard: function (id) {
bankimport_transactionlist._action(id, 'discard', function () {
$('tr[data-id=' + id + '] td').remove()
})
},
retry: function (id) {
bankimport_transactionlist._action(id, "retry", function () {
$("tr[data-id=" + id + "] td.actions").html('').text(gettext("Marked as paid"));
});
},
retry: function (id) {
bankimport_transactionlist._action(id, 'retry', function () {
$('tr[data-id=' + id + '] td.actions').html('').text(gettext('Marked as paid'))
})
},
accept: function (id) {
bankimport_transactionlist._action(id, "accept", function () {
$("tr[data-id=" + id + "] td.actions").html('').text(gettext("Marked as paid"));
});
},
accept: function (id) {
bankimport_transactionlist._action(id, 'accept', function () {
$('tr[data-id=' + id + '] td.actions').html('').text(gettext('Marked as paid'))
})
},
assign: function (id) {
bankimport_transactionlist._action(id, "assign:" + $("tr[data-id=" + id + "] input.form-control:not(.tt-hint)").val(), function () {
$("tr[data-id=" + id + "] td.actions").html('').text(gettext("Marked as paid"));
});
},
assign: function (id) {
bankimport_transactionlist._action(id, 'assign:' + $('tr[data-id=' + id + '] input.form-control:not(.tt-hint)').val(), function () {
$('tr[data-id=' + id + '] td.actions').html('').text(gettext('Marked as paid'))
})
},
comment_reset_to_text: function (id, text, plain) {
var $box = $("tr[data-id=" + id + "] .comment-box");
$box[0].dataset["plain"] = plain;
$box.html("")
.append($("<strong>").text(gettext("Comment:")))
.append(" ")
.append($("<span>").addClass("comment").append(" ").append(text))
.append(" ")
.append($("<a>").addClass("comment-modify btn btn-default btn-xs")
.append("<span class='fa fa-edit'></span>"));
},
comment_reset_to_text: function (id, text, plain) {
let $box = $('tr[data-id=' + id + '] .comment-box')
$box[0].dataset['plain'] = plain
$box.html('')
.append($('<strong>').text(gettext('Comment:')))
.append(' ')
.append($('<span>').addClass('comment').append(' ').append(text))
.append(' ')
.append($('<a>').addClass('comment-modify btn btn-default btn-xs')
.append('<span class=\'fa fa-edit\'></span>'))
},
comment_start_edit: function (e) {
var $box = $(e.target).closest("div");
var id = $box.closest("tr").attr("data-id");
var $inp = $("<textarea>").addClass("form-control");
var orig_rendered = $box.find(".comment");
var orig_text = $box[0].dataset.plain;
$inp.val(orig_text);
comment_start_edit: function (e) {
let $box = $(e.target).closest('div')
let id = $box.closest('tr').attr('data-id')
let $inp = $('<textarea>').addClass('form-control')
let orig_rendered = $box.find('.comment')
let orig_text = $box[0].dataset.plain
$inp.val(orig_text)
var $btngrp = $("<div>");
$btngrp.addClass("btn-group");
var $btn1 = $("<button>");
$btn1.attr("type", "button").addClass("btn btn-default");
$btn1.append("<span class='fa fa-check'></span>");
$btngrp.append($btn1);
var $btn2 = $("<button>");
$btn2.attr("type", "button").addClass("btn btn-default");
$btn2.append("<span class='fa fa-close'></span>");
$btngrp.append($btn2);
$box.html("").append($inp).append($btngrp);
$btn1.click(function () {
var text = $box.find("textarea").val();
$box.find("input, textarea, button").prop("disabled", true);
bankimport_transactionlist._action(id, "comment:" + text, function () {
$("tr[data-id=" + id + "] button").prop("disabled", false);
});
});
$btn2.click(function () {
bankimport_transactionlist.comment_reset_to_text(id, orig_rendered, orig_text);
});
let $btngrp = $('<div>')
$btngrp.addClass('btn-group')
let $btn1 = $('<button>')
$btn1.attr('type', 'button').addClass('btn btn-default')
$btn1.append('<span class=\'fa fa-check\'></span>')
$btngrp.append($btn1)
let $btn2 = $('<button>')
$btn2.attr('type', 'button').addClass('btn btn-default')
$btn2.append('<span class=\'fa fa-close\'></span>')
$btngrp.append($btn2)
$box.html('').append($inp).append($btngrp)
$btn1.click(function () {
let text = $box.find('textarea').val()
$box.find('input, textarea, button').prop('disabled', true)
bankimport_transactionlist._action(id, 'comment:' + text, function () {
$('tr[data-id=' + id + '] button').prop('disabled', false)
})
})
$btn2.click(function () {
bankimport_transactionlist.comment_reset_to_text(id, orig_rendered, orig_text)
})
e.preventDefault();
},
e.preventDefault()
},
typeahead_source: function () {
return new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: $(".transaction-list").attr("data-url"),
prepare: function (query, settings) {
settings.url = settings.url + '?query=' + encodeURIComponent(query);
return settings;
},
transform: function (object) {
var results = object.results;
var suggs = [];
var reslen = results.length;
for (var i = 0; i < reslen; i++) {
suggs.push(results[i]);
}
return suggs;
}
}
});
},
typeahead_source: function () {
return new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: $('.transaction-list').attr('data-url'),
prepare: function (query, settings) {
settings.url = settings.url + '?query=' + encodeURIComponent(query)
return settings
},
transform: function (object) {
let results = object.results
let suggs = []
let reslen = results.length
for (let i = 0; i < reslen; i++) {
suggs.push(results[i])
}
return suggs
}
}
})
},
init: function () {
if ($(".transaction-list").length) {
$(".transaction-list button").click(bankimport_transactionlist._btn_click);
init: function () {
if ($('.transaction-list').length) {
$('.transaction-list button').click(bankimport_transactionlist._btn_click)
$(".transaction-list").on("click", ".comment-modify", bankimport_transactionlist.comment_start_edit);
$('.transaction-list').on('click', '.comment-modify', bankimport_transactionlist.comment_start_edit)
$(".transaction-list .form-control").typeahead(null, {
minLength: 2,
name: 'order-dataset',
source: bankimport_transactionlist.typeahead_source(),
display: function (obj) {
return obj.code;
},
templates: {
suggestion: function (obj) {
return '<div>' + obj.code + ' (' + obj.total + ', ' + obj.status + ')</div>';
}
}
}).keypress(function (e) {
if (e.keyCode === 13) {
$(this).parent().parent().find("button[value=assign]").click();
}
});
}
$('.transaction-list .form-control').typeahead(null, {
minLength: 2,
name: 'order-dataset',
source: bankimport_transactionlist.typeahead_source(),
display: function (obj) {
return obj.code
},
templates: {
suggestion: function (obj) {
return '<div>' + obj.code + ' (' + obj.total + ', ' + obj.status + ')</div>'
}
}
}).keypress(function (e) {
if (e.keyCode === 13) {
$(this).parent().parent().find('button[value=assign]').click()
}
})
}
if ($("[data-job-waiting]").length) {
window.setTimeout(bankimport_transactionlist.check_state, 750);
}
},
if ($('[data-job-waiting]').length) {
window.setTimeout(bankimport_transactionlist.check_state, 750)
}
},
check_state: function () {
$.getJSON($("[data-job-waiting-url]").attr("data-job-waiting-url"), function (data) {
if (data.state == 'running' || data.state == 'pending') {
window.setTimeout(bankimport_transactionlist.check_state, 750);
} else {
location.reload();
}
});
}
};
check_state: function () {
$.getJSON($('[data-job-waiting-url]').attr('data-job-waiting-url'), function (data) {
if (data.state == 'running' || data.state == 'pending') {
window.setTimeout(bankimport_transactionlist.check_state, 750)
} else {
location.reload()
}
})
}
}
$(function () {
bankimport_transactionlist.init();
});
bankimport_transactionlist.init()
})
@@ -1,350 +1,350 @@
/*global $, paypal_client_id, paypal_loadingmessage, gettext */
'use strict';
/* global paypal_client_id, paypal_loadingmessage, gettext */
'use strict'
var pretixpaypal = {
paypal: null,
client_id: null,
order_id: null,
payer_id: null,
merchant_id: null,
currency: null,
method: null,
additional_disabled_funding: null,
additional_enabled_funding: null,
debug_buyer_country: null,
continue_button: null,
paypage: false,
method_map: {
wallet: {
method: 'wallet',
funding_source: 'paypal',
//disable_funding: null,
//enable_funding: 'paylater',
early_auth: true,
},
apm: {
method: 'apm',
funding_source: null,
//disable_funding: null,
//enable_funding: null,
early_auth: false,
}
},
apm_map: {
paypal: gettext('PayPal'),
venmo: gettext('Venmo'),
applepay: gettext('Apple Pay'),
itau: gettext('Itaú'),
credit: gettext('PayPal Credit'),
card: gettext('Credit Card'),
paylater: gettext('PayPal Pay Later'),
ideal: gettext('iDEAL | Wero'),
sepa: gettext('SEPA Direct Debit'),
bancontact: gettext('Bancontact'),
giropay: gettext('giropay'),
sofort: gettext('SOFORT'),
eps: gettext('eps'),
mybank: gettext('MyBank'),
p24: gettext('Przelewy24'),
verkkopankki: gettext('Verkkopankki'),
payu: gettext('PayU'),
blik: gettext('BLIK'),
trustly: gettext('Trustly'),
zimpler: gettext('Zimpler'),
maxima: gettext('Maxima'),
oxxo: gettext('OXXO'),
boleto: gettext('Boleto'),
wechatpay: gettext('WeChat Pay'),
mercadopago: gettext('Mercado Pago')
},
readyToSubmitApproval: false,
paypal: null,
client_id: null,
order_id: null,
payer_id: null,
merchant_id: null,
currency: null,
method: null,
additional_disabled_funding: null,
additional_enabled_funding: null,
debug_buyer_country: null,
continue_button: null,
paypage: false,
method_map: {
wallet: {
method: 'wallet',
funding_source: 'paypal',
// disable_funding: null,
// enable_funding: 'paylater',
early_auth: true,
},
apm: {
method: 'apm',
funding_source: null,
// disable_funding: null,
// enable_funding: null,
early_auth: false,
}
},
apm_map: {
paypal: gettext('PayPal'),
venmo: gettext('Venmo'),
applepay: gettext('Apple Pay'),
itau: gettext('Itaú'),
credit: gettext('PayPal Credit'),
card: gettext('Credit Card'),
paylater: gettext('PayPal Pay Later'),
ideal: gettext('iDEAL | Wero'),
sepa: gettext('SEPA Direct Debit'),
bancontact: gettext('Bancontact'),
giropay: gettext('giropay'),
sofort: gettext('SOFORT'),
eps: gettext('eps'),
mybank: gettext('MyBank'),
p24: gettext('Przelewy24'),
verkkopankki: gettext('Verkkopankki'),
payu: gettext('PayU'),
blik: gettext('BLIK'),
trustly: gettext('Trustly'),
zimpler: gettext('Zimpler'),
maxima: gettext('Maxima'),
oxxo: gettext('OXXO'),
boleto: gettext('Boleto'),
wechatpay: gettext('WeChat Pay'),
mercadopago: gettext('Mercado Pago')
},
readyToSubmitApproval: false,
load: function () {
if (pretixpaypal.paypal === null) {
pretixpaypal.client_id = $.trim($("#paypal_client_id").html());
pretixpaypal.merchant_id = $.trim($("#paypal_merchant_id").html());
pretixpaypal.debug_buyer_country = $.trim($("#paypal_buyer_country").html());
pretixpaypal.continue_button = $('.checkout-button-row').closest("form").find(".checkout-button-row .btn-primary");
pretixpaypal.continue_button.closest('div').append('<div id="paypal-button-container"></div>');
pretixpaypal.additional_disabled_funding = $.trim($("#paypal_disable_funding").html());
pretixpaypal.additional_enabled_funding = $.trim($("#paypal_enable_funding").html());
pretixpaypal.paypage = Boolean($('#paypal-button-container').data('paypage'));
pretixpaypal.order_id = $.trim($("#paypal_oid").html());
pretixpaypal.currency = $("body").attr("data-currency");
pretixpaypal.locale = this.guessLocale();
}
load: function () {
if (pretixpaypal.paypal === null) {
pretixpaypal.client_id = $.trim($('#paypal_client_id').html())
pretixpaypal.merchant_id = $.trim($('#paypal_merchant_id').html())
pretixpaypal.debug_buyer_country = $.trim($('#paypal_buyer_country').html())
pretixpaypal.continue_button = $('.checkout-button-row').closest('form').find('.checkout-button-row .btn-primary')
pretixpaypal.continue_button.closest('div').append('<div id="paypal-button-container"></div>')
pretixpaypal.additional_disabled_funding = $.trim($('#paypal_disable_funding').html())
pretixpaypal.additional_enabled_funding = $.trim($('#paypal_enable_funding').html())
pretixpaypal.paypage = Boolean($('#paypal-button-container').data('paypage'))
pretixpaypal.order_id = $.trim($('#paypal_oid').html())
pretixpaypal.currency = $('body').attr('data-currency')
pretixpaypal.locale = this.guessLocale()
}
$("input[name=payment][value^='paypal']").change(function () {
if (pretixpaypal.paypal !== null) {
pretixpaypal.renderButton($(this).val());
} else {
pretixpaypal.continue_button.prop("disabled", true);
}
});
$('input[name=payment][value^=\'paypal\']').change(function () {
if (pretixpaypal.paypal !== null) {
pretixpaypal.renderButton($(this).val())
} else {
pretixpaypal.continue_button.prop('disabled', true)
}
})
$("input[name=payment]").not("[value^='paypal']").change(function () {
pretixpaypal.restore();
});
$('input[name=payment]').not('[value^=\'paypal\']').change(function () {
pretixpaypal.restore()
})
// If paypal is pre-selected, we must disable the continue button and handle it after SDK is loaded
if ($("input[name=payment][value^='paypal']").is(':checked')) {
pretixpaypal.continue_button.prop("disabled", true);
}
// If paypal is pre-selected, we must disable the continue button and handle it after SDK is loaded
if ($('input[name=payment][value^=\'paypal\']').is(':checked')) {
pretixpaypal.continue_button.prop('disabled', true)
}
// We are setting the cogwheel already here, as the renderAPM() method might take some time to get loaded.
const apmtextselector = $("input[name=payment][value=paypal_apm]").closest("label").find(".accordion-label-text");
apmtextselector.append(' <span aria-hidden="true" class="fa fa-cog fa-spin"></span>');
// We are setting the cogwheel already here, as the renderAPM() method might take some time to get loaded.
const apmtextselector = $('input[name=payment][value=paypal_apm]').closest('label').find('.accordion-label-text')
apmtextselector.append(' <span aria-hidden="true" class="fa fa-cog fa-spin"></span>')
let sdk_url = 'https://www.paypal.com/sdk/js' +
'?client-id=' + pretixpaypal.client_id +
'&components=buttons,funding-eligibility' +
'&currency=' + pretixpaypal.currency;
let sdk_url = 'https://www.paypal.com/sdk/js'
+ '?client-id=' + pretixpaypal.client_id
+ '&components=buttons,funding-eligibility'
+ '&currency=' + pretixpaypal.currency
if (pretixpaypal.locale) {
sdk_url += '&locale=' + pretixpaypal.locale;
}
if (pretixpaypal.locale) {
sdk_url += '&locale=' + pretixpaypal.locale
}
if (pretixpaypal.merchant_id) {
sdk_url += '&merchant-id=' + pretixpaypal.merchant_id;
}
if (pretixpaypal.merchant_id) {
sdk_url += '&merchant-id=' + pretixpaypal.merchant_id
}
if (pretixpaypal.additional_disabled_funding) {
sdk_url += '&disable-funding=' + [pretixpaypal.additional_disabled_funding].filter(Boolean).join(',');
}
if (pretixpaypal.additional_disabled_funding) {
sdk_url += '&disable-funding=' + [pretixpaypal.additional_disabled_funding].filter(Boolean).join(',')
}
if (pretixpaypal.additional_enabled_funding) {
sdk_url += '&enable-funding=' + [pretixpaypal.additional_enabled_funding].filter(Boolean).join(',');
}
if (pretixpaypal.additional_enabled_funding) {
sdk_url += '&enable-funding=' + [pretixpaypal.additional_enabled_funding].filter(Boolean).join(',')
}
if (pretixpaypal.debug_buyer_country) {
sdk_url += '&buyer-country=' + pretixpaypal.debug_buyer_country;
}
if (pretixpaypal.debug_buyer_country) {
sdk_url += '&buyer-country=' + pretixpaypal.debug_buyer_country
}
let ppscript = document.createElement('script');
let ready = false;
let head = document.getElementsByTagName("head")[0];
ppscript.setAttribute('src', sdk_url);
ppscript.setAttribute('data-csp-nonce', $.trim($("#csp_nonce").html()));
ppscript.setAttribute('data-page-type', 'checkout');
ppscript.setAttribute('data-partner-attribution-id', 'ramiioGmbH_Cart_PPCP');
document.head.appendChild(ppscript);
let ppscript = document.createElement('script')
let ready = false
let head = document.getElementsByTagName('head')[0]
ppscript.setAttribute('src', sdk_url)
ppscript.setAttribute('data-csp-nonce', $.trim($('#csp_nonce').html()))
ppscript.setAttribute('data-page-type', 'checkout')
ppscript.setAttribute('data-partner-attribution-id', 'ramiioGmbH_Cart_PPCP')
document.head.appendChild(ppscript)
ppscript.onload = ppscript.onreadystatechange = function () {
if (!ready && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
ready = true;
ppscript.onload = ppscript.onreadystatechange = function () {
if (!ready && (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')) {
ready = true
pretixpaypal.paypal = paypal;
pretixpaypal.paypal = paypal
// Handle memory leak in IE
ppscript.onload = ppscript.onreadystatechange = null;
if (head && ppscript.parentNode) {
head.removeChild(ppscript);
}
}
};
// Handle memory leak in IE
ppscript.onload = ppscript.onreadystatechange = null
if (head && ppscript.parentNode) {
head.removeChild(ppscript)
}
}
}
document.addEventListener("visibilitychange", this.onApproveSubmit);
},
document.addEventListener('visibilitychange', this.onApproveSubmit)
},
ready: function () {
if ($("input[name=payment][value=paypal_apm]").length > 0) {
pretixpaypal.renderAPMs();
}
ready: function () {
if ($('input[name=payment][value=paypal_apm]').length > 0) {
pretixpaypal.renderAPMs()
}
if ($("input[name=payment][value^='paypal']").is(':checked')) {
pretixpaypal.renderButton($("input[name=payment][value^='paypal']:checked").val());
} else if ($(".payment-redo-form").length) {
pretixpaypal.renderButton($("input[name=payment][value^='paypal']").val());
} else if ($('#paypal-button-container').data('paypage')) {
pretixpaypal.renderButton('paypal_apm');
}
},
if ($('input[name=payment][value^=\'paypal\']').is(':checked')) {
pretixpaypal.renderButton($('input[name=payment][value^=\'paypal\']:checked').val())
} else if ($('.payment-redo-form').length) {
pretixpaypal.renderButton($('input[name=payment][value^=\'paypal\']').val())
} else if ($('#paypal-button-container').data('paypage')) {
pretixpaypal.renderButton('paypal_apm')
}
},
restore: function () {
// if PayPal has not been initialized, there shouldn't be anything to cleanup
if (pretixpaypal.paypal !== null) {
$('#paypal-button-container').empty()
pretixpaypal.continue_button.text(gettext('Continue'));
pretixpaypal.continue_button.show();
}
pretixpaypal.continue_button.prop("disabled", false);
},
restore: function () {
// if PayPal has not been initialized, there shouldn't be anything to cleanup
if (pretixpaypal.paypal !== null) {
$('#paypal-button-container').empty()
pretixpaypal.continue_button.text(gettext('Continue'))
pretixpaypal.continue_button.show()
}
pretixpaypal.continue_button.prop('disabled', false)
},
renderButton: function (method) {
if (method === 'paypal') {
method = "wallet"
} else {
method = method.split('paypal_').at(-1)
}
pretixpaypal.method = pretixpaypal.method_map[method];
renderButton: function (method) {
if (method === 'paypal') {
method = 'wallet'
} else {
method = method.split('paypal_').at(-1)
}
pretixpaypal.method = pretixpaypal.method_map[method]
if (pretixpaypal.method.method === 'apm' && !pretixpaypal.paypage) {
pretixpaypal.restore();
return;
}
if (pretixpaypal.method.method === 'apm' && !pretixpaypal.paypage) {
pretixpaypal.restore()
return
}
$('#paypal-button-container').empty()
$('#paypal-card-container').empty()
$('#paypal-button-container').empty()
$('#paypal-card-container').empty()
let button = pretixpaypal.paypal.Buttons({
fundingSource: pretixpaypal.method.funding_source,
style: {
layout: pretixpaypal.method.early_auth ? 'horizontal' : 'vertical',
//color: 'white',
shape: 'rect',
label: 'pay',
tagline: false
},
createOrder: function (data, actions) {
if (pretixpaypal.order_id) {
return pretixpaypal.order_id;
}
let button = pretixpaypal.paypal.Buttons({
fundingSource: pretixpaypal.method.funding_source,
style: {
layout: pretixpaypal.method.early_auth ? 'horizontal' : 'vertical',
// color: 'white',
shape: 'rect',
label: 'pay',
tagline: false
},
createOrder: function (data, actions) {
if (pretixpaypal.order_id) {
return pretixpaypal.order_id
}
// On the paypal:pay view, we already pregenerated the OID.
// Since this view is also only used for APMs, we only need the XHR-calls for the Smart Payment Buttons.
if (pretixpaypal.paypage) {
return $("#payment_paypal_" + pretixpaypal.method.method + "_oid");
} else {
var xhrurl = $("#payment_paypal_" + pretixpaypal.method.method + "_xhr").val();
}
// On the paypal:pay view, we already pregenerated the OID.
// Since this view is also only used for APMs, we only need the XHR-calls for the Smart Payment Buttons.
if (pretixpaypal.paypage) {
return $('#payment_paypal_' + pretixpaypal.method.method + '_oid')
} else {
var xhrurl = $('#payment_paypal_' + pretixpaypal.method.method + '_xhr').val()
}
return fetch(xhrurl, {
method: 'POST'
}).then(function (res) {
return res.json();
}).then(function (data) {
if ('id' in data) {
return data.id;
} else {
// Refreshing the page to surface the request-error message
location.reload();
}
});
},
onApprove: function (data, actions) {
waitingDialog.show(gettext("Confirming your payment …"));
pretixpaypal.order_id = data.orderID;
pretixpaypal.payer_id = data.payerID;
return fetch(xhrurl, {
method: 'POST'
}).then(function (res) {
return res.json()
}).then(function (data) {
if ('id' in data) {
return data.id
} else {
// Refreshing the page to surface the request-error message
location.reload()
}
})
},
onApprove: function (data, actions) {
waitingDialog.show(gettext('Confirming your payment …'))
pretixpaypal.order_id = data.orderID
pretixpaypal.payer_id = data.payerID
let method = pretixpaypal.paypage ? "wallet" : pretixpaypal.method.method;
let selectorstub = "#payment_paypal_" + method;
// Insert the tokens into the form, so it gets submitted to the server
$(selectorstub + "_oid").val(pretixpaypal.order_id);
$(selectorstub + "_payer").val(pretixpaypal.payer_id);
let method = pretixpaypal.paypage ? 'wallet' : pretixpaypal.method.method
let selectorstub = '#payment_paypal_' + method
// Insert the tokens into the form, so it gets submitted to the server
$(selectorstub + '_oid').val(pretixpaypal.order_id)
$(selectorstub + '_payer').val(pretixpaypal.payer_id)
// We are moving the submission to a separate function, which is also an EventListener, since
// SFSafariView refuses to submit a form that is not visible. Unfortunately, that is exactly the case
// when the ticket shop is used on iOS within an SFSafariView and the PayPal payment popup has not
// closed itself quickly enough.
pretixpaypal.readyToSubmitApproval = true;
pretixpaypal.onApproveSubmit();
// We are moving the submission to a separate function, which is also an EventListener, since
// SFSafariView refuses to submit a form that is not visible. Unfortunately, that is exactly the case
// when the ticket shop is used on iOS within an SFSafariView and the PayPal payment popup has not
// closed itself quickly enough.
pretixpaypal.readyToSubmitApproval = true
pretixpaypal.onApproveSubmit()
// billingToken: null
// facilitatorAccessToken: "A21AAL_fEu0gDD-sIXyOy65a6MjgSJJrhmxuPcxxUGnL5gW2DzTxiiAksfoC4x8hD-BjeY1LsFVKl7ceuO7UR1a9pQr8Q_AVw"
// orderID: "7RF70259NY7589848"
// payerID: "8M3BU92Z97VXA"
// paymentID: null
},
});
// billingToken: null
// facilitatorAccessToken: "A21AAL_fEu0gDD-sIXyOy65a6MjgSJJrhmxuPcxxUGnL5gW2DzTxiiAksfoC4x8hD-BjeY1LsFVKl7ceuO7UR1a9pQr8Q_AVw"
// orderID: "7RF70259NY7589848"
// payerID: "8M3BU92Z97VXA"
// paymentID: null
},
})
if (button.isEligible()) {
button.render('#paypal-button-container');
pretixpaypal.continue_button.hide();
} else {
pretixpaypal.continue_button.text(gettext('Payment method unavailable'));
pretixpaypal.continue_button.show();
}
},
if (button.isEligible()) {
button.render('#paypal-button-container')
pretixpaypal.continue_button.hide()
} else {
pretixpaypal.continue_button.text(gettext('Payment method unavailable'))
pretixpaypal.continue_button.show()
}
},
onApproveSubmit: function() {
if (document.visibilityState === "visible" && pretixpaypal.readyToSubmitApproval === true) {
let method = pretixpaypal.paypage ? "wallet" : pretixpaypal.method.method;
let selectorstub = "#payment_paypal_" + method;
var $form = $(selectorstub + "_oid").closest("form");
onApproveSubmit: function () {
if (document.visibilityState === 'visible' && pretixpaypal.readyToSubmitApproval === true) {
let method = pretixpaypal.paypage ? 'wallet' : pretixpaypal.method.method
let selectorstub = '#payment_paypal_' + method
let $form = $(selectorstub + '_oid').closest('form')
$form.get(0).submit();
}
},
$form.get(0).submit()
}
},
renderAPMs: function () {
pretixpaypal.restore();
let inputselector = $("input[name=payment][value=paypal_apm]");
let textselector = inputselector.closest("label").find('.accordion-label-text');
let eligibles = [];
renderAPMs: function () {
pretixpaypal.restore()
let inputselector = $('input[name=payment][value=paypal_apm]')
let textselector = inputselector.closest('label').find('.accordion-label-text')
let eligibles = []
pretixpaypal.paypal.getFundingSources().forEach(function (fundingSource) {
// Let's always skip PayPal, since it's always a dedicated funding source
if (fundingSource === 'paypal') {
return;
}
pretixpaypal.paypal.getFundingSources().forEach(function (fundingSource) {
// Let's always skip PayPal, since it's always a dedicated funding source
if (fundingSource === 'paypal') {
return
}
// This could also be paypal.Marks() - but they only expose images instead of cleartext...
let button = pretixpaypal.paypal.Buttons({
fundingSource: fundingSource
});
// This could also be paypal.Marks() - but they only expose images instead of cleartext...
let button = pretixpaypal.paypal.Buttons({
fundingSource: fundingSource
})
if (button.isEligible()) {
eligibles.push(gettext(pretixpaypal.apm_map[fundingSource] || fundingSource));
}
});
if (button.isEligible()) {
eligibles.push(gettext(pretixpaypal.apm_map[fundingSource] || fundingSource))
}
})
inputselector.attr('title', eligibles.join(', '));
textselector.fadeOut(300, function () {
textselector.text(eligibles.join(', '));
textselector.fadeIn(300);
});
},
inputselector.attr('title', eligibles.join(', '))
textselector.fadeOut(300, function () {
textselector.text(eligibles.join(', '))
textselector.fadeIn(300)
})
},
guessLocale: function() {
// This is a horrible hackjob and does not at all take into consideration the actual locale.
// Instead, we only look at the language that the shop is currently being displayed in and make
// that into a locale.
let allowed_locales = [
'en_US',
'ar_DZ',
'fr_FR',
'es_ES',
'zh_CN',
'de_DE',
'nl_NL',
'pt_PT',
'cs_CZ',
'da_DK',
'fi_FI',
'el_GR',
'hu_HU',
'id_ID',
'he_IL',
'it_IT',
'ja_JP',
'ru_RU',
'no_NO',
'pl_PL',
'sk_SK',
'sv_SE',
'th_TH',
'tr_TR',
]
let lang = $("body").attr("data-locale").split('-')[0];
return allowed_locales.find(element => element.startsWith(lang));
}
};
guessLocale: function () {
// This is a horrible hackjob and does not at all take into consideration the actual locale.
// Instead, we only look at the language that the shop is currently being displayed in and make
// that into a locale.
let allowed_locales = [
'en_US',
'ar_DZ',
'fr_FR',
'es_ES',
'zh_CN',
'de_DE',
'nl_NL',
'pt_PT',
'cs_CZ',
'da_DK',
'fi_FI',
'el_GR',
'hu_HU',
'id_ID',
'he_IL',
'it_IT',
'ja_JP',
'ru_RU',
'no_NO',
'pl_PL',
'sk_SK',
'sv_SE',
'th_TH',
'tr_TR',
]
let lang = $('body').attr('data-locale').split('-')[0]
return allowed_locales.find(element => element.startsWith(lang))
}
}
$(function () {
// This script is always loaded if paypal is enabled as a payment method, regardless of
// whether it is available (it could e.g. be hidden or limited to certain countries).
// We do not want to unnecessarily load the sdk.
// If no paypal/paypal_apm payment option is present and we are not on
// the (APM) PayView, then we do not need the SDK.
if (!$("input[name=payment][value^='paypal']").length && !$('#paypal-button-container').data('paypage')) {
return
}
// This script is always loaded if paypal is enabled as a payment method, regardless of
// whether it is available (it could e.g. be hidden or limited to certain countries).
// We do not want to unnecessarily load the sdk.
// If no paypal/paypal_apm payment option is present and we are not on
// the (APM) PayView, then we do not need the SDK.
if (!$('input[name=payment][value^=\'paypal\']').length && !$('#paypal-button-container').data('paypage')) {
return
}
pretixpaypal.load();
pretixpaypal.load();
(async() => {
while(!pretixpaypal.paypal)
await new Promise(resolve => setTimeout(resolve, 1000));
pretixpaypal.ready();
})();
});
(async () => {
while (!pretixpaypal.paypal)
await new Promise(resolve => setTimeout(resolve, 1000))
pretixpaypal.ready()
})()
})
@@ -1,81 +1,81 @@
/*globals $, Morris, gettext, django*/
function gettext(msgid) {
if (typeof django !== 'undefined' && typeof django.gettext !== 'undefined') {
return django.gettext(msgid);
}
return msgid;
/* globals Morris, django */
function gettext (msgid) {
if (typeof django !== 'undefined' && typeof django.gettext !== 'undefined') {
return django.gettext(msgid)
}
return msgid
}
$(function () {
$(".chart").css("height", "250px");
new Morris.Area({
element: 'obd_chart',
data: JSON.parse($("#obd-data").html()),
xkey: 'date',
ykeys: ['ordered', 'paid'],
labels: [gettext('Placed orders'), gettext('Paid orders')],
lineColors: ['#3b1c4a', '#50a167'],
smooth: false,
resize: true,
fillOpacity: 0.3,
behaveLikeLine: true
});
new Morris.Area({
element: 'abd_chart',
data: JSON.parse($("#abd-data").html()),
xkey: 'date',
ykeys: ['ordered', 'paid'],
labels: [gettext('Attendees (ordered)'), gettext('Attendees (paid)')],
lineColors: ['#3b1c4a', '#50a167'],
smooth: false,
resize: true,
fillOpacity: 0.3,
behaveLikeLine: true
});
new Morris.Area({
element: 'abt_chart',
data: JSON.parse($("#abt-data").html()),
xkey: 'date',
ykeys: ['ordered', 'paid'],
labels: [gettext('Attendees (ordered)'), gettext('Attendees (paid)')],
lineColors: ['#3b1c4a', '#50a167'],
smooth: false,
resize: true,
fillOpacity: 0.3,
behaveLikeLine: true
});
new Morris.Area({
element: 'rev_chart',
data: JSON.parse($("#rev-data").html()),
xkey: 'date',
ykeys: ['revenue'],
labels: [gettext('Total revenue')],
smooth: false,
resize: true,
lineColors: ['#3b1c4a'],
fillOpacity: 0.3,
preUnits: $.trim($("#currency").html()) + ' '
});
new Morris.Bar({
element: 'obp_chart',
data: JSON.parse($("#obp-data").html()),
xkey: 'item_short',
ykeys: ['ordered', 'paid'],
labels: [gettext('Placed orders'), gettext('Paid orders')],
barColors: ['#3b1c4a', '#50a167'],
hoverCallback: function (index, options, content, row) {
console.log(content);
var $c = $("<div>" + content + "</div>");
var $label = $c.find(".morris-hover-row-label");
$label.text(row.item);
var newc = $label.get(0).outerHTML;
$c.find('.morris-hover-point').each(function (i, r) {
if ($.trim($(r).text().split("\n")[2]) !== "0") {
newc += r.outerHTML;
}
});
return newc;
},
resize: true,
xLabelAngle: 30
});
});
$('.chart').css('height', '250px')
new Morris.Area({
element: 'obd_chart',
data: JSON.parse($('#obd-data').html()),
xkey: 'date',
ykeys: ['ordered', 'paid'],
labels: [gettext('Placed orders'), gettext('Paid orders')],
lineColors: ['#3b1c4a', '#50a167'],
smooth: false,
resize: true,
fillOpacity: 0.3,
behaveLikeLine: true
})
new Morris.Area({
element: 'abd_chart',
data: JSON.parse($('#abd-data').html()),
xkey: 'date',
ykeys: ['ordered', 'paid'],
labels: [gettext('Attendees (ordered)'), gettext('Attendees (paid)')],
lineColors: ['#3b1c4a', '#50a167'],
smooth: false,
resize: true,
fillOpacity: 0.3,
behaveLikeLine: true
})
new Morris.Area({
element: 'abt_chart',
data: JSON.parse($('#abt-data').html()),
xkey: 'date',
ykeys: ['ordered', 'paid'],
labels: [gettext('Attendees (ordered)'), gettext('Attendees (paid)')],
lineColors: ['#3b1c4a', '#50a167'],
smooth: false,
resize: true,
fillOpacity: 0.3,
behaveLikeLine: true
})
new Morris.Area({
element: 'rev_chart',
data: JSON.parse($('#rev-data').html()),
xkey: 'date',
ykeys: ['revenue'],
labels: [gettext('Total revenue')],
smooth: false,
resize: true,
lineColors: ['#3b1c4a'],
fillOpacity: 0.3,
preUnits: $.trim($('#currency').html()) + ' '
})
new Morris.Bar({
element: 'obp_chart',
data: JSON.parse($('#obp-data').html()),
xkey: 'item_short',
ykeys: ['ordered', 'paid'],
labels: [gettext('Placed orders'), gettext('Paid orders')],
barColors: ['#3b1c4a', '#50a167'],
hoverCallback: function (index, options, content, row) {
console.log(content)
let $c = $('<div>' + content + '</div>')
let $label = $c.find('.morris-hover-row-label')
$label.text(row.item)
let newc = $label.get(0).outerHTML
$c.find('.morris-hover-point').each(function (i, r) {
if ($.trim($(r).text().split('\n')[2]) !== '0') {
newc += r.outerHTML
}
})
return newc
},
resize: true,
xLabelAngle: 30
})
})
@@ -1,435 +1,435 @@
/*global $, stripe_pubkey, stripe_loadingmessage, gettext */
'use strict';
/* global stripe_pubkey, stripe_loadingmessage, gettext */
'use strict'
var pretixstripe = {
stripe: null,
elements: null,
card: null,
sepa: null,
affirm: null,
klarna: null,
paymentRequest: null,
paymentRequestButton: null,
stripe: null,
elements: null,
card: null,
sepa: null,
affirm: null,
klarna: null,
paymentRequest: null,
paymentRequestButton: null,
'pm_request': function (method, element, kwargs = {}) {
waitingDialog.show(gettext("Contacting Stripe …"));
$(".stripe-errors").hide();
pm_request: function (method, element, kwargs = {}) {
waitingDialog.show(gettext('Contacting Stripe …'))
$('.stripe-errors').hide()
pretixstripe.stripe.createPaymentMethod(method, element, kwargs).then(function (result) {
waitingDialog.hide();
if (result.error) {
$(".stripe-errors").stop().hide().removeClass("sr-only");
$(".stripe-errors").html("<div class='alert alert-danger'>" + result.error.message + "</div>");
$(".stripe-errors").slideDown();
} else {
var $form = $("#stripe_" + method + "_payment_method_id").closest("form");
// Insert the token into the form so it gets submitted to the server
$("#stripe_" + method + "_payment_method_id").val(result.paymentMethod.id);
if (method === 'card') {
$("#stripe_card_brand").val(result.paymentMethod.card.brand);
$("#stripe_card_last4").val(result.paymentMethod.card.last4);
}
if (method === 'sepa_debit') {
$("#stripe_sepa_debit_last4").val(result.paymentMethod.sepa_debit.last4);
}
// and submit
$form.get(0).submit();
}
}).catch((e) => {
waitingDialog.hide();
$(".stripe-errors").stop().hide().removeClass("sr-only");
$(".stripe-errors").html("<div class='alert alert-danger'>Technical error, please contact support: " + e + "</div>");
$(".stripe-errors").slideDown();
});
},
'load': function () {
if (pretixstripe.stripe !== null) {
return;
}
$('.stripe-container').closest("form").find(".checkout-button-row .btn-primary").prop("disabled", true);
$.ajax(
{
url: 'https://js.stripe.com/v3/',
dataType: 'script',
success: function () {
if ($.trim($("#stripe_connectedAccountId").html())) {
pretixstripe.stripe = Stripe($.trim($("#stripe_pubkey").html()), {
stripeAccount: $.trim($("#stripe_connectedAccountId").html()),
locale: $.trim($("body").attr("data-locale"))
});
} else {
pretixstripe.stripe = Stripe($.trim($("#stripe_pubkey").html()), {
locale: $.trim($("body").attr("data-locale"))
});
}
pretixstripe.elements = pretixstripe.stripe.elements();
if ($.trim($("#stripe_merchantcountry").html()) !== "") {
try {
pretixstripe.paymentRequest = pretixstripe.stripe.paymentRequest({
country: $("#stripe_merchantcountry").html(),
currency: $("#stripe_card_currency").val().toLowerCase(),
total: {
label: gettext('Total'),
amount: parseInt($("#stripe_card_total").val())
},
displayItems: [],
requestPayerName: false,
requestPayerEmail: false,
requestPayerPhone: false,
requestShipping: false,
});
pretixstripe.stripe.createPaymentMethod(method, element, kwargs).then(function (result) {
waitingDialog.hide()
if (result.error) {
$('.stripe-errors').stop().hide().removeClass('sr-only')
$('.stripe-errors').html('<div class=\'alert alert-danger\'>' + result.error.message + '</div>')
$('.stripe-errors').slideDown()
} else {
let $form = $('#stripe_' + method + '_payment_method_id').closest('form')
// Insert the token into the form so it gets submitted to the server
$('#stripe_' + method + '_payment_method_id').val(result.paymentMethod.id)
if (method === 'card') {
$('#stripe_card_brand').val(result.paymentMethod.card.brand)
$('#stripe_card_last4').val(result.paymentMethod.card.last4)
}
if (method === 'sepa_debit') {
$('#stripe_sepa_debit_last4').val(result.paymentMethod.sepa_debit.last4)
}
// and submit
$form.get(0).submit()
}
}).catch((e) => {
waitingDialog.hide()
$('.stripe-errors').stop().hide().removeClass('sr-only')
$('.stripe-errors').html('<div class=\'alert alert-danger\'>Technical error, please contact support: ' + e + '</div>')
$('.stripe-errors').slideDown()
})
},
load: function () {
if (pretixstripe.stripe !== null) {
return
}
$('.stripe-container').closest('form').find('.checkout-button-row .btn-primary').prop('disabled', true)
$.ajax(
{
url: 'https://js.stripe.com/v3/',
dataType: 'script',
success: function () {
if ($.trim($('#stripe_connectedAccountId').html())) {
pretixstripe.stripe = Stripe($.trim($('#stripe_pubkey').html()), {
stripeAccount: $.trim($('#stripe_connectedAccountId').html()),
locale: $.trim($('body').attr('data-locale'))
})
} else {
pretixstripe.stripe = Stripe($.trim($('#stripe_pubkey').html()), {
locale: $.trim($('body').attr('data-locale'))
})
}
pretixstripe.elements = pretixstripe.stripe.elements()
if ($.trim($('#stripe_merchantcountry').html()) !== '') {
try {
pretixstripe.paymentRequest = pretixstripe.stripe.paymentRequest({
country: $('#stripe_merchantcountry').html(),
currency: $('#stripe_card_currency').val().toLowerCase(),
total: {
label: gettext('Total'),
amount: parseInt($('#stripe_card_total').val())
},
displayItems: [],
requestPayerName: false,
requestPayerEmail: false,
requestPayerPhone: false,
requestShipping: false,
})
pretixstripe.paymentRequest.on('paymentmethod', function (ev) {
ev.complete('success');
pretixstripe.paymentRequest.on('paymentmethod', function (ev) {
ev.complete('success')
var $form = $("#stripe_card_payment_method_id").closest("form");
// Insert the token into the form so it gets submitted to the server
$("#stripe_card_payment_method_id").val(ev.paymentMethod.id);
$("#stripe_card_brand").val(ev.paymentMethod.card.brand);
$("#stripe_card_last4").val(ev.paymentMethod.card.last4);
// and submit
$form.get(0).submit();
});
} catch (e) {
pretixstripe.paymentRequest = null;
}
} else {
pretixstripe.paymentRequest = null;
}
if ($("#stripe-card").length) {
pretixstripe.card = pretixstripe.elements.create('card', {
'style': {
'base': {
'fontFamily': '"Open Sans","OpenSans","Helvetica Neue",Helvetica,Arial,sans-serif',
'fontSize': '14px',
'color': '#555555',
'lineHeight': '1.42857',
'border': '1px solid #ccc',
'::placeholder': {
color: 'rgba(0,0,0,0.4)',
},
},
'invalid': {
'color': 'red',
},
},
classes: {
focus: 'is-focused',
invalid: 'has-error',
}
});
pretixstripe.card.mount("#stripe-card");
pretixstripe.card.on('ready', function () {
$('.stripe-container').closest("form").find(".checkout-button-row .btn-primary").prop("disabled", false);
});
}
if ($("#stripe-sepa").length) {
pretixstripe.sepa = pretixstripe.elements.create('iban', {
'style': {
'base': {
'fontFamily': '"Open Sans","OpenSans","Helvetica Neue",Helvetica,Arial,sans-serif',
'fontSize': '14px',
'color': '#555555',
'lineHeight': '1.42857',
'border': '1px solid #ccc',
'::placeholder': {
color: 'rgba(0,0,0,0.4)',
},
},
'invalid': {
'color': 'red',
},
},
supportedCountries: ['SEPA'],
classes: {
focus: 'is-focused',
invalid: 'has-error',
}
});
pretixstripe.sepa.on('change', function (event) {
// List of IBAN-countries, that require the country as well as line1-property according to
// https://stripe.com/docs/payments/sepa-debit/accept-a-payment?platform=web&ui=element#web-submit-payment
if (['AD', 'PF', 'TF', 'GI', 'GB', 'GG', 'VA', 'IM', 'JE', 'MC', 'NC', 'BL', 'PM', 'SM', 'CH', 'WF'].indexOf(event.country) > 0) {
$("#stripe_sepa_debit_country").prop('checked', true);
$("#stripe_sepa_debit_country").change();
} else {
$("#stripe_sepa_debit_country").prop('checked', false);
$("#stripe_sepa_debit_country").change();
}
if (event.bankName) {
$("#stripe_sepa_debit_bank").val(event.bankName);
}
});
pretixstripe.sepa.mount("#stripe-sepa");
pretixstripe.sepa.on('ready', function () {
$('.stripe-container').closest("form").find(".checkout-button-row .btn-primary").prop("disabled", false);
});
}
if ($("#stripe-affirm").length) {
pretixstripe.affirm = pretixstripe.elements.create('affirmMessage', {
'amount': parseInt($("#stripe_affirm_total").val()),
'currency': $("#stripe_affirm_currency").val(),
});
let $form = $('#stripe_card_payment_method_id').closest('form')
// Insert the token into the form so it gets submitted to the server
$('#stripe_card_payment_method_id').val(ev.paymentMethod.id)
$('#stripe_card_brand').val(ev.paymentMethod.card.brand)
$('#stripe_card_last4').val(ev.paymentMethod.card.last4)
// and submit
$form.get(0).submit()
})
} catch (e) {
pretixstripe.paymentRequest = null
}
} else {
pretixstripe.paymentRequest = null
}
if ($('#stripe-card').length) {
pretixstripe.card = pretixstripe.elements.create('card', {
style: {
base: {
fontFamily: '"Open Sans","OpenSans","Helvetica Neue",Helvetica,Arial,sans-serif',
fontSize: '14px',
color: '#555555',
lineHeight: '1.42857',
border: '1px solid #ccc',
'::placeholder': {
color: 'rgba(0,0,0,0.4)',
},
},
invalid: {
color: 'red',
},
},
classes: {
focus: 'is-focused',
invalid: 'has-error',
}
})
pretixstripe.card.mount('#stripe-card')
pretixstripe.card.on('ready', function () {
$('.stripe-container').closest('form').find('.checkout-button-row .btn-primary').prop('disabled', false)
})
}
if ($('#stripe-sepa').length) {
pretixstripe.sepa = pretixstripe.elements.create('iban', {
style: {
base: {
fontFamily: '"Open Sans","OpenSans","Helvetica Neue",Helvetica,Arial,sans-serif',
fontSize: '14px',
color: '#555555',
lineHeight: '1.42857',
border: '1px solid #ccc',
'::placeholder': {
color: 'rgba(0,0,0,0.4)',
},
},
invalid: {
color: 'red',
},
},
supportedCountries: ['SEPA'],
classes: {
focus: 'is-focused',
invalid: 'has-error',
}
})
pretixstripe.sepa.on('change', function (event) {
// List of IBAN-countries, that require the country as well as line1-property according to
// https://stripe.com/docs/payments/sepa-debit/accept-a-payment?platform=web&ui=element#web-submit-payment
if (['AD', 'PF', 'TF', 'GI', 'GB', 'GG', 'VA', 'IM', 'JE', 'MC', 'NC', 'BL', 'PM', 'SM', 'CH', 'WF'].indexOf(event.country) > 0) {
$('#stripe_sepa_debit_country').prop('checked', true)
$('#stripe_sepa_debit_country').change()
} else {
$('#stripe_sepa_debit_country').prop('checked', false)
$('#stripe_sepa_debit_country').change()
}
if (event.bankName) {
$('#stripe_sepa_debit_bank').val(event.bankName)
}
})
pretixstripe.sepa.mount('#stripe-sepa')
pretixstripe.sepa.on('ready', function () {
$('.stripe-container').closest('form').find('.checkout-button-row .btn-primary').prop('disabled', false)
})
}
if ($('#stripe-affirm').length) {
pretixstripe.affirm = pretixstripe.elements.create('affirmMessage', {
amount: parseInt($('#stripe_affirm_total').val()),
currency: $('#stripe_affirm_currency').val(),
})
pretixstripe.affirm.mount('#stripe-affirm');
}
if ($("#stripe-klarna").length) {
try {
pretixstripe.klarna = pretixstripe.elements.create('paymentMethodMessaging', {
'amount': parseInt($("#stripe_klarna_total").val()),
'currency': $("#stripe_klarna_currency").val(),
'countryCode': $("#stripe_klarna_country").val(),
'paymentMethodTypes': ['klarna'],
});
pretixstripe.affirm.mount('#stripe-affirm')
}
if ($('#stripe-klarna').length) {
try {
pretixstripe.klarna = pretixstripe.elements.create('paymentMethodMessaging', {
amount: parseInt($('#stripe_klarna_total').val()),
currency: $('#stripe_klarna_currency').val(),
countryCode: $('#stripe_klarna_country').val(),
paymentMethodTypes: ['klarna'],
})
pretixstripe.klarna.mount('#stripe-klarna');
} catch (e) {
console.error(e);
$("#stripe-klarna").html("<div class='alert alert-danger'>Technical error, please contact support: " + e + "</div>");
}
}
if ($("#stripe-payment-request-button").length && pretixstripe.paymentRequest != null) {
pretixstripe.paymentRequestButton = pretixstripe.elements.create('paymentRequestButton', {
paymentRequest: pretixstripe.paymentRequest,
});
pretixstripe.klarna.mount('#stripe-klarna')
} catch (e) {
console.error(e)
$('#stripe-klarna').html('<div class=\'alert alert-danger\'>Technical error, please contact support: ' + e + '</div>')
}
}
if ($('#stripe-payment-request-button').length && pretixstripe.paymentRequest != null) {
pretixstripe.paymentRequestButton = pretixstripe.elements.create('paymentRequestButton', {
paymentRequest: pretixstripe.paymentRequest,
})
pretixstripe.paymentRequest.canMakePayment().then(function (result) {
if (result) {
pretixstripe.paymentRequestButton.mount('#stripe-payment-request-button');
$('#stripe-card-elements .stripe-or').removeClass("hidden");
$('#stripe-payment-request-button').parent().removeClass("hidden");
} else {
$('#stripe-payment-request-button').hide();
document.getElementById('stripe-payment-request-button').style.display = 'none';
}
});
}
}
}
);
},
'withStripe': function (callback) {
$.ajax({
url: 'https://js.stripe.com/v3/',
dataType: 'script',
success: function () {
if ($.trim($("#stripe_connectedAccountId").html())) {
pretixstripe.stripe = Stripe($.trim($("#stripe_pubkey").html()), {
stripeAccount: $.trim($("#stripe_connectedAccountId").html()),
locale: $.trim($("body").attr("data-locale"))
});
} else {
pretixstripe.stripe = Stripe($.trim($("#stripe_pubkey").html()), {
locale: $.trim($("body").attr("data-locale"))
});
}
callback();
}
});
},
'handleAlipayAction': function (payment_intent_client_secret) {
pretixstripe.withStripe(function () {
pretixstripe.stripe.confirmAlipayPayment(
payment_intent_client_secret,
{
return_url: window.location.href
}
).then(function (result) {
if (result.error) {
waitingDialog.hide();
$(".stripe-errors").stop().hide().removeClass("sr-only");
$(".stripe-errors").html("<div class='alert alert-danger'>Technical error, please contact support: " + result.error.message + "</div>");
$(".stripe-errors").slideDown();
} else {
waitingDialog.show(gettext("Confirming your payment …"));
}
});
});
},
'handleWechatAction': function (payment_intent_client_secret) {
pretixstripe.withStripe(function () {
pretixstripe.stripe.confirmWechatPayPayment(
payment_intent_client_secret,
{
payment_method_options: {
wechat_pay: {
client: 'web',
},
},
}
).then(function (result) {
if (result.error) {
waitingDialog.hide();
$(".stripe-errors").stop().hide().removeClass("sr-only");
$(".stripe-errors").html("<div class='alert alert-danger'>Technical error, please contact support: " + result.error.message + "</div>");
$(".stripe-errors").slideDown();
} else {
waitingDialog.show(gettext("Confirming your payment …"));
location.reload();
}
});
});
},
'handleCardAction': function (payment_intent_client_secret) {
pretixstripe.withStripe(function () {
pretixstripe.stripe.handleCardAction(
payment_intent_client_secret
).then(function (result) {
if (result.error) {
waitingDialog.hide();
$(".stripe-errors").stop().hide().removeClass("sr-only");
$(".stripe-errors").html("<div class='alert alert-danger'>Technical error, please contact support: " + result.error.message + "</div>");
$(".stripe-errors").slideDown();
} else {
waitingDialog.show(gettext("Confirming your payment …"));
location.reload();
}
});
});
},
'handlePaymentRedirectAction': function (payment_intent_next_action_redirect_url) {
waitingDialog.show(gettext("Contacting your bank …"));
pretixstripe.paymentRequest.canMakePayment().then(function (result) {
if (result) {
pretixstripe.paymentRequestButton.mount('#stripe-payment-request-button')
$('#stripe-card-elements .stripe-or').removeClass('hidden')
$('#stripe-payment-request-button').parent().removeClass('hidden')
} else {
$('#stripe-payment-request-button').hide()
document.getElementById('stripe-payment-request-button').style.display = 'none'
}
})
}
}
}
)
},
withStripe: function (callback) {
$.ajax({
url: 'https://js.stripe.com/v3/',
dataType: 'script',
success: function () {
if ($.trim($('#stripe_connectedAccountId').html())) {
pretixstripe.stripe = Stripe($.trim($('#stripe_pubkey').html()), {
stripeAccount: $.trim($('#stripe_connectedAccountId').html()),
locale: $.trim($('body').attr('data-locale'))
})
} else {
pretixstripe.stripe = Stripe($.trim($('#stripe_pubkey').html()), {
locale: $.trim($('body').attr('data-locale'))
})
}
callback()
}
})
},
handleAlipayAction: function (payment_intent_client_secret) {
pretixstripe.withStripe(function () {
pretixstripe.stripe.confirmAlipayPayment(
payment_intent_client_secret,
{
return_url: window.location.href
}
).then(function (result) {
if (result.error) {
waitingDialog.hide()
$('.stripe-errors').stop().hide().removeClass('sr-only')
$('.stripe-errors').html('<div class=\'alert alert-danger\'>Technical error, please contact support: ' + result.error.message + '</div>')
$('.stripe-errors').slideDown()
} else {
waitingDialog.show(gettext('Confirming your payment …'))
}
})
})
},
handleWechatAction: function (payment_intent_client_secret) {
pretixstripe.withStripe(function () {
pretixstripe.stripe.confirmWechatPayPayment(
payment_intent_client_secret,
{
payment_method_options: {
wechat_pay: {
client: 'web',
},
},
}
).then(function (result) {
if (result.error) {
waitingDialog.hide()
$('.stripe-errors').stop().hide().removeClass('sr-only')
$('.stripe-errors').html('<div class=\'alert alert-danger\'>Technical error, please contact support: ' + result.error.message + '</div>')
$('.stripe-errors').slideDown()
} else {
waitingDialog.show(gettext('Confirming your payment …'))
location.reload()
}
})
})
},
handleCardAction: function (payment_intent_client_secret) {
pretixstripe.withStripe(function () {
pretixstripe.stripe.handleCardAction(
payment_intent_client_secret
).then(function (result) {
if (result.error) {
waitingDialog.hide()
$('.stripe-errors').stop().hide().removeClass('sr-only')
$('.stripe-errors').html('<div class=\'alert alert-danger\'>Technical error, please contact support: ' + result.error.message + '</div>')
$('.stripe-errors').slideDown()
} else {
waitingDialog.show(gettext('Confirming your payment …'))
location.reload()
}
})
})
},
handlePaymentRedirectAction: function (payment_intent_next_action_redirect_url) {
waitingDialog.show(gettext('Contacting your bank …'))
let payment_intent_redirect_action_handling = $.trim($("#stripe_payment_intent_redirect_action_handling").html());
if (payment_intent_redirect_action_handling === 'iframe') {
let iframe = document.createElement('iframe');
iframe.src = payment_intent_next_action_redirect_url;
iframe.className = 'embed-responsive-item';
$('#scacontainer').append(iframe);
$('#scacontainer iframe').on("load", function () {
waitingDialog.hide();
});
} else if (payment_intent_redirect_action_handling === 'redirect') {
window.location.href = payment_intent_next_action_redirect_url;
}
}
};
let payment_intent_redirect_action_handling = $.trim($('#stripe_payment_intent_redirect_action_handling').html())
if (payment_intent_redirect_action_handling === 'iframe') {
let iframe = document.createElement('iframe')
iframe.src = payment_intent_next_action_redirect_url
iframe.className = 'embed-responsive-item'
$('#scacontainer').append(iframe)
$('#scacontainer iframe').on('load', function () {
waitingDialog.hide()
})
} else if (payment_intent_redirect_action_handling === 'redirect') {
window.location.href = payment_intent_next_action_redirect_url
}
}
}
$(function () {
if ($("#stripe_payment_intent_SCA_status").length) {
let payment_intent_redirect_action_handling = $.trim($("#stripe_payment_intent_redirect_action_handling").html());
let order_status = $.trim($("#order_status").html());
let order_url = $.trim($("#order_url").html())
if ($('#stripe_payment_intent_SCA_status').length) {
let payment_intent_redirect_action_handling = $.trim($('#stripe_payment_intent_redirect_action_handling').html())
let order_status = $.trim($('#order_status').html())
let order_url = $.trim($('#order_url').html())
if (payment_intent_redirect_action_handling === 'iframe') {
window.parent.postMessage('3DS-authentication-complete.' + order_status, '*');
return;
} else if (payment_intent_redirect_action_handling === 'redirect') {
waitingDialog.show(gettext("Confirming your payment …"));
if (payment_intent_redirect_action_handling === 'iframe') {
window.parent.postMessage('3DS-authentication-complete.' + order_status, '*')
return
} else if (payment_intent_redirect_action_handling === 'redirect') {
waitingDialog.show(gettext('Confirming your payment …'))
if (order_status === 'p') {
window.location.href = order_url + '?paid=yes';
} else {
window.location.href = order_url;
}
}
} else if ($("#stripe_payment_intent_next_action_redirect_url").length) {
let payment_intent_next_action_redirect_url = JSON.parse($("#stripe_payment_intent_next_action_redirect_url").html());
pretixstripe.handlePaymentRedirectAction(payment_intent_next_action_redirect_url);
} else if ($.trim($("#stripe_payment_intent_action_type").html()) === "promptpay_display_qr_code") {
waitingDialog.hide();
} else if ($.trim($("#stripe_payment_intent_action_type").html()) === "wechat_pay_display_qr_code") {
let payment_intent_client_secret = $.trim($("#stripe_payment_intent_client_secret").html());
pretixstripe.handleWechatAction(payment_intent_client_secret);
} else if ($.trim($("#stripe_payment_intent_action_type").html()) === "alipay_handle_redirect") {
let payment_intent_client_secret = $.trim($("#stripe_payment_intent_client_secret").html());
pretixstripe.handleAlipayAction(payment_intent_client_secret);
} else if ($("#stripe_payment_intent_client_secret").length) {
let payment_intent_client_secret = $.trim($("#stripe_payment_intent_client_secret").html());
pretixstripe.handleCardAction(payment_intent_client_secret);
}
if (order_status === 'p') {
window.location.href = order_url + '?paid=yes'
} else {
window.location.href = order_url
}
}
} else if ($('#stripe_payment_intent_next_action_redirect_url').length) {
let payment_intent_next_action_redirect_url = JSON.parse($('#stripe_payment_intent_next_action_redirect_url').html())
pretixstripe.handlePaymentRedirectAction(payment_intent_next_action_redirect_url)
} else if ($.trim($('#stripe_payment_intent_action_type').html()) === 'promptpay_display_qr_code') {
waitingDialog.hide()
} else if ($.trim($('#stripe_payment_intent_action_type').html()) === 'wechat_pay_display_qr_code') {
let payment_intent_client_secret = $.trim($('#stripe_payment_intent_client_secret').html())
pretixstripe.handleWechatAction(payment_intent_client_secret)
} else if ($.trim($('#stripe_payment_intent_action_type').html()) === 'alipay_handle_redirect') {
let payment_intent_client_secret = $.trim($('#stripe_payment_intent_client_secret').html())
pretixstripe.handleAlipayAction(payment_intent_client_secret)
} else if ($('#stripe_payment_intent_client_secret').length) {
let payment_intent_client_secret = $.trim($('#stripe_payment_intent_client_secret').html())
pretixstripe.handleCardAction(payment_intent_client_secret)
}
$(window).on("message onmessage", function (e) {
if (typeof e.originalEvent.data === "string" && e.originalEvent.data.startsWith('3DS-authentication-complete.')) {
waitingDialog.show(gettext("Confirming your payment …"));
$('#scacontainer').hide();
$('#continuebutton').removeClass('hidden');
$(window).on('message onmessage', function (e) {
if (typeof e.originalEvent.data === 'string' && e.originalEvent.data.startsWith('3DS-authentication-complete.')) {
waitingDialog.show(gettext('Confirming your payment …'))
$('#scacontainer').hide()
$('#continuebutton').removeClass('hidden')
if (e.originalEvent.data.split('.')[1] == 'p') {
window.location.href = $('#continuebutton').attr('href') + '?paid=yes';
} else {
window.location.href = $('#continuebutton').attr('href');
}
}
});
if (e.originalEvent.data.split('.')[1] == 'p') {
window.location.href = $('#continuebutton').attr('href') + '?paid=yes'
} else {
window.location.href = $('#continuebutton').attr('href')
}
}
})
if (!$(".stripe-container").length)
return;
if (!$('.stripe-container').length)
return
if (
$("input[name=payment][value=stripe]").is(':checked')
|| $("input[name=payment][value=stripe_sepa_debit]").is(':checked')
|| $("input[name=payment][value=stripe_affirm]").is(':checked')
|| $("input[name=payment][value=stripe_klarna]").is(':checked')
|| $(".payment-redo-form").length) {
pretixstripe.load();
} else {
$("input[name=payment]").change(function () {
if (['stripe', 'stripe_sepa_debit', 'stripe_affirm', 'stripe_klarna'].indexOf($(this).val()) > -1) {
pretixstripe.load();
}
})
}
if (
$('input[name=payment][value=stripe]').is(':checked')
|| $('input[name=payment][value=stripe_sepa_debit]').is(':checked')
|| $('input[name=payment][value=stripe_affirm]').is(':checked')
|| $('input[name=payment][value=stripe_klarna]').is(':checked')
|| $('.payment-redo-form').length) {
pretixstripe.load()
} else {
$('input[name=payment]').change(function () {
if (['stripe', 'stripe_sepa_debit', 'stripe_affirm', 'stripe_klarna'].indexOf($(this).val()) > -1) {
pretixstripe.load()
}
})
}
$("#stripe_other_card").click(
function (e) {
$("#stripe_card_payment_method_id").val("");
$("#stripe-current-card").slideUp();
$("#stripe-card-elements").slideDown();
$('#stripe_other_card').click(
function (e) {
$('#stripe_card_payment_method_id').val('')
$('#stripe-current-card').slideUp()
$('#stripe-card-elements').slideDown()
e.preventDefault();
return false;
}
);
e.preventDefault()
return false
}
)
if ($("#stripe-current-card").length) {
$("#stripe-card-elements").hide();
}
if ($('#stripe-current-card').length) {
$('#stripe-card-elements').hide()
}
$("#stripe_other_account").click(
function (e) {
$("#stripe_sepa_debit_payment_method_id").val("");
$("#stripe-current-account").slideUp();
// We're using a css-selector here instead of the id-selector,
// as we're hiding Stripe Elements *and* Django form fields
$('.stripe-sepa_debit-form').slideDown();
$('#stripe_other_account').click(
function (e) {
$('#stripe_sepa_debit_payment_method_id').val('')
$('#stripe-current-account').slideUp()
// We're using a css-selector here instead of the id-selector,
// as we're hiding Stripe Elements *and* Django form fields
$('.stripe-sepa_debit-form').slideDown()
e.preventDefault();
return false;
}
);
e.preventDefault()
return false
}
)
if ($("#stripe-current-account").length) {
// We're using a css-selector here instead of the id-selector,
// as we're hiding Stripe Elements *and* Django form fields
$('.stripe-sepa_debit-form').hide();
}
if ($('#stripe-current-account').length) {
// We're using a css-selector here instead of the id-selector,
// as we're hiding Stripe Elements *and* Django form fields
$('.stripe-sepa_debit-form').hide()
}
$('.stripe-container').closest("form").submit(
function () {
if ($("input[name=card_new]").length && !$("input[name=card_new]").prop('checked')) {
return null;
}
if (($("input[name=payment][value=stripe]").prop('checked') || $("input[name=payment][type=radio]").length === 0)
&& $("#stripe_card_payment_method_id").val() == "") {
pretixstripe.pm_request('card', pretixstripe.card);
return false;
}
$('.stripe-container').closest('form').submit(
function () {
if ($('input[name=card_new]').length && !$('input[name=card_new]').prop('checked')) {
return null
}
if (($('input[name=payment][value=stripe]').prop('checked') || $('input[name=payment][type=radio]').length === 0)
&& $('#stripe_card_payment_method_id').val() == '') {
pretixstripe.pm_request('card', pretixstripe.card)
return false
}
if (($("input[name=payment][value=stripe_sepa_debit]").prop('checked')) && $("#stripe_sepa_debit_payment_method_id").val() == "") {
pretixstripe.pm_request('sepa_debit', pretixstripe.sepa, {
billing_details: {
name: $("#id_payment_stripe_sepa_debit-accountname").val(),
email: $("#stripe_sepa_debit_email").val(),
address: {
line1: $("#id_payment_stripe_sepa_debit-line1").val(),
postal_code: $("#id_payment_stripe_sepa_debit-postal_code").val(),
city: $("#id_payment_stripe_sepa_debit-city").val(),
country: $("#id_payment_stripe_sepa_debit-country").val(),
}
}
});
return false;
}
}
);
});
if (($('input[name=payment][value=stripe_sepa_debit]').prop('checked')) && $('#stripe_sepa_debit_payment_method_id').val() == '') {
pretixstripe.pm_request('sepa_debit', pretixstripe.sepa, {
billing_details: {
name: $('#id_payment_stripe_sepa_debit-accountname').val(),
email: $('#stripe_sepa_debit_email').val(),
address: {
line1: $('#id_payment_stripe_sepa_debit-line1').val(),
postal_code: $('#id_payment_stripe_sepa_debit-postal_code').val(),
city: $('#id_payment_stripe_sepa_debit-city').val(),
country: $('#id_payment_stripe_sepa_debit-country').val(),
}
}
})
return false
}
}
)
})
+169 -171
View File
@@ -1,195 +1,193 @@
$(function () {
"use strict";
'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 = {};
// 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.
let responseCache = {}
const cleanName = (name) => {
// Remove form prefix
name = name.split("-").pop();
// Remove settings prefix
name = name.replace(/^invoice_address_from_/, "");
return name
}
const cleanName = (name) => {
// Remove form prefix
name = name.split('-').pop()
// Remove settings prefix
name = name.replace(/^invoice_address_from_/, '')
return name
}
$("[data-address-information-url]").each(function () {
let xhr;
const form = $(this);
const dependencies = $(this).find("[data-trigger-address-info]");
const loader = $("<span class='fa fa-cog fa-spin'></span>").hide().prependTo(dependencies.closest(".form-group").find("label").first())
const baseUrl = this.getAttribute('data-address-information-url')
const isAnyRequired = dependencies.toArray().some(function (e) { return $(e).closest(".form-group").is(".required") });
$('[data-address-information-url]').each(function () {
let xhr
const form = $(this)
const dependencies = $(this).find('[data-trigger-address-info]')
const loader = $('<span class=\'fa fa-cog fa-spin\'></span>').hide().prependTo(dependencies.closest('.form-group').find('label').first())
const baseUrl = this.getAttribute('data-address-information-url')
const isAnyRequired = dependencies.toArray().some(function (e) { return $(e).closest('.form-group').is('.required') })
const dependents = {
'city': form.find("input[name$=city]"),
'zipcode': form.find("input[name$=zipcode]"),
'street': form.find("textarea[name$=street]"),
'state': form.find("select[name$=state]"),
'vat_id': form.find("input[name$=vat_id]"),
};
const dependents = {
city: form.find('input[name$=city]'),
zipcode: form.find('input[name$=zipcode]'),
street: form.find('textarea[name$=street]'),
state: form.find('select[name$=state]'),
vat_id: form.find('input[name$=vat_id]'),
}
form.find("select[name*=transmission_], textarea[name*=transmission_], input[name*=transmission_]").each(function () {
dependents[cleanName($(this).attr("name"))] = $(this)
})
form.find('select[name*=transmission_], textarea[name*=transmission_], input[name*=transmission_]').each(function () {
dependents[cleanName($(this).attr('name'))] = $(this)
})
const dependentsDisabled = [];
for (var k in dependents) {
if (dependents[k].prop("disabled")) {
dependentsDisabled.push(k);
}
}
const dependentsDisabled = []
for (let k in dependents) {
if (dependents[k].prop('disabled')) {
dependentsDisabled.push(k)
}
}
if (!Object.values(dependents).some((el) => el.length)) {
// No address fields found, do not create request
return;
}
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);
});
const update_form = function (data) {
let 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) {
let 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 (dependents.transmission_type) {
let 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";
}
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);
});
$.each(data.transmission_types, function (k, s) {
let 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
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 (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)
}
if ('helptext_visible' in options) {
dependent.closest('.form-group').find('.help-block').toggle(options.helptext_visible)
}
if ('label' in options) {
dependent.closest(".form-group").find(".control-label").text(options.label);
}
if ('helptext_visible' in options) {
dependent.closest(".form-group").find(".help-block").toggle(options.helptext_visible);
}
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 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', dependentsDisabled.includes(k))
loader.hide()
}
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", dependentsDisabled.includes(k));
loader.hide();
}
const update = function (ev) {
dependents.state.prop('data-selected-value', dependents.state.val())
if (dependents.transmission_type) {
dependents.transmission_type.prop('data-selected-value', dependents.transmission_type.val())
}
const update = function (ev) {
dependents.state.prop("data-selected-value", dependents.state.val());
if (dependents.transmission_type) {
dependents.transmission_type.prop("data-selected-value", dependents.transmission_type.val());
}
for (let k in dependents) dependents[k].prop('disabled', true)
loader.show()
let url = new URL(baseUrl, location.href)
// Address depends on all annotated fields
form.find('[data-trigger-address-info]').each(function () {
// Remove prefix of the form to get actual field name
if (($(this).attr('type') === 'radio' || $(this).attr('type') === 'checkbox') && !$(this).prop('checked')) {
return
}
url.searchParams.append(cleanName($(this).attr('name')), $(this).val())
})
if (dependents.transmission_type) {
url.searchParams.append('transmission_type_required', !dependents.transmission_type.find('option[value=\'-\']').length)
}
for (var k in dependents) dependents[k].prop("disabled", true);
loader.show();
var url = new URL(baseUrl, location.href);
// Address depends on all annotated fields
form.find("[data-trigger-address-info]").each(function () {
// Remove prefix of the form to get actual field name
if (($(this).attr("type") === "radio" || $(this).attr("type") === "checkbox") && !$(this).prop("checked")) {
return
}
url.searchParams.append(cleanName($(this).attr("name")), $(this).val());
})
if (dependents.transmission_type) {
url.searchParams.append("transmission_type_required", !dependents.transmission_type.find("option[value='-']").length);
}
if (xhr && url in responseCache) {
if (responseCache[url] == xhr) {
// already requested this, but XHR is still running and will resolve promise
// only re-resolve promise for JSON-data in responseCache[url]
return
} else {
// abort current xhr as it is not the one we want
// aborting deletes responseCache[url] but async
xhr.abort()
}
}
if (xhr && url in responseCache) {
if (responseCache[url] == xhr) {
// already requested this, but XHR is still running and will resolve promise
// only re-resolve promise for JSON-data in responseCache[url]
return;
} else {
// abort current xhr as it is not the one we want
// aborting deletes responseCache[url] but async
xhr.abort();
}
}
if (!(url in responseCache)) {
responseCache[url] = xhr = $.ajax({
dataType: 'json',
url: url,
timeout: 3000,
})
}
if (!(url in responseCache)) {
responseCache[url] = xhr = $.ajax({
dataType: "json",
url: url,
timeout: 3000,
});
}
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 (let k in dependents) {
const dependent = dependents[k],
visible = true,
required = false
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) {
const dependent = dependents[k],
visible = true,
required = false;
dependent.closest('.form-group').toggle(visible).toggleClass('required', required)
dependent.prop('required', required).prop('disabled', dependentsDisabled.includes(k))
}
}).finally(function () {
loader.hide()
})
}
update()
dependencies.on('change', update)
dependent.closest(".form-group").toggle(visible).toggleClass('required', required);
dependent.prop("required", required).prop("disabled", dependentsDisabled.includes(k));
}
}).finally(function () {
loader.hide();
});
};
update();
dependencies.on("change", update);
if (dependents.vat_id && dependents.transmission_type && dependents.transmission_peppol_participant_id) {
// In Belgium, the VAT ID is built from "BE" + the company ID. The Peppol ID also needs to be built
// from the company ID with ID scheme 0208. We can save users some knowing and typing by filling this in!
if (!dependents.transmission_peppol_participant_id.val()) {
const fill_peppol_id = function () {
const vatId = dependents.vat_id.val();
if (vatId && vatId.startsWith("BE") && dependents.transmission_type.val() === "peppol") {
dependents.transmission_peppol_participant_id.val("0208:" + vatId.substring(2).replaceAll(".", ""))
}
}
dependents.vat_id.add(dependents.transmission_type).on("change", fill_peppol_id);
dependents.transmission_peppol_participant_id.one("change", () => {
dependents.vat_id.add(dependents.transmission_type).unbind("change", fill_peppol_id)
});
}
}
});
});
if (dependents.vat_id && dependents.transmission_type && dependents.transmission_peppol_participant_id) {
// In Belgium, the VAT ID is built from "BE" + the company ID. The Peppol ID also needs to be built
// from the company ID with ID scheme 0208. We can save users some knowing and typing by filling this in!
if (!dependents.transmission_peppol_participant_id.val()) {
const fill_peppol_id = function () {
const vatId = dependents.vat_id.val()
if (vatId && vatId.startsWith('BE') && dependents.transmission_type.val() === 'peppol') {
dependents.transmission_peppol_participant_id.val('0208:' + vatId.substring(2).replaceAll('.', ''))
}
}
dependents.vat_id.add(dependents.transmission_type).on('change', fill_peppol_id)
dependents.transmission_peppol_participant_id.one('change', () => {
dependents.vat_id.add(dependents.transmission_type).unbind('change', fill_peppol_id)
})
}
}
})
})
@@ -1,10 +1,10 @@
var check = function () {
$.getJSON(location.href + '&ajax=1', function (data, status) {
if (data.redirect) {
location.href = data.redirect;
} else {
window.setTimeout(check, 500);
}
});
let check = function () {
$.getJSON(location.href + '&ajax=1', function (data, _status) {
if (data.redirect) {
location.href = data.redirect
} else {
window.setTimeout(check, 500)
}
})
}
window.setTimeout(check, 500);
window.setTimeout(check, 500)
+328 -330
View File
@@ -1,359 +1,357 @@
/*global $, gettext */
var async_task_id = null;
var async_task_timeout = null;
var async_task_check_url = null;
var async_task_old_url = null;
var async_task_is_download = false;
var async_task_is_long = false;
var async_task_dont_redirect = false;
/* global gettext */
let async_task_id = null
let async_task_timeout = null
let async_task_check_url = null
let async_task_old_url = null
let async_task_is_download = false
let async_task_is_long = false
let async_task_dont_redirect = false
var async_task_status_messages = {
// These are functions in order to be lazily evaluated after the gettext file is loaded
long_task_started: () => gettext(
'Your request is currently being processed. Depending on the size of your event, this might take up to ' +
'a few minutes.'
),
long_task_pending: () => gettext(
'Your request has been queued on the server and will soon be ' +
'processed.'
),
short_task: () => gettext(
'Your request arrived on the server but we still wait for it to be ' +
'processed. If this takes longer than two minutes, please contact us or go ' +
'back in your browser and try again.'
)
};
function async_task_schedule_check(context, timeout) {
"use strict";
async_task_timeout = window.setTimeout(function() {
$.ajax(
{
'type': 'GET',
'url': async_task_check_url,
'success': async_task_check_callback,
'error': async_task_check_error,
'context': context,
'dataType': 'json'
}
);
}, timeout);
let async_task_status_messages = {
// These are functions in order to be lazily evaluated after the gettext file is loaded
long_task_started: () => gettext(
'Your request is currently being processed. Depending on the size of your event, this might take up to '
+ 'a few minutes.'
),
long_task_pending: () => gettext(
'Your request has been queued on the server and will soon be '
+ 'processed.'
),
short_task: () => gettext(
'Your request arrived on the server but we still wait for it to be '
+ 'processed. If this takes longer than two minutes, please contact us or go '
+ 'back in your browser and try again.'
)
}
function async_task_on_success(data) {
"use strict";
if ((async_task_is_download && data.success) || async_task_dont_redirect) {
waitingDialog.hide();
if (location.href.indexOf("async_id") !== -1) {
history.replaceState({}, "pretix", async_task_old_url);
}
}
if (!async_task_dont_redirect) {
$(window).one("pageshow", function (e) {
// hide waitingDialog when using browser's history back
waitingDialog.hide();
});
if (async_task_is_download && window.self !== window.top) {
// if in an iframe, force to download an async_task_is_download
// e.g. pretix-reseller embeds order-page in iframe, which would cause ticket-PDFs to be displayed inline
var a = document.createElement("a");
a.href = data.redirect;
a.download = "";
a.target = "_blank";
a.click();
} else {
location.href = data.redirect;
}
}
$(this).trigger('pretix:async-task-success', data);
function async_task_schedule_check (context, timeout) {
'use strict'
async_task_timeout = window.setTimeout(function () {
$.ajax(
{
type: 'GET',
url: async_task_check_url,
success: async_task_check_callback,
error: async_task_check_error,
context: context,
dataType: 'json'
}
)
}, timeout)
}
function async_task_check_callback(data, textStatus, jqXHR) {
"use strict";
if (data.ready && data.redirect) {
async_task_on_success.call(this, data);
return;
}
if (typeof data.percentage === "number") {
waitingDialog.setProgress(data.percentage);
}
if (typeof data.steps === "object" && Array.isArray(data.steps)) {
waitingDialog.setSteps(data.steps);
}
async_task_schedule_check(this, 250);
async_task_update_status(data);
function async_task_on_success (data) {
'use strict'
if ((async_task_is_download && data.success) || async_task_dont_redirect) {
waitingDialog.hide()
if (location.href.indexOf('async_id') !== -1) {
history.replaceState({}, 'pretix', async_task_old_url)
}
}
if (!async_task_dont_redirect) {
$(window).one('pageshow', function (e) {
// hide waitingDialog when using browser's history back
waitingDialog.hide()
})
if (async_task_is_download && window.self !== window.top) {
// if in an iframe, force to download an async_task_is_download
// e.g. pretix-reseller embeds order-page in iframe, which would cause ticket-PDFs to be displayed inline
let a = document.createElement('a')
a.href = data.redirect
a.download = ''
a.target = '_blank'
a.click()
} else {
location.href = data.redirect
}
}
$(this).trigger('pretix:async-task-success', data)
}
function async_task_update_status(data) {
if (async_task_is_long) {
if (data.started) {
waitingDialog.setStatus(async_task_status_messages.long_task_started());
} else {
waitingDialog.setStatus(async_task_status_messages.long_task_pending());
}
} else {
waitingDialog.setStatus(async_task_status_messages.short_task());
}
function async_task_check_callback (data, textStatus, jqXHR) {
'use strict'
if (data.ready && data.redirect) {
async_task_on_success.call(this, data)
return
}
if (typeof data.percentage === 'number') {
waitingDialog.setProgress(data.percentage)
}
if (typeof data.steps === 'object' && Array.isArray(data.steps)) {
waitingDialog.setSteps(data.steps)
}
async_task_schedule_check(this, 250)
async_task_update_status(data)
}
function async_task_replace_page(target, new_html) {
"use strict";
waitingDialog.hide();
$(target).html(new_html);
setup_basics($(target));
form_handlers($(target));
setup_collapsible_details($(target));
window.setTimeout(function () { $(window).scrollTop(0) }, 200)
$(document).trigger("pretix:bind-forms");
function async_task_update_status (data) {
if (async_task_is_long) {
if (data.started) {
waitingDialog.setStatus(async_task_status_messages.long_task_started())
} else {
waitingDialog.setStatus(async_task_status_messages.long_task_pending())
}
} else {
waitingDialog.setStatus(async_task_status_messages.short_task())
}
}
function async_task_check_error(jqXHR, textStatus, errorThrown) {
"use strict";
var respdom = $(jqXHR.responseText);
var c = respdom.filter('.container');
if (jqXHR.status === 401 && jqXHR.getResponseHeader("X-Login-Url")) {
window.location = jqXHR.getResponseHeader("X-Login-Url") + "?next=" + encodeURIComponent(location.pathname + location.search + location.hash);
return;
}
if (respdom.filter('form') && (respdom.filter('.has-error') || respdom.filter('.alert-danger'))) {
// This is a failed form validation, let's just use it
$("body").data('ajaxing', false);
async_task_replace_page("body", jqXHR.responseText.substring(
jqXHR.responseText.indexOf("<body"),
jqXHR.responseText.indexOf("</body")
));
} else if (c.length > 0) {
// This is some kind of 500/404/403 page, show it in an overlay
$("body").data('ajaxing', false);
waitingDialog.hide();
if (location.href.indexOf("async_id") !== -1) {
history.replaceState({}, "pretix", async_task_old_url);
}
ajaxErrDialog.show(c.first().html());
} else {
if (jqXHR.status >= 400 && jqXHR.status < 500) {
$("body").data('ajaxing', false);
waitingDialog.hide();
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status));
} else {
// 500 can be an application error or overload in some cases :(
waitingDialog.setStatus(gettext('We currently cannot reach the server, but we keep trying.' +
' Last error code: {code}').replace(/\{code\}/, jqXHR.status));
async_task_schedule_check(this, 5000);
}
}
function async_task_replace_page (target, new_html) {
'use strict'
waitingDialog.hide()
$(target).html(new_html)
setup_basics($(target))
form_handlers($(target))
setup_collapsible_details($(target))
window.setTimeout(function () { $(window).scrollTop(0) }, 200)
$(document).trigger('pretix:bind-forms')
}
function async_task_callback(data, jqXHR, status) {
"use strict";
$("body").data('ajaxing', false);
if (data.redirect) {
async_task_on_success.call(this, data);
return;
}
var check_url = new URL(data.check_url, window.location);
if (async_task_dont_redirect) {
check_url.searchParams.set('ajax_dont_redirect', '1');
}
async_task_id = data.async_id;
async_task_check_url = check_url.toString();
async_task_schedule_check(this, 100);
async_task_update_status(data);
if (location.href.indexOf("async_id") === -1) {
history.pushState({}, "Waiting", async_task_check_url.replace(/ajax=1/, ''));
}
function async_task_check_error (jqXHR, textStatus, errorThrown) {
'use strict'
let respdom = $(jqXHR.responseText)
let c = respdom.filter('.container')
if (jqXHR.status === 401 && jqXHR.getResponseHeader('X-Login-Url')) {
window.location = jqXHR.getResponseHeader('X-Login-Url') + '?next=' + encodeURIComponent(location.pathname + location.search + location.hash)
return
}
if (respdom.filter('form') && (respdom.filter('.has-error') || respdom.filter('.alert-danger'))) {
// This is a failed form validation, let's just use it
$('body').data('ajaxing', false)
async_task_replace_page('body', jqXHR.responseText.substring(
jqXHR.responseText.indexOf('<body'),
jqXHR.responseText.indexOf('</body')
))
} else if (c.length > 0) {
// This is some kind of 500/404/403 page, show it in an overlay
$('body').data('ajaxing', false)
waitingDialog.hide()
if (location.href.indexOf('async_id') !== -1) {
history.replaceState({}, 'pretix', async_task_old_url)
}
ajaxErrDialog.show(c.first().html())
} else {
if (jqXHR.status >= 400 && jqXHR.status < 500) {
$('body').data('ajaxing', false)
waitingDialog.hide()
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status))
} else {
// 500 can be an application error or overload in some cases :(
waitingDialog.setStatus(gettext('We currently cannot reach the server, but we keep trying.'
+ ' Last error code: {code}').replace(/\{code\}/, jqXHR.status))
async_task_schedule_check(this, 5000)
}
}
}
function async_task_error(jqXHR, textStatus, errorThrown) {
"use strict";
$("body").data('ajaxing', false);
if (jqXHR.status === 401 && jqXHR.getResponseHeader("X-Login-Url")) {
window.location = jqXHR.getResponseHeader("X-Login-Url") + "?next=" + encodeURIComponent(location.pathname + location.search + location.hash);
return;
}
waitingDialog.hide();
if (textStatus === "timeout") {
alert(gettext("The request took too long. Please try again."));
} else if (jqXHR.responseText.indexOf('<html') > 0) {
var respdom = $(jqXHR.responseText);
var c = respdom.filter('.container');
if (respdom.filter('form') && (respdom.filter('.has-error') || respdom.filter('.alert-danger'))) {
if (respdom.filter('#page-wrapper') && $('#page-wrapper').length) {
// This is a failed form validation, let's just use it
async_task_replace_page("#page-wrapper", respdom.find("#page-wrapper").html());
} else {
async_task_replace_page("body", jqXHR.responseText.substring(
jqXHR.responseText.indexOf("<body"),
jqXHR.responseText.indexOf("</body")
));
document.dispatchEvent(new Event("pretix:async-task-error"))
function async_task_callback (data, jqXHR, status) {
'use strict'
$('body').data('ajaxing', false)
if (data.redirect) {
async_task_on_success.call(this, data)
return
}
let check_url = new URL(data.check_url, window.location)
if (async_task_dont_redirect) {
check_url.searchParams.set('ajax_dont_redirect', '1')
}
async_task_id = data.async_id
async_task_check_url = check_url.toString()
async_task_schedule_check(this, 100)
}
async_task_update_status(data)
} else if (c.length > 0) {
// This is some kind of 500/404/403 page, show it in an overlay
ajaxErrDialog.show(c.first().html());
} else {
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status));
}
} else {
if (jqXHR.status >= 400 && jqXHR.status < 500) {
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status));
} else {
alert(gettext('We currently cannot reach the server. Please try again. ' +
'Error code: {code}').replace(/\{code\}/, jqXHR.status));
}
}
if (location.href.indexOf('async_id') === -1) {
history.pushState({}, 'Waiting', async_task_check_url.replace(/ajax=1/, ''))
}
}
function async_task_error (jqXHR, textStatus, errorThrown) {
'use strict'
$('body').data('ajaxing', false)
if (jqXHR.status === 401 && jqXHR.getResponseHeader('X-Login-Url')) {
window.location = jqXHR.getResponseHeader('X-Login-Url') + '?next=' + encodeURIComponent(location.pathname + location.search + location.hash)
return
}
waitingDialog.hide()
if (textStatus === 'timeout') {
alert(gettext('The request took too long. Please try again.'))
} else if (jqXHR.responseText.indexOf('<html') > 0) {
let respdom = $(jqXHR.responseText)
let c = respdom.filter('.container')
if (respdom.filter('form') && (respdom.filter('.has-error') || respdom.filter('.alert-danger'))) {
if (respdom.filter('#page-wrapper') && $('#page-wrapper').length) {
// This is a failed form validation, let's just use it
async_task_replace_page('#page-wrapper', respdom.find('#page-wrapper').html())
} else {
async_task_replace_page('body', jqXHR.responseText.substring(
jqXHR.responseText.indexOf('<body'),
jqXHR.responseText.indexOf('</body')
))
document.dispatchEvent(new Event('pretix:async-task-error'))
}
} else if (c.length > 0) {
// This is some kind of 500/404/403 page, show it in an overlay
ajaxErrDialog.show(c.first().html())
} else {
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status))
}
} else {
if (jqXHR.status >= 400 && jqXHR.status < 500) {
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status))
} else {
alert(gettext('We currently cannot reach the server. Please try again. '
+ 'Error code: {code}').replace(/\{code\}/, jqXHR.status))
}
}
}
$(function () {
"use strict";
$("body").on('submit', 'form[data-asynctask]', function (e) {
// Not supported on IE, may lead to wrong results, but we don't support IE in the backend anymore
var submitter = e.originalEvent ? e.originalEvent.submitter : null;
'use strict'
$('body').on('submit', 'form[data-asynctask]', function (e) {
// Not supported on IE, may lead to wrong results, but we don't support IE in the backend anymore
let submitter = e.originalEvent ? e.originalEvent.submitter : null
if (submitter && submitter.hasAttribute("data-no-asynctask")) {
return;
}
if (submitter && submitter.hasAttribute('data-no-asynctask')) {
return
}
e.preventDefault();
$(this).removeClass("dirty"); // Avoid problems with are-you-sure.js
if ($("body").data('ajaxing')) {
return;
}
async_task_id = null;
async_task_is_download = $(this).is("[data-asynctask-download]");
async_task_dont_redirect = $(this).is("[data-asynctask-no-redirect]");
async_task_is_long = $(this).is("[data-asynctask-long]");
async_task_old_url = location.href;
$("body").data('ajaxing', true);
waitingDialog.show(
$(this).attr("data-asynctask-headline") || gettext('We are processing your request …'),
$(this).attr("data-asynctask-text") || '',
gettext(
'We are currently sending your request to the server. If this takes longer ' +
'than one minute, please check your internet connection and then reload ' +
'this page and try again.'
)
);
e.preventDefault()
$(this).removeClass('dirty') // Avoid problems with are-you-sure.js
if ($('body').data('ajaxing')) {
return
}
async_task_id = null
async_task_is_download = $(this).is('[data-asynctask-download]')
async_task_dont_redirect = $(this).is('[data-asynctask-no-redirect]')
async_task_is_long = $(this).is('[data-asynctask-long]')
async_task_old_url = location.href
$('body').data('ajaxing', true)
waitingDialog.show(
$(this).attr('data-asynctask-headline') || gettext('We are processing your request …'),
$(this).attr('data-asynctask-text') || '',
gettext(
'We are currently sending your request to the server. If this takes longer '
+ 'than one minute, please check your internet connection and then reload '
+ 'this page and try again.'
)
)
var action = this.action;
var formData = new FormData(this);
formData.append('ajax', '1');
if (async_task_dont_redirect) {
formData.append('ajax_dont_redirect', '1');
}
if (submitter && submitter.name) {
formData.append(submitter.name, submitter.value);
}
if (submitter && submitter.getAttribute("formaction")) {
action = submitter.getAttribute("formaction");
}
$.ajax(
{
'type': 'POST',
'url': action,
'data': formData,
processData: false,
contentType: false,
'success': async_task_callback,
'error': async_task_error,
'context': this,
'dataType': 'json',
'timeout': 60000,
}
);
});
let action = this.action
let formData = new FormData(this)
formData.append('ajax', '1')
if (async_task_dont_redirect) {
formData.append('ajax_dont_redirect', '1')
}
if (submitter && submitter.name) {
formData.append(submitter.name, submitter.value)
}
if (submitter && submitter.getAttribute('formaction')) {
action = submitter.getAttribute('formaction')
}
$.ajax(
{
type: 'POST',
url: action,
data: formData,
processData: false,
contentType: false,
success: async_task_callback,
error: async_task_error,
context: this,
dataType: 'json',
timeout: 60000,
}
)
})
window.addEventListener("pageshow", function (evt) {
// In Safari, if you submit an async task, then get redirected, then go back,
// Safari won't reload the HTML from disk cache but instead reuse the DOM of the
// previous request, thus not clearing the "loading" state.
if (evt.persisted && $("body").hasClass("loading")) {
setTimeout(function () {
window.location.reload();
}, 10);
}
}, false);
window.addEventListener('pageshow', function (evt) {
// In Safari, if you submit an async task, then get redirected, then go back,
// Safari won't reload the HTML from disk cache but instead reuse the DOM of the
// previous request, thus not clearing the "loading" state.
if (evt.persisted && $('body').hasClass('loading')) {
setTimeout(function () {
window.location.reload()
}, 10)
}
}, false)
$("#ajaxerr").on("click", ".ajaxerr-close", ajaxErrDialog.hide);
$("#loadingmodal").on("cancel", function() {
return false;
});
$("#loadingmodal").prop("closedBy", "none");
});
$('#ajaxerr').on('click', '.ajaxerr-close', ajaxErrDialog.hide)
$('#loadingmodal').on('cancel', function () {
return false
})
$('#loadingmodal').prop('closedBy', 'none')
})
var waitingDialog = {
show: function (title, text, status) {
"use strict";
this.setTitle(title);
this.setText(text);
this.setStatus(status || gettext('If this takes longer than a few minutes, please contact us.'));
this.setProgress(null);
this.setSteps(null);
document.getElementById("loadingmodal").showModal();
},
hide: function () {
"use strict";
document.getElementById("loadingmodal").close();
},
setTitle: function(title) {
$("#loadingmodal .modal-card-title").text(title);
},
setStatus: function(statusText) {
$("#loadingmodal p.status").text(statusText);
},
setText: function(text) {
if (text)
$("#loadingmodal .modal-card-description").text(text).show();
else
$("#loadingmodal .modal-card-description").hide();
},
setProgress: function(percentage) {
if (typeof percentage === 'number') {
$("#loadingmodal .progress").show();
$("#loadingmodal .progress .progress-bar").css("width", percentage + "%");
} else {
$("#loadingmodal .progress").hide();
}
},
setSteps: function(steps) {
var $steps = $("#loadingmodal .steps");
if (steps) {
$steps.html("").show()
for (var step of steps) {
$steps.append(
$("<span>").addClass("fa fa-fw")
.toggleClass("fa-check text-success", step.done)
.toggleClass("fa-cog fa-spin text-muted", !step.done)
).append(
$("<span>").text(step.label)
).append(
$("<br>")
)
}
} else {
$steps.hide();
}
}
};
show: function (title, text, status) {
'use strict'
this.setTitle(title)
this.setText(text)
this.setStatus(status || gettext('If this takes longer than a few minutes, please contact us.'))
this.setProgress(null)
this.setSteps(null)
document.getElementById('loadingmodal').showModal()
},
hide: function () {
'use strict'
document.getElementById('loadingmodal').close()
},
setTitle: function (title) {
$('#loadingmodal .modal-card-title').text(title)
},
setStatus: function (statusText) {
$('#loadingmodal p.status').text(statusText)
},
setText: function (text) {
if (text)
$('#loadingmodal .modal-card-description').text(text).show()
else
$('#loadingmodal .modal-card-description').hide()
},
setProgress: function (percentage) {
if (typeof percentage === 'number') {
$('#loadingmodal .progress').show()
$('#loadingmodal .progress .progress-bar').css('width', percentage + '%')
} else {
$('#loadingmodal .progress').hide()
}
},
setSteps: function (steps) {
let $steps = $('#loadingmodal .steps')
if (steps) {
$steps.html('').show()
for (let step of steps) {
$steps.append(
$('<span>').addClass('fa fa-fw')
.toggleClass('fa-check text-success', step.done)
.toggleClass('fa-cog fa-spin text-muted', !step.done)
).append(
$('<span>').text(step.label)
).append(
$('<br>')
)
}
} else {
$steps.hide()
}
}
}
var ajaxErrDialog = {
show: function (c) {
"use strict";
$("#ajaxerr").html(c);
$("#ajaxerr .links").html("<a class='btn btn-default ajaxerr-close'>"
+ gettext("Close message") + "</a>");
$("body").addClass("ajaxerr has-modal-dialog");
$("#ajaxerr").prop("hidden", false);
},
hide: function () {
"use strict";
$("body").removeClass("ajaxerr has-modal-dialog");
$("#ajaxerr").prop("hidden", true);
},
};
show: function (c) {
'use strict'
$('#ajaxerr').html(c)
$('#ajaxerr .links').html('<a class=\'btn btn-default ajaxerr-close\'>'
+ gettext('Close message') + '</a>')
$('body').addClass('ajaxerr has-modal-dialog')
$('#ajaxerr').prop('hidden', false)
},
hide: function () {
'use strict'
$('body').removeClass('ajaxerr has-modal-dialog')
$('#ajaxerr').prop('hidden', true)
},
}
@@ -1,7 +1,7 @@
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('a[href^="mailto:"]').forEach(function(link) {
// Replace [at] with @ and the [dot] with . in both the href and the displayed text (if needed)
link.href = link.href.replace('[at]', '@').replace('[dot]', '.');
link.textContent = link.textContent.replace('[at]', '@').replace('[dot]', '.');
});
});
document.addEventListener('DOMContentLoaded', function () {
document.querySelectorAll('a[href^="mailto:"]').forEach(function (link) {
// Replace [at] with @ and the [dot] with . in both the href and the displayed text (if needed)
link.href = link.href.replace('[at]', '@').replace('[dot]', '.')
link.textContent = link.textContent.replace('[at]', '@').replace('[dot]', '.')
})
})
+137 -140
View File
@@ -1,152 +1,149 @@
/*global $ */
setup_collapsible_details = function (el) {
el.find('.sneak-peek-trigger').each(function () {
let trigger = this
let button = this.querySelector('button')
let content = document.getElementById(button.getAttribute('aria-controls'))
if (content.scrollHeight < 200) {
trigger.remove()
content.classList.remove('sneak-peek-content')
return
}
content.setAttribute('aria-hidden', 'true')
content.setAttribute('inert', true)
button.setAttribute('aria-expanded', 'false')
button.addEventListener('click', function (e) {
button.setAttribute('aria-expanded', 'true')
content.setAttribute('aria-hidden', 'false')
content.removeAttribute('inert')
el.find('.sneak-peek-trigger').each(function() {
var trigger = this;
var button = this.querySelector('button');
var content = document.getElementById(button.getAttribute('aria-controls'));
if (content.scrollHeight < 200) {
trigger.remove();
content.classList.remove('sneak-peek-content');
return;
}
content.setAttribute('aria-hidden', 'true');
content.setAttribute('inert', true);
button.setAttribute('aria-expanded', 'false');
button.addEventListener('click', function (e) {
button.setAttribute('aria-expanded', 'true');
content.setAttribute('aria-hidden', 'false');
content.removeAttribute('inert');
content.addEventListener('transitionend', function () {
content.classList.remove('sneak-peek-content')
content.style.removeProperty('height')
// we need to keep the trigger/button in the DOM to not irritate screenreaders toggling visibility
trigger.classList.add('sr-only')
}, { once: true })
content.style.height = content.scrollHeight + 'px'
content.addEventListener('transitionend', function() {
content.classList.remove('sneak-peek-content');
content.style.removeProperty('height');
// we need to keep the trigger/button in the DOM to not irritate screenreaders toggling visibility
trigger.classList.add('sr-only');
}, {once: true});
content.style.height = content.scrollHeight + 'px';
button.addEventListener('click', function (e) {
// this will be called by screenreader users if they kept focus on the button after expanding
// we need to keep the trigger/button in the DOM to not irritate screenreaders toggling visibility
let expanded = button.getAttribute('aria-expanded') == 'true'
button.setAttribute('aria-expanded', !expanded)
content.setAttribute('aria-hidden', expanded)
})
button.addEventListener('blur', function (e) {
// if content is visible and the user leaves the button, we can safely remove the trigger/button
if (button.getAttribute('aria-expanded') == 'true') {
trigger.remove()
}
})
}, { once: true })
button.addEventListener('click', function (e) {
// this will be called by screenreader users if they kept focus on the button after expanding
// we need to keep the trigger/button in the DOM to not irritate screenreaders toggling visibility
var expanded = button.getAttribute('aria-expanded') == 'true';
button.setAttribute('aria-expanded', !expanded);
content.setAttribute('aria-hidden', expanded);
});
button.addEventListener('blur', function (e) {
// if content is visible and the user leaves the button, we can safely remove the trigger/button
if (button.getAttribute('aria-expanded') == 'true') {
trigger.remove();
}
});
}, { once: true });
let container = this.closest('details.sneak-peek-container')
if (container) {
function removeSneekPeakWhenClosed (e) {
if (e.newState == 'closed') {
container.removeEventListener('toggle', removeSneekPeakWhenClosed)
trigger.remove()
content.removeAttribute('aria-hidden')
content.removeAttribute('inert')
content.classList.remove('sneak-peek-content')
}
}
container.addEventListener('toggle', removeSneekPeakWhenClosed)
}
})
var container = this.closest('details.sneak-peek-container');
if (container) {
function removeSneekPeakWhenClosed(e) {
if (e.newState == "closed") {
container.removeEventListener("toggle", removeSneekPeakWhenClosed);
trigger.remove();
content.removeAttribute('aria-hidden');
content.removeAttribute('inert');
content.classList.remove('sneak-peek-content');
}
}
container.addEventListener("toggle", removeSneekPeakWhenClosed);
}
});
let isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'
el.find('details summary').click(function (e) {
if (this.tagName !== 'A' && $(e.target).closest('a').length > 0) {
return true
}
let $details = $(this).closest('details')
let isOpen = $details.prop('open')
let $detailsNotSummary = $details.children(':not(summary)')
if ($detailsNotSummary.is(':animated')) {
e.preventDefault()
return false
}
if (isOpen) {
$details.removeClass('details-open')
$detailsNotSummary.stop().show().slideUp(500, function () {
$details.prop('open', false)
})
} else {
$detailsNotSummary.stop().hide()
$details.prop('open', true)
$details.addClass('details-open')
$detailsNotSummary.slideDown()
}
e.preventDefault()
return false
}).keyup(function (event) {
if (32 == event.keyCode || (13 == event.keyCode && !isOpera)) {
// Space or Enter is pressed — trigger the `click` event on the `summary` element
// Opera already seems to trigger the `click` event when Enter is pressed
event.preventDefault()
$(this).click()
}
})
var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
el.find("details summary").click(function (e) {
if (this.tagName !== "A" && $(e.target).closest("a").length > 0) {
return true;
}
var $details = $(this).closest("details");
var isOpen = $details.prop("open");
var $detailsNotSummary = $details.children(':not(summary)');
if ($detailsNotSummary.is(':animated')) {
e.preventDefault();
return false;
}
if (isOpen) {
$details.removeClass("details-open");
$detailsNotSummary.stop().show().slideUp(500, function () {
$details.prop("open", false);
});
} else {
$detailsNotSummary.stop().hide();
$details.prop("open", true);
$details.addClass("details-open");
$detailsNotSummary.slideDown();
}
e.preventDefault();
return false;
}).keyup(function (event) {
if (32 == event.keyCode || (13 == event.keyCode && !isOpera)) {
// Space or Enter is pressed — trigger the `click` event on the `summary` element
// Opera already seems to trigger the `click` event when Enter is pressed
event.preventDefault();
$(this).click();
}
});
$('details').each(function () {
let $details = $(this),
$detailsSummary = $('summary', $details).first(),
$detailsNotSummary = $details.children(':not(summary)')
$details.prop('open', typeof $details.attr('open') == 'string')
if (!$details.prop('open')) {
if ($details.find('.has-error, .alert-danger').length) {
$details.addClass('details-open')
$details.prop('open', true)
} else {
$detailsNotSummary.hide()
}
} else {
$details.addClass('details-open')
}
$detailsSummary.attr({
role: 'button',
'aria-controls': $details.attr('id')
}).prop('tabIndex', 0).bind('selectstart dragstart mousedown', function () {
return false
})
})
$('details').each(function () {
var $details = $(this),
$detailsSummary = $('summary', $details).first(),
$detailsNotSummary = $details.children(':not(summary)');
$details.prop('open', typeof $details.attr('open') == 'string');
if (!$details.prop('open')) {
if ($details.find(".has-error, .alert-danger").length) {
$details.addClass("details-open");
$details.prop('open', true);
} else {
$detailsNotSummary.hide();
}
} else {
$details.addClass("details-open");
}
$detailsSummary.attr({
'role': 'button',
'aria-controls': $details.attr('id')
}).prop('tabIndex', 0).bind('selectstart dragstart mousedown', function () {
return false;
});
});
el.find('article button[data-toggle=variations]').click(function (e) {
let $button = $(this)
let $details = $button.closest('article')
let $detailsNotSummary = $button.attr('aria-controls') ? $('#' + $button.attr('aria-controls')) : $('.variations', $details)
let isOpen = !$detailsNotSummary.prop('hidden')
if ($detailsNotSummary.is(':animated')) {
e.preventDefault()
return false
}
el.find("article button[data-toggle=variations]").click(function (e) {
var $button = $(this);
var $details = $button.closest("article");
var $detailsNotSummary = $button.attr("aria-controls") ? $('#' + $button.attr("aria-controls")) : $(".variations", $details);
var isOpen = !$detailsNotSummary.prop("hidden");
if ($detailsNotSummary.is(':animated')) {
e.preventDefault();
return false;
}
let altLabel = $button.attr('data-label-alt')
$button.attr('data-label-alt', $button.text().trim())
$button.find('span').text(altLabel)
$button.attr('aria-expanded', !isOpen)
var altLabel = $button.attr("data-label-alt");
$button.attr("data-label-alt", $button.text().trim());
$button.find("span").text(altLabel);
$button.attr("aria-expanded", !isOpen);
if (isOpen) {
$details.removeClass("details-open");
$detailsNotSummary.stop().show().slideUp(500, function () {
$detailsNotSummary.prop("hidden", true);
});
} else {
$detailsNotSummary.prop("hidden", false).stop().hide();
$details.addClass("details-open");
$detailsNotSummary.slideDown();
}
e.preventDefault();
return false;
});
el.find(".variations-collapsed").prop("hidden", true);
};
if (isOpen) {
$details.removeClass('details-open')
$detailsNotSummary.stop().show().slideUp(500, function () {
$detailsNotSummary.prop('hidden', true)
})
} else {
$detailsNotSummary.prop('hidden', false).stop().hide()
$details.addClass('details-open')
$detailsNotSummary.slideDown()
}
e.preventDefault()
return false
})
el.find('.variations-collapsed').prop('hidden', true)
}
$(function () {
"use strict";
'use strict'
setup_collapsible_details($("body"));
});
setup_collapsible_details($('body'))
})
+10 -10
View File
@@ -1,11 +1,11 @@
['DOMContentLoaded', 'pretix:async-task-error'].forEach(function (ev) {
document.addEventListener(ev, function () {
document.querySelectorAll('#goback, #reload').forEach(function (element) {
const regularLoad = ev === 'DOMContentLoaded' && element.id === 'goback';
element.addEventListener('click', regularLoad
? () => window.history.back()
: () => window.location.reload()
);
});
});
});
document.addEventListener(ev, function () {
document.querySelectorAll('#goback, #reload').forEach(function (element) {
const regularLoad = ev === 'DOMContentLoaded' && element.id === 'goback'
element.addEventListener('click', regularLoad
? () => window.history.back()
: () => window.location.reload()
)
})
})
})
@@ -1,3 +1,3 @@
// Attempt to auto-open page in new tab. Will be ignored by most browser's popup blockers anyways, though.
var url = JSON.parse(document.getElementById('framebreak-url').innerText)
let url = JSON.parse(document.getElementById('framebreak-url').innerText)
window.open(url)
+21 -22
View File
@@ -1,30 +1,29 @@
// The actual gettext implementation is loaded asynchronously with the translation
function gettext(msgid) {
if (typeof django !== 'undefined' && typeof django.gettext !== 'undefined') {
return django.gettext(msgid);
}
return msgid;
function gettext (msgid) {
if (typeof django !== 'undefined' && typeof django.gettext !== 'undefined') {
return django.gettext(msgid)
}
return msgid
}
function ngettext(singular, plural, count) {
if (typeof django !== 'undefined' && typeof django.ngettext !== 'undefined') {
return django.ngettext(singular, plural, count);
}
return plural;
function ngettext (singular, plural, count) {
if (typeof django !== 'undefined' && typeof django.ngettext !== 'undefined') {
return django.ngettext(singular, plural, count)
}
return plural
}
function pgettext(context, msgid) {
if (typeof django !== 'undefined' && typeof django.pgettext !== 'undefined') {
return django.pgettext(context, msgid);
}
return msgid;
function pgettext (context, msgid) {
if (typeof django !== 'undefined' && typeof django.pgettext !== 'undefined') {
return django.pgettext(context, msgid)
}
return msgid
}
function interpolate(fmt, object, named) {
if (named) {
return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])});
} else {
return fmt.replace(/%s/g, function(match){return String(obj.shift())});
}
function interpolate (fmt, object, named) {
if (named) {
return fmt.replace(/%\(\w+\)s/g, function (match) { return String(obj[match.slice(2, -2)]) })
} else {
return fmt.replace(/%s/g, function (match) { return String(obj.shift()) })
}
}
+19 -20
View File
@@ -1,25 +1,24 @@
function i18nstring_localize(o) {
var locale = document.body.attributes['data-pretixlocale'].value
var short_locale = locale.split('-')[0]
if (o[locale])
return o[locale]
function i18nstring_localize (o) {
let locale = document.body.attributes['data-pretixlocale'].value
let short_locale = locale.split('-')[0]
if (o[locale])
return o[locale]
if (o[short_locale])
return o[short_locale]
if (o[short_locale])
return o[short_locale]
for (k of Object.keys(o)) {
if (k.split('-')[0] === short_locale && o[k]) {
return o[k]
}
}
for (let k of Object.keys(o)) {
if (k.split('-')[0] === short_locale && o[k]) {
return o[k]
}
}
if (o['en'])
return o['en']
if (o['en'])
return o['en']
for (k of Object.keys(o)) {
if (o[k]) {
return o[k]
}
}
for (let k of Object.keys(o)) {
if (o[k]) {
return o[k]
}
}
}
+1 -1
View File
@@ -32,7 +32,7 @@ $(document).on('pretix:bind-forms', () => {
}
if (dirty) {
beforeAfterSelect.dispatchEvent(new Event('change', {bubbles: true}))
beforeAfterSelect.dispatchEvent(new Event('change', { bubbles: true }))
}
}
referenceSelect.addEventListener('change', updateBeforeOption)
@@ -1,8 +1,8 @@
var intId = window.setInterval(function () {
$.get(location.href + '?ajax=1', function (data, status) {
if (data === "1") {
window.clearInterval(intId);
location.reload();
}
});
}, 500);
const intId = window.setInterval(function () {
$.get(location.href + '?ajax=1', function (data, _status) {
if (data === '1') {
window.clearInterval(intId)
location.reload()
}
})
}, 500)
+17 -17
View File
@@ -1,21 +1,21 @@
var hiddenfield = document.querySelector("input[name=origin][type=hidden]");
let hiddenfield = document.querySelector('input[name=origin][type=hidden]')
if (hiddenfield) {
hiddenfield.value = window.location.origin
hiddenfield.value = window.location.origin
}
async function runCheck() {
if (document.getElementById("good_origin")) {
if (document.getElementById("good_origin").innerText.split('').reverse().join('') !== window.location.origin) {
const response = await fetch(document.getElementById("bad_origin_report_url").innerText.split('').reverse().join(''), {
method: "POST",
mode: "cors",
referrerPolicy: "unsafe-url",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: "origin=" + window.location.origin,
});
}
}
async function runCheck () {
if (document.getElementById('good_origin')) {
if (document.getElementById('good_origin').innerText.split('').reverse().join('') !== window.location.origin) {
const _response = await fetch(document.getElementById('bad_origin_report_url').innerText.split('').reverse().join(''), {
method: 'POST',
mode: 'cors',
referrerPolicy: 'unsafe-url',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'origin=' + window.location.origin,
})
}
}
}
runCheck();
runCheck()
+95 -95
View File
@@ -1,118 +1,118 @@
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
let lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
;(function (exports) {
'use strict'
'use strict'
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
let Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var PLUS = '+'.charCodeAt(0)
var SLASH = '/'.charCodeAt(0)
var NUMBER = '0'.charCodeAt(0)
var LOWER = 'a'.charCodeAt(0)
var UPPER = 'A'.charCodeAt(0)
var PLUS_URL_SAFE = '-'.charCodeAt(0)
var SLASH_URL_SAFE = '_'.charCodeAt(0)
let PLUS = '+'.charCodeAt(0)
let SLASH = '/'.charCodeAt(0)
let NUMBER = '0'.charCodeAt(0)
let LOWER = 'a'.charCodeAt(0)
let UPPER = 'A'.charCodeAt(0)
let PLUS_URL_SAFE = '-'.charCodeAt(0)
let SLASH_URL_SAFE = '_'.charCodeAt(0)
function decode (elt) {
var code = elt.charCodeAt(0)
if (code === PLUS || code === PLUS_URL_SAFE) return 62 // '+'
if (code === SLASH || code === SLASH_URL_SAFE) return 63 // '/'
if (code < NUMBER) return -1 // no match
if (code < NUMBER + 10) return code - NUMBER + 26 + 26
if (code < UPPER + 26) return code - UPPER
if (code < LOWER + 26) return code - LOWER + 26
}
function decode (elt) {
let code = elt.charCodeAt(0)
if (code === PLUS || code === PLUS_URL_SAFE) return 62 // '+'
if (code === SLASH || code === SLASH_URL_SAFE) return 63 // '/'
if (code < NUMBER) return -1 // no match
if (code < NUMBER + 10) return code - NUMBER + 26 + 26
if (code < UPPER + 26) return code - UPPER
if (code < LOWER + 26) return code - LOWER + 26
}
function b64ToByteArray (b64) {
var i, j, l, tmp, placeHolders, arr
function b64ToByteArray (b64) {
let i, j, l, tmp, placeHolders, arr
if (b64.length % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
if (b64.length % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
var len = b64.length
placeHolders = b64.charAt(len - 2) === '=' ? 2 : b64.charAt(len - 1) === '=' ? 1 : 0
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
let len = b64.length
placeHolders = b64.charAt(len - 2) === '=' ? 2 : b64.charAt(len - 1) === '=' ? 1 : 0
// base64 is 4/3 + up to two characters of the original data
arr = new Arr(b64.length * 3 / 4 - placeHolders)
// base64 is 4/3 + up to two characters of the original data
arr = new Arr(b64.length * 3 / 4 - placeHolders)
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length
var L = 0
let L = 0
function push (v) {
arr[L++] = v
}
function push (v) {
arr[L++] = v
}
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
push((tmp & 0xFF0000) >> 16)
push((tmp & 0xFF00) >> 8)
push(tmp & 0xFF)
}
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
push((tmp & 0xFF0000) >> 16)
push((tmp & 0xFF00) >> 8)
push(tmp & 0xFF)
}
if (placeHolders === 2) {
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
push(tmp & 0xFF)
} else if (placeHolders === 1) {
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
push((tmp >> 8) & 0xFF)
push(tmp & 0xFF)
}
if (placeHolders === 2) {
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
push(tmp & 0xFF)
} else if (placeHolders === 1) {
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
push((tmp >> 8) & 0xFF)
push(tmp & 0xFF)
}
return arr
}
return arr
}
function uint8ToBase64 (uint8) {
var i
var extraBytes = uint8.length % 3 // if we have 1 byte left, pad 2 bytes
var output = ''
var temp, length
function uint8ToBase64 (uint8) {
let i
let extraBytes = uint8.length % 3 // if we have 1 byte left, pad 2 bytes
let output = ''
let temp, length
function encode (num) {
return lookup.charAt(num)
}
function encode (num) {
return lookup.charAt(num)
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
}
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output += tripletToBase64(temp)
}
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output += tripletToBase64(temp)
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1]
output += encode(temp >> 2)
output += encode((temp << 4) & 0x3F)
output += '=='
break
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
output += encode(temp >> 10)
output += encode((temp >> 4) & 0x3F)
output += encode((temp << 2) & 0x3F)
output += '='
break
default:
break
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1]
output += encode(temp >> 2)
output += encode((temp << 4) & 0x3F)
output += '=='
break
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
output += encode(temp >> 10)
output += encode((temp >> 4) & 0x3F)
output += encode((temp << 2) & 0x3F)
output += '='
break
default:
break
}
return output
}
return output
}
exports.toByteArray = b64ToByteArray
exports.fromByteArray = uint8ToBase64
exports.toByteArray = b64ToByteArray
exports.fromByteArray = uint8ToBase64
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
+28 -28
View File
@@ -1,33 +1,33 @@
$(function() {
$('.btn-clipboard').tooltip({
trigger: 'click',
placement: 'bottom'
});
/* global gettext */
$(function () {
$('.btn-clipboard').tooltip({
trigger: 'click',
placement: 'bottom'
})
function setTooltip(btn, message) {
$(btn).tooltip('hide')
.attr('data-original-title', message)
.tooltip('show');
}
function setTooltip (btn, message) {
$(btn).tooltip('hide')
.attr('data-original-title', message)
.tooltip('show')
}
function hideTooltip(btn) {
setTimeout(function() {
$(btn).tooltip('hide');
}, 1000);
}
function hideTooltip (btn) {
setTimeout(function () {
$(btn).tooltip('hide')
}, 1000)
}
var clipboard = new Clipboard('.btn-clipboard');
let clipboard = new Clipboard('.btn-clipboard')
clipboard.on('success', function(e) {
if (e.text.length > 0) {
setTooltip(e.trigger, gettext('Copied!'));
hideTooltip(e.trigger);
}
});
clipboard.on('error', function(e) {
setTooltip(e.trigger, gettext('Press Ctrl-C to copy!'));
hideTooltip(e.trigger);
});
});
clipboard.on('success', function (e) {
if (e.text.length > 0) {
setTooltip(e.trigger, gettext('Copied!'))
hideTooltip(e.trigger)
}
})
clipboard.on('error', function (e) {
setTooltip(e.trigger, gettext('Press Ctrl-C to copy!'))
hideTooltip(e.trigger)
})
})
+61 -65
View File
@@ -8,79 +8,75 @@
* Under MIT License
* Modified by Raphael Michel
*/
;(function($, window, document, undefined) {
;(function ($, window, document, undefined) {
let pluginName = 'metisMenu',
defaults = {
toggle: true,
}
var pluginName = "metisMenu",
defaults = {
toggle: true,
};
function Plugin (element, options) {
this.element = $(element)
this.settings = $.extend({}, defaults, options)
this._defaults = defaults
this._name = pluginName
this.init()
}
function Plugin(element, options) {
this.element = $(element);
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function () {
let $this = this.element,
$toggle = this.settings.toggle,
obj = this
Plugin.prototype = {
init: function() {
if (this.isIE() <= 9) {
$this.find('li.active').has('ul').children('ul').collapse('show')
$this.find('li').not('.active').has('ul').children('ul').collapse('hide')
} else {
$this.find('li.active').has('ul').children('ul').addClass('collapse in')
$this.find('li').not('.active').has('ul').children('ul').addClass('collapse')
}
var $this = this.element,
$toggle = this.settings.toggle,
obj = this;
$this.find('li').has('ul').children('a.arrow').on('click' + '.' + pluginName, function (e) {
e.preventDefault()
$(this).blur()
if (this.isIE() <= 9) {
$this.find("li.active").has("ul").children("ul").collapse("show");
$this.find("li").not(".active").has("ul").children("ul").collapse("hide");
} else {
$this.find("li.active").has("ul").children("ul").addClass("collapse in");
$this.find("li").not(".active").has("ul").children("ul").addClass("collapse");
}
$(this).parent('li').toggleClass('active').children('ul').collapse('toggle')
$this.find("li").has("ul").children("a.arrow").on("click" + "." + pluginName, function(e) {
e.preventDefault();
$(this).blur();
if ($toggle) {
$(this).parent('li').siblings().removeClass('active').children('ul.in').collapse('hide')
}
})
},
$(this).parent("li").toggleClass("active").children("ul").collapse("toggle");
isIE: function () { // https://gist.github.com/padolsey/527683
let undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i')
if ($toggle) {
$(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide");
}
while (
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
) {
return v > 4 ? v : undef
}
},
});
},
remove: function () {
this.element.off('.' + pluginName)
this.element.removeData(pluginName)
}
isIE: function() { //https://gist.github.com/padolsey/527683
var undef,
v = 3,
div = document.createElement("div"),
all = div.getElementsByTagName("i");
}
while (
div.innerHTML = "<!--[if gt IE " + (++v) + "]><i></i><![endif]-->",
all[0]
) {
return v > 4 ? v : undef;
}
},
remove: function() {
this.element.off("." + pluginName);
this.element.removeData(pluginName);
}
};
$.fn[pluginName] = function(options) {
this.each(function () {
var el = $(this);
if (el.data(pluginName)) {
el.data(pluginName).remove();
}
el.data(pluginName, new Plugin(this, options));
});
return this;
};
})(jQuery, window, document);
$.fn[pluginName] = function (options) {
this.each(function () {
let el = $(this)
if (el.data(pluginName)) {
el.data(pluginName).remove()
}
el.data(pluginName, new Plugin(this, options))
})
return this
}
})(jQuery, window, document)
@@ -1,35 +1,34 @@
/*global $ */
/*
Based on https://github.com/BlackrockDigital/startbootstrap-sb-admin-2
Copyright 2013-2016 Blackrock Digital LLC
MIT License
Modified by Raphael Michel
*/
//Loads the correct sidebar on window load,
//collapses the sidebar on window resize.
// Loads the correct sidebar on window load,
// collapses the sidebar on window resize.
// Sets the min-height of #page-wrapper to window size
$(window).bind("load resize", function () {
'use strict';
var topOffset = 50,
width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width;
if (width < 768) {
$('div.navbar-collapse').addClass('collapse');
topOffset = 100; // 2-row-menu
} else {
$('div.navbar-collapse').removeClass('collapse');
}
$(window).bind('load resize', function () {
'use strict'
let topOffset = 50,
width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width
if (width < 768) {
$('div.navbar-collapse').addClass('collapse')
topOffset = 100 // 2-row-menu
} else {
$('div.navbar-collapse').removeClass('collapse')
}
var height = ((this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height) - 1;
height = height - topOffset;
if (height < 1) height = 1;
if (height > topOffset) {
$("#page-wrapper").css("min-height", (height) + "px");
}
});
let height = ((this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height) - 1
height = height - topOffset
if (height < 1) height = 1
if (height > topOffset) {
$('#page-wrapper').css('min-height', (height) + 'px')
}
})
$(function () {
'use strict';
$('ul.nav ul.nav-second-level a.active').parent().parent().addClass('in').parent().addClass('active');
$('#side-menu').metisMenu({
'toggle': false,
});
});
'use strict'
$('ul.nav ul.nav-second-level a.active').parent().parent().addClass('in').parent().addClass('active')
$('#side-menu').metisMenu({
toggle: false,
})
})
@@ -1 +1 @@
document.forms[0].submit();
document.forms[0].submit()
@@ -1,26 +1,25 @@
/*global $,gettext*/
/* global add_log_expand_handlers */
$(function () {
if ($("div[data-lazy-id]").length == 0) {
return;
}
$.getJSON("widgets.json" + ($("select[name='subevent']").val() ? "?subevent=" + $("select[name='subevent']").val() : ""), function (data) {
$.each(data.widgets, function (k, v) {
$("[data-lazy-id=" + v.lazy + "]").removeClass("widget-lazy-loading");
$("[data-lazy-id=" + v.lazy + "] .widget").html(v.content);
});
});
});
if ($('div[data-lazy-id]').length == 0) {
return
}
$.getJSON('widgets.json' + ($('select[name=\'subevent\']').val() ? '?subevent=' + $('select[name=\'subevent\']').val() : ''), function (data) {
$.each(data.widgets, function (_k, v) {
$('[data-lazy-id=' + v.lazy + ']').removeClass('widget-lazy-loading')
$('[data-lazy-id=' + v.lazy + '] .widget').html(v.content)
})
})
})
$(function () {
if ($("#logs_target").length == 0) {
return;
}
$.get("dashboard/partials/logs", function (data) {
$("#logs_target").html(data)
add_log_expand_handlers($("#logs_target"))
});
$.get("dashboard/partials/warnings", function (data) {
$("#warnings_loading").remove()
$("#warnings_target").html(data)
});
});
if ($('#logs_target').length == 0) {
return
}
$.get('dashboard/partials/logs', function (data) {
$('#logs_target').html(data)
add_log_expand_handlers($('#logs_target'))
})
$.get('dashboard/partials/warnings', function (data) {
$('#warnings_loading').remove()
$('#warnings_target').html(data)
})
})
@@ -1,14 +1,12 @@
/*globals $, Morris, gettext, RRule, RRuleSet*/
$(function () {
var update = function () {
$.getJSON(location.href + '?ajax=true', {}, function (data) {
if (data.initialized) {
location.reload();
} else {
window.setTimeout(update, 500);
}
});
};
window.setTimeout(update, 500);
});
let update = function () {
$.getJSON(location.href + '?ajax=true', {}, function (data) {
if (data.initialized) {
location.reload()
} else {
window.setTimeout(update, 500)
}
})
}
window.setTimeout(update, 500)
})
@@ -1,91 +1,95 @@
/*global $, Sortable*/
/* global Sortable */
$(function () {
const allContainers = $("[data-dnd-url]");
function updateAllSortButtonStates() {
allContainers.each(function() { updateSortButtonState($(this)); });
}
function updateSortButtonState(container) {
var disabledUp = container.find(".sortable-up:disabled"),
firstUp = container.find(">tr[data-dnd-id] .sortable-up").first();
if (disabledUp.length && disabledUp.get(0) !== firstUp.get(0)) {
disabledUp.prop("disabled", false);
firstUp.prop("disabled", true);
}
const allContainers = $('[data-dnd-url]')
function updateAllSortButtonStates () {
allContainers.each(function () {
updateSortButtonState($(this))
})
}
function updateSortButtonState (container) {
let disabledUp = container.find('.sortable-up:disabled'),
firstUp = container.find('>tr[data-dnd-id] .sortable-up').first()
if (disabledUp.length && disabledUp.get(0) !== firstUp.get(0)) {
disabledUp.prop('disabled', false)
firstUp.prop('disabled', true)
}
var disabledDown = container.find(".sortable-down:disabled"),
lastDown = container.find(">tr[data-dnd-id] .sortable-down").last();
if (disabledDown.length && disabledDown.get(0) !== lastDown.get(0)) {
disabledDown.prop("disabled", false);
lastDown.prop("disabled", true);
}
}
let disabledDown = container.find('.sortable-down:disabled'),
lastDown = container.find('>tr[data-dnd-id] .sortable-down').last()
if (disabledDown.length && disabledDown.get(0) !== lastDown.get(0)) {
disabledDown.prop('disabled', false)
lastDown.prop('disabled', true)
}
}
let didSort = false, lastClick = 0;
allContainers.each(function(){
const container = $(this),
url = container.data("dnd-url"),
handle = $('<span class="btn btn-default btn-sm dnd-sort-handle"><i class="fa fa-arrows"></i></span>');
let didSort = false, lastClick = 0
allContainers.each(function () {
const container = $(this),
url = container.data('dnd-url'),
handle = $('<span class="btn btn-default btn-sm dnd-sort-handle"><i class="fa fa-arrows"></i></span>')
container.find(".dnd-container").append(handle);
if (!sessionStorage.dndShowMoveButtons) {
container.find(".sortable-up, .sortable-down").addClass("sr-only").on("click", function () {
sessionStorage.dndShowMoveButtons = 'true';
});
}
if (container.find("[data-dnd-id]").length < 2 && !container.data("dnd-group")) {
handle.addClass("disabled");
return;
}
function maybeShowSortButtons() {
if (Date.now() - lastClick < 3000) {
$("[data-dnd-url] .sortable-up, [data-dnd-url] .sortable-down").removeClass("sr-only");
updateAllSortButtonStates();
}
lastClick = Date.now();
}
container.find(".dnd-sort-handle").on("mouseup", maybeShowSortButtons);
const group = container.data("dnd-group");
const containers = group ? container.parent().find('[data-dnd-group="' + group + '"]') : container;
Sortable.create(container.get(0), {
filter: ".sortable-disabled",
handle: ".dnd-sort-handle",
group: group,
onMove: function (evt) {
return evt.related.className.indexOf('sortable-disabled') === -1;
},
onStart: function (evt) {
containers.addClass("sortable-dragarea");
container.parent().addClass("sortable-sorting");
didSort = false;
},
onEnd: function (evt) {
containers.removeClass("sortable-dragarea");
container.parent().removeClass("sortable-sorting");
if (!didSort) {
maybeShowSortButtons();
} else {
$("[data-dnd-url] .sortable-up, [data-dnd-url] .sortable-down").addClass("sr-only");
delete sessionStorage.dndShowMoveButtons;
}
},
onSort: function (evt){
if (evt.target !== evt.to) return;
didSort = true;
container.find('.dnd-container').append(handle)
if (!sessionStorage.dndShowMoveButtons) {
container.find('.sortable-up, .sortable-down').addClass('sr-only').on('click', function () {
sessionStorage.dndShowMoveButtons = 'true'
})
}
if (container.find('[data-dnd-id]').length < 2 && !container.data('dnd-group')) {
handle.addClass('disabled')
return
}
function maybeShowSortButtons () {
if (Date.now() - lastClick < 3000) {
$('[data-dnd-url] .sortable-up, [data-dnd-url] .sortable-down').removeClass('sr-only')
updateAllSortButtonStates()
}
lastClick = Date.now()
}
container.find('.dnd-sort-handle').on('mouseup', maybeShowSortButtons)
const group = container.data('dnd-group')
const containers = group ? container.parent().find('[data-dnd-group="' + group + '"]') : container
Sortable.create(container.get(0), {
filter: '.sortable-disabled',
handle: '.dnd-sort-handle',
group: group,
onMove: function (evt) {
return evt.related.className.indexOf('sortable-disabled') === -1
},
onStart: function () {
containers.addClass('sortable-dragarea')
container.parent().addClass('sortable-sorting')
didSort = false
},
onEnd: function () {
containers.removeClass('sortable-dragarea')
container.parent().removeClass('sortable-sorting')
if (!didSort) {
maybeShowSortButtons()
} else {
$('[data-dnd-url] .sortable-up, [data-dnd-url] .sortable-down').addClass('sr-only')
delete sessionStorage.dndShowMoveButtons
}
},
onSort: function (evt) {
if (evt.target !== evt.to) return
didSort = true
const ids = container.find("[data-dnd-id]").toArray().map(function (e) { return e.dataset.dndId; });
$.ajax(
{
'type': 'POST',
'url': url,
'headers': {'X-CSRFToken': $("input[name=csrfmiddlewaretoken]").val()},
'data': JSON.stringify({
ids: ids
}),
'contentType': "application/json",
'timeout': 30000
}
);
}
});
});
});
const ids = container.find('[data-dnd-id]').toArray().map(function (e) {
return e.dataset.dndId
})
$.ajax(
{
type: 'POST',
url: url,
headers: { 'X-CSRFToken': $('input[name=csrfmiddlewaretoken]').val() },
data: JSON.stringify({
ids: ids
}),
contentType: 'application/json',
timeout: 30000
}
)
}
})
})
})
File diff suppressed because it is too large Load Diff
@@ -1,3 +1,3 @@
$(function () {
$("input, select, textarea").not(":disabled").focus();
});
$('input, select, textarea').not(':disabled').focus()
})
+179 -182
View File
@@ -1,201 +1,198 @@
/*globals $*/
/* globals $ */
$(document).on("pretix:bind-forms", function () {
function cleanup(l) {
return $.trim(l.replace(/\n/g, ", "));
}
function combine($sel) {
var parts = [
$sel.filter("[name*=street]").val(),
$sel.filter("[name*=zipcode]").val(),
$sel.filter("[name*=city]").val(),
$sel.filter("[name*=state]").val(),
$sel.filter("[name*=country]").find("option:selected").text(),
$sel.filter("[name*=location]").val(),
]
var res = "";
for (var val of parts) {
if (val) {
if (res) {
res += ", "
}
res += val
}
}
return cleanup(res)
}
$(".geodata-section").each(function () {
// Geocoding
// detach notifications and append them to first label (should be from location)
var $notifications = $(".geodata-autoupdate", this).detach().appendTo($("label", this).first());
var $lat = $("input[name$=geo_lat]", this).first();
var $lon = $("input[name$=geo_lon]", this).first();
var lat;
var lon;
var $updateButton = $("[data-action=update]", this);
$(document).on('pretix:bind-forms', function () {
function cleanup (l) {
return $.trim(l.replace(/\n/g, ', '))
}
function combine ($sel) {
let parts = [
$sel.filter('[name*=street]').val(),
$sel.filter('[name*=zipcode]').val(),
$sel.filter('[name*=city]').val(),
$sel.filter('[name*=state]').val(),
$sel.filter('[name*=country]').find('option:selected').text(),
$sel.filter('[name*=location]').val(),
]
let res = ''
for (let val of parts) {
if (val) {
if (res) {
res += ', '
}
res += val
}
}
return cleanup(res)
}
$('.geodata-section').each(function () {
// Geocoding
// detach notifications and append them to first label (should be from location)
let $notifications = $('.geodata-autoupdate', this).detach().appendTo($('label', this).first())
let $lat = $('input[name$=geo_lat]', this).first()
let $lon = $('input[name$=geo_lon]', this).first()
let lat
let lon
let $updateButton = $('[data-action=update]', this)
var $location;
// The .geodata-section is expected to include either...
// ... an English "location" field
if ($("textarea[lang=en], input[lang=en]", this).length) {
$location = $("textarea[lang=en], input[lang=en], select", this).not("[name*=geo_]");
}
let $location
// The .geodata-section is expected to include either...
// ... an English "location" field
if ($('textarea[lang=en], input[lang=en]', this).length) {
$location = $('textarea[lang=en], input[lang=en], select', this).not('[name*=geo_]')
}
// ... a "location" field in any other language
if (!$location || !$location.length) {
var lang = $("textarea, input[type=text]", this).not("[name*=geo_]").first().attr("lang");
if (lang) {
$location = $("textarea[lang=" + lang + "], input[lang=" + lang + "], select", this);
}
}
// ... a "location" field in any other language
if (!$location || !$location.length) {
let lang = $('textarea, input[type=text]', this).not('[name*=geo_]').first().attr('lang')
if (lang) {
$location = $('textarea[lang=' + lang + '], input[lang=' + lang + '], select', this)
}
}
// ... or a set of fields like a full address form
if (!$location || !$location.length) {
$location = $("textarea, input, select", this).not("[name*=geo_]");
}
// ... or a set of fields like a full address form
if (!$location || !$location.length) {
$location = $('textarea, input, select', this).not('[name*=geo_]')
}
if (!$lat.length || !$lon.length || !$location.length) {
return;
}
if (!$lat.length || !$lon.length || !$location.length) {
return
}
var debounceLoad, debounceLatLonChange, delayUpdateDismissal;
var touched = $lat.val() !== "";
var xhr;
var lastLocation = combine($location);
let debounceLoad, debounceLatLonChange, delayUpdateDismissal
let touched = $lat.val() !== ''
let xhr
let lastLocation = combine($location)
function load() {
window.clearTimeout(debounceLoad);
if (xhr) {
xhr.abort();
xhr = null;
}
function load () {
window.clearTimeout(debounceLoad)
if (xhr) {
xhr.abort()
xhr = null
}
var q = combine($location);
if (q === "" || q === lastLocation) return;
let q = combine($location)
if (q === '' || q === lastLocation) return
lastLocation = q;
$notifications.attr("data-notify", "loading");
lastLocation = q
$notifications.attr('data-notify', 'loading')
xhr = $.getJSON('/control/geocode/?q=' + encodeURIComponent(q), function (res) {
if (!res.results || !res.results.length) {
$notifications.attr("data-notify", "error");
return;
}
xhr = $.getJSON('/control/geocode/?q=' + encodeURIComponent(q), function (res) {
if (!res.results || !res.results.length) {
$notifications.attr('data-notify', 'error')
return
}
lat = res.results[0].lat;
lon = res.results[0].lon;
if ($lat.val() == lat && $lon.val() == lon) {
$notifications.attr("data-notify", "");
}
else if (touched) {
$notifications.attr("data-notify", "confirm");
}
else {
$notifications.attr("data-notify", "");
$lat.val(lat);
$lon.val(lon);
center(13);
}
})
}
lat = res.results[0].lat
lon = res.results[0].lon
if ($lat.val() == lat && $lon.val() == lon) {
$notifications.attr('data-notify', '')
} else if (touched) {
$notifications.attr('data-notify', 'confirm')
} else {
$notifications.attr('data-notify', '')
$lat.val(lat)
$lon.val(lon)
center(13)
}
})
}
$lat.add($lon).change(function () {
if (this.value !== "") touched = true;
center(13);
}).keyup(function () {
window.clearTimeout(debounceLatLonChange);
debounceLatLonChange = window.setTimeout(center, 300);
});
$lat.add($lon).change(function () {
if (this.value !== '') touched = true
center(13)
}).keyup(function () {
window.clearTimeout(debounceLatLonChange)
debounceLatLonChange = window.setTimeout(center, 300)
})
$location.change(load);
$location.keyup(function () {
window.clearTimeout(debounceLoad);
debounceLoad = window.setTimeout(load, 1000);
if ($notifications.attr("data-notify") == "confirm" && lastLocation !== cleanup(this.value)) $notifications.attr("data-notify", "");
});
$location.change(load)
$location.keyup(function () {
window.clearTimeout(debounceLoad)
debounceLoad = window.setTimeout(load, 1000)
if ($notifications.attr('data-notify') == 'confirm' && lastLocation !== cleanup(this.value)) $notifications.attr('data-notify', '')
})
$updateButton.click(function() {
$lat.val(lat);
$lon.val(lon).trigger("change");// change-event is needed by bulk-edit
touched = false;
center(13);
$notifications.attr("data-notify", "updated");
delayUpdateDismissal = window.setTimeout(function() {
if ($notifications.attr("data-notify") == "updated") $notifications.attr("data-notify", "");
}, 2500);
});
$updateButton.click(function () {
$lat.val(lat)
$lon.val(lon).trigger('change')// change-event is needed by bulk-edit
touched = false
center(13)
$notifications.attr('data-notify', 'updated')
delayUpdateDismissal = window.setTimeout(function () {
if ($notifications.attr('data-notify') == 'updated') $notifications.attr('data-notify', '')
}, 2500)
})
// Map
var $grp = $(".geodata-group", this);
var tiles = $grp.attr("data-tiles");
var attrib = $grp.attr("data-attrib");
if (tiles) {
var $map = $("<div>");
$grp.append($("<div>").addClass("col-md-9 col-md-offset-3").append($map));
var map = L.map($map.get(0));
L.tileLayer(tiles, {
attribution: attrib,
maxZoom: 18,
}).addTo(map);
// Map
let $grp = $('.geodata-group', this)
let tiles = $grp.attr('data-tiles')
let attrib = $grp.attr('data-attrib')
if (tiles) {
let $map = $('<div>')
$grp.append($('<div>').addClass('col-md-9 col-md-offset-3').append($map))
let map = L.map($map.get(0))
L.tileLayer(tiles, {
attribution: attrib,
maxZoom: 18,
}).addTo(map)
function getpoint() {
if ($lat.val() !== "" && $lon.val() !== "") {
var p = [parseFloat($lat.val().replace(",", ".")), parseFloat($lon.val().replace(",", "."))];
// Clip to valid ranges. Very invalid lon/lat values can even lead to browser crashes in leaflet apparently
if (p[0] < -90) p[0] = -90
if (p[0] > 90) p[0] = 90
if (p[1] < -180) p[1] = -180
if (p[1] > 180) p[1] = 180
return p
} else {
return [0.0, 0.0];
}
}
function getpoint () {
if ($lat.val() !== '' && $lon.val() !== '') {
let p = [parseFloat($lat.val().replace(',', '.')), parseFloat($lon.val().replace(',', '.'))]
// Clip to valid ranges. Very invalid lon/lat values can even lead to browser crashes in leaflet apparently
if (p[0] < -90) p[0] = -90
if (p[0] > 90) p[0] = 90
if (p[1] < -180) p[1] = -180
if (p[1] > 180) p[1] = 180
return p
} else {
return [0.0, 0.0]
}
}
var marker = L.marker(getpoint(), {
draggable: 'true',
icon: L.icon({
iconUrl: $grp.attr("data-icon"),
shadowUrl: $grp.attr("data-shadow"),
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
tooltipAnchor: [16, -28],
shadowSize: [41, 41]
})
});
marker.addTo(map);
marker.on("dragend", function (event) {
var position = marker.getLatLng();
marker.setLatLng(position, {
draggable: 'true'
}).bindPopup(position).update();
$lat.val(position.lat.toFixed(7));
$lon.val(position.lng.toFixed(7));
touched = true;
center(null);
});
let marker = L.marker(getpoint(), {
draggable: 'true',
icon: L.icon({
iconUrl: $grp.attr('data-icon'),
shadowUrl: $grp.attr('data-shadow'),
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
tooltipAnchor: [16, -28],
shadowSize: [41, 41]
})
})
marker.addTo(map)
marker.on('dragend', function (event) {
let position = marker.getLatLng()
marker.setLatLng(position, {
draggable: 'true'
}).bindPopup(position).update()
$lat.val(position.lat.toFixed(7))
$lon.val(position.lng.toFixed(7))
touched = true
center(null)
})
function center(zoom) {
if ($lat.val() !== "" && $lon.val() !== "") {
if (zoom) {
map.setView(getpoint(), zoom);
} else {
map.panTo(getpoint());
}
marker.setLatLng(getpoint(), {
draggable: 'true'
}).bindPopup(getpoint()).update();
} else {
map.fitWorld();
}
}
function center (zoom) {
if ($lat.val() !== '' && $lon.val() !== '') {
if (zoom) {
map.setView(getpoint(), zoom)
} else {
map.panTo(getpoint())
}
marker.setLatLng(getpoint(), {
draggable: 'true'
}).bindPopup(getpoint()).update()
} else {
map.fitWorld()
}
}
center(13);
} else {
function center(zoom) {
}
}
});
});
center(13)
} else {
function center (zoom) {
}
}
})
})
@@ -1,39 +1,39 @@
$(function () {
hideDeselected(false);
hideDeselected(false)
function hideDeselected(animate) {
var v = $("input[name='quota_option']:checked").val(),
fn = animate ? 'slideDown' : 'show';
if (v === "existing") {
hideAll(animate);
$("#existing-quota-group").children()[fn]();
} else if (v === "new") {
hideAll(animate);
if ($("#id_quota_add_new_name").val() === "") {
$("#id_quota_add_new_name").val($("input[name^=name_]").first().val());
}
$("#new-quota-group").children()[fn]();
} else {
hideAll(animate);
}
}
function hideDeselected (animate) {
let v = $('input[name=\'quota_option\']:checked').val(),
fn = animate ? 'slideDown' : 'show'
if (v === 'existing') {
hideAll(animate)
$('#existing-quota-group').children()[fn]()
} else if (v === 'new') {
hideAll(animate)
if ($('#id_quota_add_new_name').val() === '') {
$('#id_quota_add_new_name').val($('input[name^=name_]').first().val())
}
$('#new-quota-group').children()[fn]()
} else {
hideAll(animate)
}
}
function hideAll(animate) {
var fn = animate ? 'slideUp' : 'hide';
$("#new-quota-group").children()[fn]();
$("#existing-quota-group").children()[fn]();
}
function hideAll (animate) {
let fn = animate ? 'slideUp' : 'hide'
$('#new-quota-group').children()[fn]()
$('#existing-quota-group').children()[fn]()
}
$("input[name='quota_option']").on('change',
function () {
hideDeselected(true);
}
);
$('input[name=\'quota_option\']').on('change',
function () {
hideDeselected(true)
}
)
function toggleblock() {
$("#new-quota-group").closest('fieldset').toggle(!$("[name=has_variations][value=on]").prop('checked'));
}
function toggleblock () {
$('#new-quota-group').closest('fieldset').toggle(!$('[name=has_variations][value=on]').prop('checked'))
}
$("[name=has_variations]").change(toggleblock);
toggleblock();
});
$('[name=has_variations]').change(toggleblock)
toggleblock()
})
+65 -65
View File
@@ -1,75 +1,75 @@
function preview_task_callback(data, jqXHR, status) {
"use strict";
if (data.item) {
$('#' + data.item + '_panel').data('ajaxing', false);
for (var m in data.msgs){
var target = $('div[for=' + data.item + '][lang=' + m +']');
if (target.length === 1){
target.html(data.msgs[m]);
target.find('.placeholder').tooltip();
}
}
}
/* global gettext */
function preview_task_callback (data, _jqXHR, _status) {
'use strict'
if (data.item) {
$('#' + data.item + '_panel').data('ajaxing', false)
for (let m in data.msgs) {
let target = $('div[for=' + data.item + '][lang=' + m + ']')
if (target.length === 1) {
target.html(data.msgs[m])
target.find('.placeholder').tooltip()
}
}
}
}
function preview_task_error(item) {
"use strict";
return function(jqXHR, textStatus, errorThrown) {
$('#' + item + '_panel').data('ajaxing', false);
$('#' + item + '_preview div').text(gettext('An error has occurred.'));
if (textStatus === "timeout") {
alert(gettext("The request took too long. Please try again."));
} else {
if (jqXHR.status >= 400 && jqXHR.status < 500) {
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status));
} else {
alert(gettext('We currently cannot reach the server. Please try again. ' +
'Error code: {code}').replace(/\{code\}/, jqXHR.status));
}
}
}
function preview_task_error (item) {
'use strict'
return function (jqXHR, textStatus, _errorThrown) {
$('#' + item + '_panel').data('ajaxing', false)
$('#' + item + '_preview div').text(gettext('An error has occurred.'))
if (textStatus === 'timeout') {
alert(gettext('The request took too long. Please try again.'))
} else {
if (jqXHR.status >= 400 && jqXHR.status < 500) {
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status))
} else {
alert(gettext('We currently cannot reach the server. Please try again. '
+ 'Error code: {code}').replace(/\{code\}/, jqXHR.status))
}
}
}
}
function mail_preview_setup($el) {
$el.find('.mail-preview .placeholder').tooltip();
$el.find('a[type=preview]').on('click', function () {
var itemName = $(this).closest('.preview-panel').attr('for');
if ($('#' + itemName + '_panel').data('ajaxing') || $(this).parent('.active').length !== 0) {
return;
}
function mail_preview_setup ($el) {
$el.find('.mail-preview .placeholder').tooltip()
$el.find('a[type=preview]').on('click', function () {
let itemName = $(this).closest('.preview-panel').attr('for')
if ($('#' + itemName + '_panel').data('ajaxing') || $(this).parent('.active').length !== 0) {
return
}
// gathering data
var parentForm = $(this).closest('form');
var previewUrl = $(parentForm).attr('mail-preview-url');
var token = $(parentForm).find('input[name=csrfmiddlewaretoken]').val();
var dataString = 'item=' + itemName + '&csrfmiddlewaretoken=' + token;
$('#' + itemName + '_edit textarea, #' + itemName + '_edit input').each(function () {
dataString += '&' + $(this).serialize();
});
// gathering data
let parentForm = $(this).closest('form')
let previewUrl = $(parentForm).attr('mail-preview-url')
let token = $(parentForm).find('input[name=csrfmiddlewaretoken]').val()
let dataString = 'item=' + itemName + '&csrfmiddlewaretoken=' + token
$('#' + itemName + '_edit textarea, #' + itemName + '_edit input').each(function () {
dataString += '&' + $(this).serialize()
})
// prepare for ajax
$('#' + itemName + '_panel').data('ajaxing', true);
$('#' + itemName + '_preview div').text(gettext('Generating messages …'));
// prepare for ajax
$('#' + itemName + '_panel').data('ajaxing', true)
$('#' + itemName + '_preview div').text(gettext('Generating messages …'))
$.ajax(
{
'type': 'POST',
'url': previewUrl,
'data': dataString,
'success': preview_task_callback,
'error': preview_task_error(itemName),
'dataType': 'json',
'timeout': 60000,
}
);
});
$.ajax(
{
type: 'POST',
url: previewUrl,
data: dataString,
success: preview_task_callback,
error: preview_task_error(itemName),
dataType: 'json',
timeout: 60000,
}
)
})
}
$(function () {
"use strict";
mail_preview_setup($("body"));
$(document).on("pretix:bind-forms", function () {
mail_preview_setup($("body"));
});
});
'use strict'
mail_preview_setup($('body'))
$(document).on('pretix:bind-forms', function () {
mail_preview_setup($('body'))
})
})
File diff suppressed because it is too large Load Diff
@@ -1,59 +1,62 @@
/*global $, gettext*/
/* global gettext */
$(function () {
if (!$(".form-order-change").length) {
return;
}
$(".form-order-change").each(function () {
var url = $(this).attr("data-pricecalc-endpoint");
var $itemvar = $(this).find("[name*=itemvar]");
var $subevent = $(this).find("[name*=subevent]");
var $tax_rule = $(this).find("[name*=tax_rule]");
var $price = $(this).find("[name*=price]");
var update_price = function () {
console.log(url);
var itemvar = $itemvar.val();
var item = null;
var variation = null;
if (itemvar.indexOf("-")) {
item = parseInt(itemvar.split("-")[0]);
variation = parseInt(itemvar.split("-")[1]);
} else {
item = parseInt(itemvar);
}
$price.closest(".field-container").append("<small class=\"loading-indicator\"><span class=\"fa fa-cog fa-spin\"></span> " +
gettext("Calculating default price…") + "</small>");
$.ajax(
{
'type': 'POST',
'url': url,
'headers': {'X-CSRFToken': $("input[name=csrfmiddlewaretoken]").val()},
'data': JSON.stringify({
'item': item,
'variation': variation,
'subevent': $subevent.val(),
'tax_rule': $tax_rule.val(),
'locale': $("body").attr("data-pretixlocale"),
}),
'contentType': "application/json",
'success': function (data) {
$price.val(data.gross_formatted);
$tax_rule.val(data.tax_rule);
$price.closest(".field-container").find(".loading-indicator").remove();
},
// 'error': …
'context': this,
'dataType': 'json',
'timeout': 30000
}
);
};
$itemvar.on("change", function () { $tax_rule.val(null); update_price() });
$tax_rule.on("change", update_price);
$subevent.on("change", update_price).on("change", function () {
var seat = $(this).closest(".form-order-change").find("[id$=seat]");
if (seat.length) {
seat.prop("required", !!$subevent.val());
}
});
});
});
if (!$('.form-order-change').length) {
return
}
$('.form-order-change').each(function () {
let url = $(this).attr('data-pricecalc-endpoint')
let $itemvar = $(this).find('[name*=itemvar]')
let $subevent = $(this).find('[name*=subevent]')
let $tax_rule = $(this).find('[name*=tax_rule]')
let $price = $(this).find('[name*=price]')
let update_price = function () {
console.log(url)
let itemvar = $itemvar.val()
let item
let variation = null
if (itemvar.indexOf('-')) {
item = parseInt(itemvar.split('-')[0])
variation = parseInt(itemvar.split('-')[1])
} else {
item = parseInt(itemvar)
}
$price.closest('.field-container').append('<small class="loading-indicator"><span class="fa fa-cog fa-spin"></span> '
+ gettext('Calculating default price…') + '</small>')
$.ajax(
{
type: 'POST',
url: url,
headers: { 'X-CSRFToken': $('input[name=csrfmiddlewaretoken]').val() },
data: JSON.stringify({
item: item,
variation: variation,
subevent: $subevent.val(),
tax_rule: $tax_rule.val(),
locale: $('body').attr('data-pretixlocale'),
}),
contentType: 'application/json',
success: function (data) {
$price.val(data.gross_formatted)
$tax_rule.val(data.tax_rule)
$price.closest('.field-container').find('.loading-indicator').remove()
},
// 'error': …
context: this,
dataType: 'json',
timeout: 30000
}
)
}
$itemvar.on('change', function () {
$tax_rule.val(null)
update_price()
})
$tax_rule.on('change', update_price)
$subevent.on('change', update_price).on('change', function () {
let seat = $(this).closest('.form-order-change').find('[id$=seat]')
if (seat.length) {
seat.prop('required', !!$subevent.val())
}
})
})
})
@@ -1,43 +1,43 @@
function is_sandbox_supported() {
const iframe = document.createElement('iframe');
return 'sandbox' in iframe;
function is_sandbox_supported () {
const iframe = document.createElement('iframe')
return 'sandbox' in iframe
}
function safe_render(url, parent) {
// Estimate the height that prevents the user from having to scroll on two levels to see the full email
const height = (
Math.max(400, window.innerHeight - parent.parent().get(0).getBoundingClientRect().top - document.querySelector("footer").getBoundingClientRect().height - 20)
) + "px";
function safe_render (url, parent) {
// Estimate the height that prevents the user from having to scroll on two levels to see the full email
const height = (
Math.max(400, window.innerHeight - parent.parent().get(0).getBoundingClientRect().top - document.querySelector('footer').getBoundingClientRect().height - 20)
) + 'px'
const iframe = (
// Per the HTML spec, a data: URL in an iframe is treated as its own origin:
// https://github.com/whatwg/html/pull/1756
// It is unclear, if Firefox complies, and the behaviour around data URLs is quite wild:
// https://github.com/whatwg/html/issues/12091
// Together with the sandbox attribute disallowing all JavaScript, and the fact
// that we sanitize the HTML before we even save it to the database, this should
// still be the safest way to render HTML in the context of our backend.
$("<iframe>")
.height(height)
.attr("class", "html-email")
.attr("src", url)
.attr("sandbox", "allow-popups allow-popups-to-escape-sandbox")
.attr("csp", "script-src 'none'; font-src 'none'; connect-src 'none'; form-action 'none'; style-src 'unsafe-inline'") // respected only by chrome
.prop("credentialless", true) // respected only by chrome
);
const iframe = (
// Per the HTML spec, a data: URL in an iframe is treated as its own origin:
// https://github.com/whatwg/html/pull/1756
// It is unclear, if Firefox complies, and the behaviour around data URLs is quite wild:
// https://github.com/whatwg/html/issues/12091
// Together with the sandbox attribute disallowing all JavaScript, and the fact
// that we sanitize the HTML before we even save it to the database, this should
// still be the safest way to render HTML in the context of our backend.
$('<iframe>')
.height(height)
.attr('class', 'html-email')
.attr('src', url)
.attr('sandbox', 'allow-popups allow-popups-to-escape-sandbox')
.attr('csp', 'script-src \'none\'; font-src \'none\'; connect-src \'none\'; form-action \'none\'; style-src \'unsafe-inline\'') // respected only by chrome
.prop('credentialless', true) // respected only by chrome
)
console.log(parent, iframe);
parent.append(iframe);
console.log(parent, iframe)
parent.append(iframe)
}
$(function () {
const script_element = $("#mail_body_html");
if (!script_element.length) return;
if (!is_sandbox_supported()) {
// Browser is too old for <iframe sandbox>
$(script_element.parent()).text("Please switch to a modern browser to view HTML content safely.");
return;
}
const script_element = $('#mail_body_html')
if (!script_element.length) return
if (!is_sandbox_supported()) {
// Browser is too old for <iframe sandbox>
$(script_element.parent()).text('Please switch to a modern browser to view HTML content safely.')
return
}
safe_render(JSON.parse(script_element.html()), script_element.parent());
});
safe_render(JSON.parse(script_element.html()), script_element.parent())
})
@@ -1,84 +1,89 @@
$(function() {
var plugins = $(".plugin-container").toArray().map(function(el) {
return {
sortName: el.getAttribute('data-plugin-name').toLowerCase().replace(/pretix /g, ''),
name: el.getAttribute('data-plugin-name').toLowerCase(),
module: el.getAttribute('data-plugin-module').toLowerCase(),
description: $(el).find('.plugin-description').text().toLowerCase(),
html: el.outerHTML,
category: $(el).closest('[data-plugin-category]').attr('data-plugin-category'),
categoryLabel: $(el).closest('[data-plugin-category]').attr('data-plugin-category-label'),
active: !!$(el).has('[data-is-active]').length,
}
});
function SearchMatcher(term, fields) {
this.searchFor = term.toLowerCase().split(/\s+/);
this.fields = fields;
}
function inStringRanked(haystack, needle) {
let pos = -1, rank = 0;
do {
pos = haystack.indexOf(needle, pos + 1);
if (pos !== -1) rank = 10;
if (pos === 0 || haystack.charCodeAt(pos - 1) <= 47)
return 15; // string start or word start (=char before match is special char)
} while (pos !== -1);
return rank;
}
SearchMatcher.prototype.isMatch = function(obj) {
let rank = 0;
for(let j = 0; j < this.searchFor.length; j++) {
var searchFor = this.searchFor[j];
for(let i = this.fields.length - 1; i >= 0; i--) {
var result = inStringRanked(obj[this.fields[i]], searchFor);
if (result) {
rank += (i + 1) * result;
break;
}
}
}
return rank;
}
function strcmp(a, b) {
return a > b ? 1 : a < b ? -1 : 0;
}
var $results_box = $("#plugin_search_results");
var $plugin_tabs = $("#plugin_tabs");
var $results = $("#plugin_search_results .plugin-list");
function search() {
$results.html("");
var value = $("#plugin_search_input").val();
var only_active = $("input[name=plugin_state_filter][value=active]").prop("checked");
if (!value && !only_active) {
$results_box.hide(); $plugin_tabs.show();
return;
}
$results_box.show(); $plugin_tabs.hide();
var matcher = new SearchMatcher(value, ["description", "module", "name"]);
var matches = [];
for(const plugin of plugins) {
if (only_active && !plugin.active) continue;
var rank = matcher.isMatch(plugin);
if (!rank) continue;
matches.push([rank, plugin]);
}
matches.sort(function (a,b) { return (b[0]-a[0]) || strcmp(a[1].sortName, b[1].sortName); })
$results.append(matches.map(function(res) { return $(res[1].html).prepend('<span class="pull-right">' + res[1].categoryLabel + '</span>'); }))
$results.find(".panel-body, .panel, .featured-plugin, .btn-lg").removeClass("panel-body panel featured-plugin btn-lg");
if (matches.length === 0) {
$results.append(gettext("No results"));
}
}
$("#plugin_search_input").on("input", search);
$("input[name=plugin_state_filter]").on("change", search);
$results_box.find("button.close").on("click", function() {
$("input[name=plugin_state_filter][value=all]").prop("checked", true).trigger("click");
$("#plugin_search_input").val("").trigger("input");
});
if (location.search) {
var search = new URLSearchParams(location.search);
if (search.has('q')) {
$("#plugin_search_input").val(search.get("q")).trigger("input");
}
}
/* global gettext */
$(function () {
let plugins = $('.plugin-container').toArray().map(function (el) {
return {
sortName: el.getAttribute('data-plugin-name').toLowerCase().replace(/pretix /g, ''),
name: el.getAttribute('data-plugin-name').toLowerCase(),
module: el.getAttribute('data-plugin-module').toLowerCase(),
description: $(el).find('.plugin-description').text().toLowerCase(),
html: el.outerHTML,
category: $(el).closest('[data-plugin-category]').attr('data-plugin-category'),
categoryLabel: $(el).closest('[data-plugin-category]').attr('data-plugin-category-label'),
active: !!$(el).has('[data-is-active]').length,
}
})
function SearchMatcher (term, fields) {
this.searchFor = term.toLowerCase().split(/\s+/)
this.fields = fields
}
function inStringRanked (haystack, needle) {
let pos = -1, rank = 0
do {
pos = haystack.indexOf(needle, pos + 1)
if (pos !== -1) rank = 10
if (pos === 0 || haystack.charCodeAt(pos - 1) <= 47)
return 15 // string start or word start (=char before match is special char)
} while (pos !== -1)
return rank
}
SearchMatcher.prototype.isMatch = function (obj) {
let rank = 0
for (let j = 0; j < this.searchFor.length; j++) {
let searchFor = this.searchFor[j]
for (let i = this.fields.length - 1; i >= 0; i--) {
let result = inStringRanked(obj[this.fields[i]], searchFor)
if (result) {
rank += (i + 1) * result
break
}
}
}
return rank
}
function strcmp (a, b) {
return a > b ? 1 : a < b ? -1 : 0
}
let $results_box = $('#plugin_search_results')
let $plugin_tabs = $('#plugin_tabs')
let $results = $('#plugin_search_results .plugin-list')
function search () {
$results.html('')
let value = $('#plugin_search_input').val()
let only_active = $('input[name=plugin_state_filter][value=active]').prop('checked')
if (!value && !only_active) {
$results_box.hide()
$plugin_tabs.show()
return
}
$results_box.show()
$plugin_tabs.hide()
let matcher = new SearchMatcher(value, ['description', 'module', 'name'])
let matches = []
for (const plugin of plugins) {
if (only_active && !plugin.active)
continue
let rank = matcher.isMatch(plugin)
if (!rank)
continue
matches.push([rank, plugin])
}
matches.sort(function (a, b) { return (b[0] - a[0]) || strcmp(a[1].sortName, b[1].sortName) })
$results.append(matches.map(function (res) { return $(res[1].html).prepend('<span class="pull-right">' + res[1].categoryLabel + '</span>') }))
$results.find('.panel-body, .panel, .featured-plugin, .btn-lg').removeClass('panel-body panel featured-plugin btn-lg')
if (matches.length === 0) {
$results.append(gettext('No results'))
}
}
$('#plugin_search_input').on('input', search)
$('input[name=plugin_state_filter]').on('change', search)
$results_box.find('button.close').on('click', function () {
$('input[name=plugin_state_filter][value=all]').prop('checked', true).trigger('click')
$('#plugin_search_input').val('').trigger('input')
})
if (location.search) {
var search = new URLSearchParams(location.search)
if (search.has('q')) {
$('#plugin_search_input').val(search.get('q')).trigger('input')
}
}
})
+137 -137
View File
@@ -1,156 +1,156 @@
/*global $, Morris, gettext*/
/* global Morris, gettext, apiGET, i18nToString */
$(function () {
// Question view
if (!$("#question_chart").length) {
return;
}
// Question view
if (!$('#question_chart').length) {
return
}
$(".chart").css("height", "250px");
var data_type = $("#question_chart").attr("data-type"),
data = JSON.parse($("#question-chart-data").text() || "[]"),
others_sum = 0,
max_num = 8;
$('.chart').css('height', '250px')
let data_type = $('#question_chart').attr('data-type'),
data = JSON.parse($('#question-chart-data').text() || '[]'),
others_sum = 0,
max_num = 8
data = data.map(function (d) {
return {
'value': d.count,
'label': d.answer.length > 20 ? d.answer.substring(0, 20) + '…' : d.answer,
}
});
data = data.map(function (d) {
return {
value: d.count,
label: d.answer.length > 20 ? d.answer.substring(0, 20) + '…' : d.answer,
}
})
if (data_type == 'N') {
// Sort
data.sort(function (a, b) {
if (parseFloat(a.label) > parseFloat(b.label)) {
return 1;
} else if (parseFloat(a.label) < parseFloat(b.label)) {
return -1;
} else {
return 0;
}
});
max_num = 20;
}
if (data_type == 'N') {
// Sort
data.sort(function (a, b) {
if (parseFloat(a.label) > parseFloat(b.label)) {
return 1
} else if (parseFloat(a.label) < parseFloat(b.label)) {
return -1
} else {
return 0
}
})
max_num = 20
}
// Limit shown options
if (data.length > max_num) {
for (var i = max_num; i < data.length; i++) {
others_sum += data[i].value;
}
data = data.slice(0, max_num);
data.push({'value': others_sum, 'label': gettext('Others')});
}
// Limit shown options
if (data.length > max_num) {
for (let i = max_num; i < data.length; i++) {
others_sum += data[i].value
}
data = data.slice(0, max_num)
data.push({ value: others_sum, label: gettext('Others') })
}
if (data_type === 'B') {
var colors;
if (data[0].answer_bool) {
colors = ['#50A167', '#C44F4F'];
} else {
colors = ['#C44F4F', '#50A167'];
}
new Morris.Donut({
element: 'question_chart',
data: data,
resize: true,
colors: colors
});
} else if (data_type === 'C') {
new Morris.Donut({
element: 'question_chart',
data: data,
resize: true,
colors: [
'#7F4A91',
'#50A167',
'#FFB419',
'#5F9CD4',
'#C44F4F',
'#83FFFA',
'#FF6C38',
'#1f5b8e',
'#2d683c',
]
});
} else { // M, N, S, T
new Morris.Bar({
element: 'question_chart',
data: data,
resize: true,
xkey: 'label',
ykeys: ['value'],
labels: [gettext('Count')]
});
}
if (data_type === 'B') {
let colors
if (data[0].answer_bool) {
colors = ['#50A167', '#C44F4F']
} else {
colors = ['#C44F4F', '#50A167']
}
new Morris.Donut({
element: 'question_chart',
data: data,
resize: true,
colors: colors
})
} else if (data_type === 'C') {
new Morris.Donut({
element: 'question_chart',
data: data,
resize: true,
colors: [
'#7F4A91',
'#50A167',
'#FFB419',
'#5F9CD4',
'#C44F4F',
'#83FFFA',
'#FF6C38',
'#1f5b8e',
'#2d683c',
]
})
} else { // M, N, S, T
new Morris.Bar({
element: 'question_chart',
data: data,
resize: true,
xkey: 'label',
ykeys: ['value'],
labels: [gettext('Count')]
})
}
// N, S, T
});
// N, S, T
})
$(function () {
// Question editor
// Question editor
if (!$("#answer-options").length) {
return;
}
if (!$('#answer-options').length) {
return
}
// Question editor
$("#id_type").change(question_page_toggle_view);
$("#id_required").change(question_page_toggle_view);
question_page_toggle_view();
// Question editor
$('#id_type').change(question_page_toggle_view)
$('#id_required').change(question_page_toggle_view)
question_page_toggle_view()
function question_page_toggle_view() {
var show = $("#id_type").val() == "C" || $("#id_type").val() == "M";
$("#answer-options").toggle(show);
function question_page_toggle_view () {
let show = $('#id_type').val() == 'C' || $('#id_type').val() == 'M'
$('#answer-options').toggle(show)
$("#valid-date").toggle($("#id_type").val() == "D");
$("#valid-datetime").toggle($("#id_type").val() == "W");
$("#valid-string").toggle($("#id_type").val() == "T" || $("#id_type").val() == "S");
$("#valid-number").toggle($("#id_type").val() == "N");
$("#valid-file").toggle($("#id_type").val() == "F");
$('#valid-date').toggle($('#id_type').val() == 'D')
$('#valid-datetime').toggle($('#id_type').val() == 'W')
$('#valid-string').toggle($('#id_type').val() == 'T' || $('#id_type').val() == 'S')
$('#valid-number').toggle($('#id_type').val() == 'N')
$('#valid-file').toggle($('#id_type').val() == 'F')
show = $("#id_type").val() == "B" && $("#id_required").prop("checked");
$(".alert-required-boolean").toggle(show);
}
show = $('#id_type').val() == 'B' && $('#id_required').prop('checked')
$('.alert-required-boolean').toggle(show)
}
var $val = $("#id_dependency_values");
var $dq = $("#id_dependency_question");
var oldval = JSON.parse($("#dependency_value_val").text());
function update_dependency_options() {
$val.parent().find(".loading-indicator").remove();
$("#id_dependency_values option").remove();
$("#id_dependency_values").prop("required", false);
let $val = $('#id_dependency_values')
let $dq = $('#id_dependency_question')
let oldval = JSON.parse($('#dependency_value_val').text())
function update_dependency_options () {
$val.parent().find('.loading-indicator').remove()
$('#id_dependency_values option').remove()
$('#id_dependency_values').prop('required', false)
var val = $dq.children("option:selected").val();
if (!val) {
$("#id_dependency_values").show();
$val.show();
return;
}
let val = $dq.children('option:selected').val()
if (!val) {
$('#id_dependency_values').show()
$val.show()
return
}
$("#id_dependency_values").prop("required", true);
$val.hide();
$val.parent().append("<div class=\"help-block loading-indicator\"><span class=\"fa" +
" fa-cog fa-spin\"></span></div>");
$('#id_dependency_values').prop('required', true)
$val.hide()
$val.parent().append('<div class="help-block loading-indicator"><span class="fa'
+ ' fa-cog fa-spin"></span></div>')
// the container_type parameter is undocumented. this API is going to change in a later release.
apiGET('/api/v1/organizers/' + $("body").attr("data-organizer") + '/events/' + $("body").attr("data-event") + '/questions/' + val + '/?container_type=' + encodeURIComponent($dq.data('container-type')), function (data) {
if (data.type === "B") {
$val.append($("<option>").attr("value", "True").text(gettext("Yes")));
$val.append($("<option>").attr("value", "False").text(gettext("No")));
} else {
for (var i = 0; i < data.options.length; i++) {
var opt = data.options[i];
var $opt = $("<option>").attr("value", opt.identifier).text(i18nToString(opt.answer));
$val.append($opt);
}
}
if (oldval) {
$val.val(oldval);
}
$val.parent().find(".loading-indicator").remove();
$val.show();
});
}
// the container_type parameter is undocumented. this API is going to change in a later release.
apiGET('/api/v1/organizers/' + $('body').attr('data-organizer') + '/events/' + $('body').attr('data-event') + '/questions/' + val + '/?container_type=' + encodeURIComponent($dq.data('container-type')), function (data) {
if (data.type === 'B') {
$val.append($('<option>').attr('value', 'True').text(gettext('Yes')))
$val.append($('<option>').attr('value', 'False').text(gettext('No')))
} else {
for (let i = 0; i < data.options.length; i++) {
let opt = data.options[i]
let $opt = $('<option>').attr('value', opt.identifier).text(i18nToString(opt.answer))
$val.append($opt)
}
}
if (oldval) {
$val.val(oldval)
}
$val.parent().find('.loading-indicator').remove()
$val.show()
})
}
update_dependency_options();
$dq.change(update_dependency_options);
});
update_dependency_options()
$dq.change(update_dependency_options)
})
@@ -1,50 +1,50 @@
$(function () {
"use strict";
'use strict'
var ticket_type_quota_calculation = function () {
var sum = 0;
$("#ticket-type-formset div[data-formset-form]").each(function () {
if (!$(this).find("input[name$=DELETE]").prop("checked")) {
var val = $(this).find("input[name$=quota]").val();
if (val === "") {
sum = "∞";
} else if (sum !== "∞") {
sum += parseInt(val);
}
}
});
$("#total-capacity").text(sum);
};
let ticket_type_quota_calculation = function () {
let sum = 0
$('#ticket-type-formset div[data-formset-form]').each(function () {
if (!$(this).find('input[name$=DELETE]').prop('checked')) {
let val = $(this).find('input[name$=quota]').val()
if (val === '') {
sum = '∞'
} else if (sum !== '∞') {
sum += parseInt(val)
}
}
})
$('#total-capacity').text(sum)
}
var toggle_payment = function () {
var any = false;
$("#ticket-type-formset div[data-formset-form]").each(function () {
if (!$(this).find("input[name$=DELETE]").prop("checked")) {
var val = $(this).find("input[name$=default_price]").val();
if (/.*[1-9].*/.test(val)) {
any = true;
}
}
});
if ($("#quick-setup-step-payment:visible").length && !any) {
$("#quick-setup-step-payment").stop().slideUp();
} else if (!$("#quick-setup-step-payment:visible").length && any) {
$("#quick-setup-step-payment").stop().slideDown();
}
};
let toggle_payment = function () {
let any = false
$('#ticket-type-formset div[data-formset-form]').each(function () {
if (!$(this).find('input[name$=DELETE]').prop('checked')) {
let val = $(this).find('input[name$=default_price]').val()
if (/.*[1-9].*/.test(val)) {
any = true
}
}
})
if ($('#quick-setup-step-payment:visible').length && !any) {
$('#quick-setup-step-payment').stop().slideUp()
} else if (!$('#quick-setup-step-payment:visible').length && any) {
$('#quick-setup-step-payment').stop().slideDown()
}
}
$("#ticket-type-formset").bind("formAdded", ticket_type_quota_calculation);
$("#ticket-type-formset").on("change keyup keydown keypress", "input", function () {
ticket_type_quota_calculation();
toggle_payment();
});
ticket_type_quota_calculation();
toggle_payment();
$('#ticket-type-formset').bind('formAdded', ticket_type_quota_calculation)
$('#ticket-type-formset').on('change keyup keydown keypress', 'input', function () {
ticket_type_quota_calculation()
toggle_payment()
})
ticket_type_quota_calculation()
toggle_payment()
$("#total-capacity-edit").click(function () {
$("#id_total_quota").val(parseInt($("#total-capacity").text()));
$("#total-capacity").hide();
$("#id_total_quota").closest("div").removeClass("sr-only");
$("#total-capacity-edit").hide();
});
});
$('#total-capacity-edit').click(function () {
$('#id_total_quota').val(parseInt($('#total-capacity').text()))
$('#total-capacity').hide()
$('#id_total_quota').closest('div').removeClass('sr-only')
$('#total-capacity-edit').hide()
})
})
+37 -37
View File
@@ -1,43 +1,43 @@
/*globals $, Morris, gettext*/
/* globals Morris */
$(function () {
if (!$("#quota-stats").length) {
return;
}
if (!$('#quota-stats').length) {
return
}
$(".chart").css("height", "250px");
new Morris.Donut({
element: 'quota_chart',
data: JSON.parse($("#quota-chart-data").html()),
resize: true,
colors: [
'#0044CC', // paid
'#0088CC', // pending
'#BD362F', // vouchers
'#F89406', // carts
'#51A351' // available
]
});
});
$('.chart').css('height', '250px')
new Morris.Donut({
element: 'quota_chart',
data: JSON.parse($('#quota-chart-data').html()),
resize: true,
colors: [
'#0044CC', // paid
'#0088CC', // pending
'#BD362F', // vouchers
'#F89406', // carts
'#51A351' // available
]
})
})
$(function () {
if (!$("input[name=itemvars]").length) {
return;
}
var autofill = ($("#id_name").val() === "");
if (!$('input[name=itemvars]').length) {
return
}
let autofill = ($('#id_name').val() === '')
$("#id_name").on("change keyup keydown keypress", function () {
autofill = false;
})
$('#id_name').on('change keyup keydown keypress', function () {
autofill = false
})
function do_autofill() {
if (autofill) {
var names = [];
$("input[name=itemvars]:checked").each(function () {
names.push($.trim($(this).closest("label").text()))
});
$("#id_name").val(names.join(', '));
}
}
$("input[name=itemvars]").change(do_autofill);
do_autofill();
});
function do_autofill () {
if (autofill) {
let names = []
$('input[name=itemvars]:checked').each(function () {
names.push($.trim($(this).closest('label').text()))
})
$('#id_name').val(names.join(', '))
}
}
$('input[name=itemvars]').change(do_autofill)
do_autofill()
})
+15 -17
View File
@@ -1,21 +1,19 @@
/*globals $, Morris, gettext, RRule, RRuleSet*/
function rrule_form_toggles($form) {
var freq = $form.find("select[name*=freq]").val();
$form.find(".repeat-yearly").toggle(freq === "yearly");
$form.find(".repeat-monthly").toggle(freq === "monthly");
$form.find(".repeat-weekly").toggle(freq === "weekly");
function rrule_form_toggles ($form) {
let freq = $form.find('select[name*=freq]').val()
$form.find('.repeat-yearly').toggle(freq === 'yearly')
$form.find('.repeat-monthly').toggle(freq === 'monthly')
$form.find('.repeat-weekly').toggle(freq === 'weekly')
}
function rrule_bind_form($form) {
$form.find("select[name*=freq]").change(function () {
rrule_form_toggles($form);
});
rrule_form_toggles($form);
function rrule_bind_form ($form) {
$form.find('select[name*=freq]').change(function () {
rrule_form_toggles($form)
})
rrule_form_toggles($form)
}
$(document).on("pretix:bind-forms", function () {
$(".rrule-form").each(function () {
rrule_bind_form($(this));
});
});
$(document).on('pretix:bind-forms', function () {
$('.rrule-form').each(function () {
rrule_bind_form($(this))
})
})
+203 -204
View File
@@ -1,226 +1,225 @@
/*globals $, Morris, gettext, RRule, RRuleSet*/
/* globals ngettext, rrule */
$(document).on("pretix:bind-forms", function () {
if (!$("div[data-formset-prefix=checkinlist_set]").length) {
return;
}
$(document).on('pretix:bind-forms', function () {
if (!$('div[data-formset-prefix=checkinlist_set]').length) {
return
}
function parse_weekday(wd) {
map = {
'MO': 0,
'TU': 1,
'WE': 2,
'TH': 3,
'FR': 4,
'SA': 5,
'SU': 6
}
if (wd.indexOf(",") > 0) {
var wds = [];
$.each(wd.split(","), function (k, v) {
wds.push(map[v]);
});
return wds;
} else {
return map[wd];
}
}
function parse_weekday (wd) {
map = {
MO: 0,
TU: 1,
WE: 2,
TH: 3,
FR: 4,
SA: 5,
SU: 6
}
if (wd.indexOf(',') > 0) {
let wds = []
$.each(wd.split(','), function (k, v) {
wds.push(map[v])
})
return wds
} else {
return map[wd]
}
}
// RRule editor
function rrule_preview() {
var ruleset = new rrule.RRuleSet();
// RRule editor
function rrule_preview () {
let ruleset = new rrule.RRuleSet()
$(".rrule-form").each(function () {
if ($(this).find("input[name$=DELETE]").prop("checked")) {
return;
}
$('.rrule-form').each(function () {
if ($(this).find('input[name$=DELETE]').prop('checked')) {
return
}
var rule_args = {};
var $form = $(this);
var freq = $form.find("select[name*=freq]").val();
if (!$form.find("input[name*=dtstart]").data("DateTimePicker")) {
// uninitialized
return;
}
var dtstart = $form.find("input[name*=dtstart]").data("DateTimePicker").date();
dtstart = dtstart.add(dtstart.utcOffset(), 'm').add(12, 'h').utcOffset(0);
rule_args.dtstart = dtstart.toDate();
rule_args.interval = parseInt($form.find("input[name*=interval]").val()) || 1;
let rule_args = {}
let $form = $(this)
let freq = $form.find('select[name*=freq]').val()
if (!$form.find('input[name*=dtstart]').data('DateTimePicker')) {
// uninitialized
return
}
let dtstart = $form.find('input[name*=dtstart]').data('DateTimePicker').date()
dtstart = dtstart.add(dtstart.utcOffset(), 'm').add(12, 'h').utcOffset(0)
rule_args.dtstart = dtstart.toDate()
rule_args.interval = parseInt($form.find('input[name*=interval]').val()) || 1
if (freq === 'yearly') {
rule_args.freq = rrule.RRule.YEARLY;
if (freq === 'yearly') {
rule_args.freq = rrule.RRule.YEARLY
var same = $form.find("input[name*=yearly_same]:checked").val();
if (same === "off") {
rule_args.bysetpos = parseInt($form.find("select[name*=yearly_bysetpos]").val());
rule_args.byweekday = parse_weekday($form.find("select[name*=yearly_byweekday]").val());
rule_args.bymonth = parseInt($form.find("select[name*=yearly_bymonth]").val());
}
} else if (freq === 'monthly') {
rule_args.freq = rrule.RRule.MONTHLY;
var same = $form.find('input[name*=yearly_same]:checked').val()
if (same === 'off') {
rule_args.bysetpos = parseInt($form.find('select[name*=yearly_bysetpos]').val())
rule_args.byweekday = parse_weekday($form.find('select[name*=yearly_byweekday]').val())
rule_args.bymonth = parseInt($form.find('select[name*=yearly_bymonth]').val())
}
} else if (freq === 'monthly') {
rule_args.freq = rrule.RRule.MONTHLY
var same = $form.find("input[name*=monthly_same]:checked").val();
if (same === "off") {
rule_args.bysetpos = parseInt($form.find("select[name*=monthly_bysetpos]").val());
rule_args.byweekday = parse_weekday($form.find("select[name*=monthly_byweekday]").val());
}
} else if (freq === 'weekly') {
rule_args.freq = rrule.RRule.WEEKLY;
var same = $form.find('input[name*=monthly_same]:checked').val()
if (same === 'off') {
rule_args.bysetpos = parseInt($form.find('select[name*=monthly_bysetpos]').val())
rule_args.byweekday = parse_weekday($form.find('select[name*=monthly_byweekday]').val())
}
} else if (freq === 'weekly') {
rule_args.freq = rrule.RRule.WEEKLY
var days = [];
$form.find("input[name*=weekly_byweekday]:checked").each(function () {
days.push(parse_weekday($(this).val()));
});
if (days.length !== 0) {
rule_args.byweekday = days;
}
} else if (freq === 'daily') {
rule_args.freq = rrule.RRule.DAILY;
}
let days = []
$form.find('input[name*=weekly_byweekday]:checked').each(function () {
days.push(parse_weekday($(this).val()))
})
if (days.length !== 0) {
rule_args.byweekday = days
}
} else if (freq === 'daily') {
rule_args.freq = rrule.RRule.DAILY
}
var end = $form.find("input[name*=end]:checked").val();
if (end === "count") {
rule_args.count = Math.max(parseInt($form.find("input[name*=count]").val()) || 1, 1);
} else {
var date = $form.find("input[name*=until]").data("DateTimePicker").date();
if (date !== null) {
// rrule.until is non-inclusive, whereas in pretix-backend "until" is inclusive => add 1 day
// date is a Moment-object. Moment.add() mutates, but is save to do here
date.add(1, 'days');
rule_args.until = date;
}
}
let end = $form.find('input[name*=end]:checked').val()
if (end === 'count') {
rule_args.count = Math.max(parseInt($form.find('input[name*=count]').val()) || 1, 1)
} else {
let date = $form.find('input[name*=until]').data('DateTimePicker').date()
if (date !== null) {
// rrule.until is non-inclusive, whereas in pretix-backend "until" is inclusive => add 1 day
// date is a Moment-object. Moment.add() mutates, but is save to do here
date.add(1, 'days')
rule_args.until = date
}
}
if ($form.find("input[name*=exclude]").prop("checked")) {
ruleset.exrule(new rrule.RRule(rule_args));
$form.closest(".panel").addClass("panel-danger").removeClass("panel-default");
} else {
ruleset.rrule(new rrule.RRule(rule_args));
$form.closest(".panel").addClass("panel-default").removeClass("panel-danger");
}
});
if ($form.find('input[name*=exclude]').prop('checked')) {
ruleset.exrule(new rrule.RRule(rule_args))
$form.closest('.panel').addClass('panel-danger').removeClass('panel-default')
} else {
ruleset.rrule(new rrule.RRule(rule_args))
$form.closest('.panel').addClass('panel-default').removeClass('panel-danger')
}
})
var all_dates = ruleset.all();
var format = $("body").attr("data-longdateformat") + " (dddd)";
$("#rrule-preview").html("");
if (all_dates.length > 20) {
$("#rrule-preview").html("");
all_dates.slice(0, 10).forEach(function(element) {
$("#rrule-preview").append($("<li>").text(moment(element).utc().format(format)));
});
$("#rrule-preview").append($("<li>").text(ngettext(
"(one more date)",
"({num} more dates)",
all_dates.length - 20
).replace(/\{num\}/g, all_dates.length - 20)));
all_dates.slice(-10).forEach(function(element) {
$("#rrule-preview").append($("<li>").text(moment(element).utc().format(format)));
});
} else {
all_dates.forEach(function(element) {
$("#rrule-preview").append($("<li>").text(moment(element).utc().format(format)));
});
}
}
$("#rrule-formset").on("change keydown keyup keypress dp.change", "input, select", function () {
rrule_preview();
});
rrule_preview();
let all_dates = ruleset.all()
let format = $('body').attr('data-longdateformat') + ' (dddd)'
$('#rrule-preview').html('')
if (all_dates.length > 20) {
$('#rrule-preview').html('')
all_dates.slice(0, 10).forEach(function (element) {
$('#rrule-preview').append($('<li>').text(moment(element).utc().format(format)))
})
$('#rrule-preview').append($('<li>').text(ngettext(
'(one more date)',
'({num} more dates)',
all_dates.length - 20
).replace(/\{num\}/g, all_dates.length - 20)))
all_dates.slice(-10).forEach(function (element) {
$('#rrule-preview').append($('<li>').text(moment(element).utc().format(format)))
})
} else {
all_dates.forEach(function (element) {
$('#rrule-preview').append($('<li>').text(moment(element).utc().format(format)))
})
}
}
$('#rrule-formset').on('change keydown keyup keypress dp.change', 'input, select', function () {
rrule_preview()
})
rrule_preview()
$("#rrule-formset").on("formAdded", "div", function (event) {rrule_bind_form($(event.target)); });
$('#rrule-formset').on('formAdded', 'div', function (event) { rrule_bind_form($(event.target)) })
// Timeslot editor
$("#subevent_add_many_slots_go").on("click", function () {
$("#time-formset [data-formset-form]").each(function () {
var tf = $(this).find("[name$=time_from]").val()
if (!tf) {
$(this).remove();
}
})
// Timeslot editor
$('#subevent_add_many_slots_go').on('click', function () {
$('#time-formset [data-formset-form]').each(function () {
let tf = $(this).find('[name$=time_from]').val()
if (!tf) {
$(this).remove()
}
})
var first = $("#subevent_add_many_slots_first").data('DateTimePicker').date();
var end = $("#subevent_add_many_slots_end").data('DateTimePicker').date();
var length_m = parseFloat($("#subevent_add_many_slots_length").val()) || 0;
var break_m = parseFloat($("#subevent_add_many_slots_break").val()) || 0;
if (!first || !end || !length_m) {
console.log("invalid", first, end, length_m)
return
}
let first = $('#subevent_add_many_slots_first').data('DateTimePicker').date()
let end = $('#subevent_add_many_slots_end').data('DateTimePicker').date()
let length_m = parseFloat($('#subevent_add_many_slots_length').val()) || 0
let break_m = parseFloat($('#subevent_add_many_slots_break').val()) || 0
if (!first || !end || !length_m) {
console.log('invalid', first, end, length_m)
return
}
function closure($form, time) {
return function () {
console.log("setting value", time)
$form.find("[name$=time_from]").data('DateTimePicker').date(time);
time.add(length_m, 'minutes');
$form.find("[name$=time_to]").data('DateTimePicker').date(time);
}
}
function closure ($form, time) {
return function () {
console.log('setting value', time)
$form.find('[name$=time_from]').data('DateTimePicker').date(time)
time.add(length_m, 'minutes')
$form.find('[name$=time_to]').data('DateTimePicker').date(time)
}
}
var pointer = first.clone();
while (pointer.isBefore(end)) {
var $form = $("#time-formset").formset("getOrCreate").addForm();
$form.attr("data-formset-created-at-runtime", "false"); // prevents animation
var time = pointer.clone();
window.setTimeout(closure($form, time), 1);
// jquery.formset.js only calls trigger("formAdded") after a setTimeout of 0,
// but we need to run after that to make sure the date pickers are initialized
pointer.add(break_m + length_m, 'minutes');
}
$("#subevent_add_many_slots").addClass("hidden");
$("#subevent_add_many_slots_start").removeClass("hidden");
let pointer = first.clone()
while (pointer.isBefore(end)) {
let $form = $('#time-formset').formset('getOrCreate').addForm()
$form.attr('data-formset-created-at-runtime', 'false') // prevents animation
let time = pointer.clone()
window.setTimeout(closure($form, time), 1)
// jquery.formset.js only calls trigger("formAdded") after a setTimeout of 0,
// but we need to run after that to make sure the date pickers are initialized
pointer.add(break_m + length_m, 'minutes')
}
$('#subevent_add_many_slots').addClass('hidden')
$('#subevent_add_many_slots_start').removeClass('hidden')
})
$('#subevent_add_many_slots_start').on('click', function () {
$('#subevent_add_many_slots').removeClass('hidden')
$(this).addClass('hidden')
})
});
$("#subevent_add_many_slots_start").on("click", function () {
$("#subevent_add_many_slots").removeClass("hidden");
$(this).addClass("hidden");
});
// Hide config for products that are not for sale
function quota_form_handlers (el) {
// searchable_selection = True
el.find('[id^="id_quotas-"]').on('select2:select select2:unselect', () => {
update_item_visibility()
})
// searchable_selection = False
el.find('input[id^="id_quotas-"][id*=itemvars_]').on('change', () => {
update_item_visibility()
})
}
function update_item_visibility () {
const itemvars = []
// Hide config for products that are not for sale
function quota_form_handlers(el) {
// searchable_selection = True
el.find('[id^="id_quotas-"]').on("select2:select select2:unselect", () => {
update_item_visibility();
});
// searchable_selection = False
el.find('input[id^="id_quotas-"][id*=itemvars_]').on("change", () => {
update_item_visibility();
});
}
function update_item_visibility() {
const itemvars = [];
// searchable_selection = True
$('select[id^=id_quotas-][id$=-itemvars]').filter((idx, el) => {
return !$(el).closest('[data-formset-form]').is('[data-formset-form-deleted]')
}).each((_, e) => itemvars.push(...$(e).val()))
// searchable_selection = False
$('input[id^=id_quotas-][id*=itemvars_]:checked').filter((idx, el) => {
return !$(el).closest('[data-formset-form]').is('[data-formset-form-deleted]')
}).each((_, e) => itemvars.push($(e).val()))
// searchable_selection = True
$("select[id^=id_quotas-][id$=-itemvars]").filter((idx, el) => {
return !$(el).closest('[data-formset-form]').is('[data-formset-form-deleted]');
}).each((_, e) => itemvars.push(...$(e).val()));
// searchable_selection = False
$("input[id^=id_quotas-][id*=itemvars_]:checked").filter((idx, el) => {
return !$(el).closest('[data-formset-form]').is('[data-formset-form-deleted]');
}).each((_, e) => itemvars.push($(e).val()));
$('div[data-itemvar]').each(function (idx, e) {
const el = $(e)
el.prop('hidden', !itemvars.includes(el.attr('data-itemvar')) && !el.find('.has-error, .alert-danger').length)
})
}
$("div[data-itemvar]").each(function (idx, e) {
const el = $(e);
el.prop("hidden", !itemvars.includes(el.attr("data-itemvar")) && !el.find(".has-error, .alert-danger").length);
});
}
$('[data-formset-prefix="quotas"]').on('formDeleted', 'div', () => {
update_item_visibility()
}).on('formAdded', 'div', (event) => {
quota_form_handlers($(event.target))
update_item_visibility()
})
quota_form_handlers($('body'))
update_item_visibility()
$('[data-formset-prefix="quotas"]').on("formDeleted", "div", () => {
update_item_visibility();
}).on("formAdded", "div", (event) => {
quota_form_handlers($(event.target));
update_item_visibility();
})
quota_form_handlers($("body"));
update_item_visibility();
// Auto-set name of check-in list
var $namef = $("input[id^=id_name]").first();
var lastValue = $namef.val();
$namef.change(function () {
var field = $("div[data-formset-prefix=checkinlist_set] input[id$=name]").first();
if (field.val() === lastValue) {
lastValue = $(this).val();
field.val(lastValue);
}
});
});
// Auto-set name of check-in list
let $namef = $('input[id^=id_name]').first()
let lastValue = $namef.val()
$namef.change(function () {
let field = $('div[data-formset-prefix=checkinlist_set] input[id$=name]').first()
if (field.val() === lastValue) {
lastValue = $(this).val()
field.val(lastValue)
}
})
})
+52 -54
View File
@@ -1,56 +1,54 @@
/*globals $*/
$(function () {
var j = 0;
$(".tabbed-form").each(function () {
var $form = $(this);
var $tabs = $("<ul>").addClass("nav nav-tabs").insertBefore($form);
$form.addClass("tab-content");
let j = 0
$('.tabbed-form').each(function () {
let $form = $(this)
let $tabs = $('<ul>').addClass('nav nav-tabs').insertBefore($form)
$form.addClass('tab-content')
var i = 0;
var preselect = null;
var validity_error = false;
$form.find("fieldset").each(function () {
var $fieldset = $(this);
var tid = $fieldset.attr("id");
if (!tid) tid = "tab-" + j + "-" + i;
var $tabli = $("<li>").appendTo($tabs);
var $tablink = $("<a>").attr("role", "tab")
.attr("data-toggle", "tab")
.attr("href", "#" + tid)
.text($fieldset.find("legend").text())
.appendTo($tabli);
if ($fieldset.find(".has-error, .alert-danger:not(.dynamic)").length > 0) {
$tablink.append(" ");
$tablink.append($("<span>").addClass("fa fa-warning text-danger"));
if (preselect === null) {
preselect = i;
}
}
$fieldset.find("input, select, textarea").on("invalid", function () {
if ($tablink.find(".fa-warning").length === 0) {
$tablink.append(" ");
$tablink.append($("<span>").addClass("fa fa-warning text-danger"));
if (!validity_error) {
validity_error = true;
$tablink.click();
}
}
});
$fieldset.find("legend").remove();
$fieldset.addClass("tab-pane").attr("id", tid);
if (location.hash && ($fieldset.find(location.hash).length || location.hash === "#" + tid + "-open") && preselect === null) {
preselect = i;
}
i++;
});
$tabs.find("a").get(preselect != null ? preselect : 0).click();
$tabs.find("a").on('shown.bs.tab', function (e) {
history.replaceState(null, null, e.target.getAttribute("href") + "-open");
});
$form.closest("form").on("submit", function () {
validity_error = false;
});
j++;
});
});
let i = 0
let preselect = null
let validity_error = false
$form.find('fieldset').each(function () {
let $fieldset = $(this)
let tid = $fieldset.attr('id')
if (!tid) tid = 'tab-' + j + '-' + i
let $tabli = $('<li>').appendTo($tabs)
let $tablink = $('<a>').attr('role', 'tab')
.attr('data-toggle', 'tab')
.attr('href', '#' + tid)
.text($fieldset.find('legend').text())
.appendTo($tabli)
if ($fieldset.find('.has-error, .alert-danger:not(.dynamic)').length > 0) {
$tablink.append(' ')
$tablink.append($('<span>').addClass('fa fa-warning text-danger'))
if (preselect === null) {
preselect = i
}
}
$fieldset.find('input, select, textarea').on('invalid', function () {
if ($tablink.find('.fa-warning').length === 0) {
$tablink.append(' ')
$tablink.append($('<span>').addClass('fa fa-warning text-danger'))
if (!validity_error) {
validity_error = true
$tablink.click()
}
}
})
$fieldset.find('legend').remove()
$fieldset.addClass('tab-pane').attr('id', tid)
if (location.hash && ($fieldset.find(location.hash).length || location.hash === '#' + tid + '-open') && preselect === null) {
preselect = i
}
i++
})
$tabs.find('a').get(preselect != null ? preselect : 0).click()
$tabs.find('a').on('shown.bs.tab', function (e) {
history.replaceState(null, null, e.target.getAttribute('href') + '-open')
})
$form.closest('form').on('submit', function () {
validity_error = false
})
j++
})
})
+157 -158
View File
@@ -1,164 +1,163 @@
/*global $,u2f */
$(function () {
$('.context-selector.dropdown').on('shown.bs.collapse shown.bs.dropdown', function () {
$(this).parent().find("input").val("").trigger('forceRunQuery').focus();
});
$('.dropdown-menu .form-box input').click(function (e) {
e.stopPropagation();
});
$('.context-selector.dropdown').on('shown.bs.collapse shown.bs.dropdown', function () {
$(this).parent().find('input').val('').trigger('forceRunQuery').focus()
})
$('.dropdown-menu .form-box input').click(function (e) {
e.stopPropagation()
})
$("[data-event-typeahead]").each(function () {
var $container = $(this);
var $query = $(this).find('[data-typeahead-query]').length ? $(this).find('[data-typeahead-query]') : $($(this).attr("data-typeahead-field"));
$container.find("li:not(.query-holder)").remove();
var lastQuery = null;
var runQueryTimeout = null;
var loadIndicatorTimeout = null;
var focusOutTimeout = null;
function showLoadIndicator() {
$container.find("li:not(.query-holder)").remove();
$container.append("<li class='loading'><span class='fa fa-4x fa-cog fa-spin'></span></li>");
$container.toggleClass('focused', $query.is(":focus") && $container.children().length > 0);
}
function runQuery() {
var thisQuery = $query.val();
if (thisQuery === lastQuery) return;
lastQuery = $query.val();
$('[data-event-typeahead]').each(function () {
let $container = $(this)
let $query = $(this).find('[data-typeahead-query]').length ? $(this).find('[data-typeahead-query]') : $($(this).attr('data-typeahead-field'))
$container.find('li:not(.query-holder)').remove()
let lastQuery = null
let runQueryTimeout = null
let loadIndicatorTimeout = null
let focusOutTimeout = null
function showLoadIndicator () {
$container.find('li:not(.query-holder)').remove()
$container.append('<li class=\'loading\'><span class=\'fa fa-4x fa-cog fa-spin\'></span></li>')
$container.toggleClass('focused', $query.is(':focus') && $container.children().length > 0)
}
function runQuery () {
let thisQuery = $query.val()
if (thisQuery === lastQuery) return
lastQuery = $query.val()
window.clearTimeout(loadIndicatorTimeout)
loadIndicatorTimeout = window.setTimeout(showLoadIndicator, 80)
window.clearTimeout(loadIndicatorTimeout)
loadIndicatorTimeout = window.setTimeout(showLoadIndicator, 80)
$.getJSON(
$container.attr("data-source") + "?query=" + encodeURIComponent($query.val()) + (typeof $container.attr("data-organizer") !== "undefined" ? "&organizer=" + $container.attr("data-organizer") : ""),
function (data) {
if (thisQuery !== lastQuery) {
// Lost race condition
return;
}
window.clearTimeout(loadIndicatorTimeout);
$container.find("li:not(.query-holder)").remove();
$.each(data.results, function (i, res) {
let $linkContent = $("<div>");
if (res.type === "organizer") {
$linkContent.append(
$("<span>").addClass("event-name-full").append(
$("<span>").addClass("fa fa-users fa-fw")
).append(" ").append($("<div>").text(res.name).html())
)
} else if (res.type === "order" || res.type === "voucher") {
$linkContent.append(
$("<span>").addClass("event-name-full").append($("<div>").text(res.title).html())
).append(
$("<span>").addClass("event-organizer").append(
$("<span>").addClass("fa fa-calendar fa-fw")
).append(" ").append($("<div>").text(res.event).html())
)
} else if (res.type === "user") {
$linkContent.append(
$("<span>").addClass("event-name-full").append(
$("<span>").addClass("fa fa-user fa-fw")
).append(" ").append($("<div>").text(res.name).html())
)
} else {
$linkContent.append(
$("<span>").addClass("event-name-full").append($("<div>").text(res.name).html())
).append(
$("<span>").addClass("event-organizer").append(
$("<span>").addClass("fa fa-users fa-fw")
).append(" ").append($("<div>").text(res.organizer).html())
).append(
$("<span>").addClass("event-daterange").append(
$("<span>").addClass("fa fa-calendar fa-fw")
).append(" ").append(res.date_range)
)
}
$.getJSON(
$container.attr('data-source') + '?query=' + encodeURIComponent($query.val()) + (typeof $container.attr('data-organizer') !== 'undefined' ? '&organizer=' + $container.attr('data-organizer') : ''),
function (data) {
if (thisQuery !== lastQuery) {
// Lost race condition
return
}
window.clearTimeout(loadIndicatorTimeout)
$container.find('li:not(.query-holder)').remove()
$.each(data.results, function (_i, res) {
let $linkContent = $('<div>')
if (res.type === 'organizer') {
$linkContent.append(
$('<span>').addClass('event-name-full').append(
$('<span>').addClass('fa fa-users fa-fw')
).append(' ').append($('<div>').text(res.name).html())
)
} else if (res.type === 'order' || res.type === 'voucher') {
$linkContent.append(
$('<span>').addClass('event-name-full').append($('<div>').text(res.title).html())
).append(
$('<span>').addClass('event-organizer').append(
$('<span>').addClass('fa fa-calendar fa-fw')
).append(' ').append($('<div>').text(res.event).html())
)
} else if (res.type === 'user') {
$linkContent.append(
$('<span>').addClass('event-name-full').append(
$('<span>').addClass('fa fa-user fa-fw')
).append(' ').append($('<div>').text(res.name).html())
)
} else {
$linkContent.append(
$('<span>').addClass('event-name-full').append($('<div>').text(res.name).html())
).append(
$('<span>').addClass('event-organizer').append(
$('<span>').addClass('fa fa-users fa-fw')
).append(' ').append($('<div>').text(res.organizer).html())
).append(
$('<span>').addClass('event-daterange').append(
$('<span>').addClass('fa fa-calendar fa-fw')
).append(' ').append(res.date_range)
)
}
$container.append(
$("<li>").append(
$("<a>").attr("href", res.url).append(
$linkContent
)
)
);
});
$container.toggleClass('focused', $query.is(":focus") && $container.children().length > 0);
}
);
}
$query.on("forceRunQuery", function () {
runQuery();
});
$query.on("input", function () {
if ($container.attr("data-typeahead-field") && $query.val() === "") {
$container.removeClass('focused');
$container.find("li:not(.query-holder)").remove();
lastQuery = null;
return;
}
window.clearTimeout(runQueryTimeout)
runQueryTimeout = window.setTimeout(runQuery, 250)
});
$query.on("keydown", function (event) {
var $selected = $container.find(".active");
if (event.which === 13) { // enter
var $link = $selected.find("a");
if ($link.length) {
location.href = $link.attr("href");
}
event.preventDefault();
event.stopPropagation();
}
});
$container.add($query).on("keydown", function (event) {
if (event.which === 27) { // escape
$container.removeClass('focused');
}
}).on("focusin", function (event) {
window.clearTimeout(focusOutTimeout);
$(document.body).one("focusout", function (event) {
focusOutTimeout = window.setTimeout(function () {
$container.removeClass('focused');
}, 100);
})
});
$query.on("keyup", function (event) {
var $first = $container.find("li:not(.query-holder)").first();
var $last = $container.find("li:not(.query-holder)").last();
var $selected = $container.find(".active");
$container.append(
$('<li>').append(
$('<a>').attr('href', res.url).append(
$linkContent
)
)
)
})
$container.toggleClass('focused', $query.is(':focus') && $container.children().length > 0)
}
)
}
$query.on('forceRunQuery', function () {
runQuery()
})
$query.on('input', function () {
if ($container.attr('data-typeahead-field') && $query.val() === '') {
$container.removeClass('focused')
$container.find('li:not(.query-holder)').remove()
lastQuery = null
return
}
window.clearTimeout(runQueryTimeout)
runQueryTimeout = window.setTimeout(runQuery, 250)
})
$query.on('keydown', function (event) {
let $selected = $container.find('.active')
if (event.which === 13) { // enter
let $link = $selected.find('a')
if ($link.length) {
location.href = $link.attr('href')
}
event.preventDefault()
event.stopPropagation()
}
})
$container.add($query).on('keydown', function (event) {
if (event.which === 27) { // escape
$container.removeClass('focused')
}
}).on('focusin', function () {
window.clearTimeout(focusOutTimeout)
$(document.body).one('focusout', function () {
focusOutTimeout = window.setTimeout(function () {
$container.removeClass('focused')
}, 100)
})
})
$query.on('keyup', function (event) {
let $first = $container.find('li:not(.query-holder)').first()
let $last = $container.find('li:not(.query-holder)').last()
let $selected = $container.find('.active')
if (event.which === 13) { // enter
event.preventDefault();
event.stopPropagation();
return true;
} else if (event.which === 40) { // down
var $next;
if ($selected.length === 0) {
$next = $first;
} else {
$next = $selected.next();
}
if ($next.length === 0) {
$next = $first;
}
$selected.removeClass("active");
$next.addClass("active");
event.preventDefault();
event.stopPropagation();
return true;
} else if (event.which === 38) { // up
if ($selected.length === 0) {
$selected = $first;
}
var $prev = $selected.prev();
if ($prev.length === 0 || $prev.find("input").length > 0) {
$prev = $last;
}
$selected.removeClass("active");
$prev.addClass("active");
event.preventDefault();
event.stopPropagation();
return true;
}
});
});
});
if (event.which === 13) { // enter
event.preventDefault()
event.stopPropagation()
return true
} else if (event.which === 40) { // down
let $next
if ($selected.length === 0) {
$next = $first
} else {
$next = $selected.next()
}
if ($next.length === 0) {
$next = $first
}
$selected.removeClass('active')
$next.addClass('active')
event.preventDefault()
event.stopPropagation()
return true
} else if (event.which === 38) { // up
if ($selected.length === 0) {
$selected = $first
}
let $prev = $selected.prev()
if ($prev.length === 0 || $prev.find('input').length > 0) {
$prev = $last
}
$selected.removeClass('active')
$prev.addClass('active')
event.preventDefault()
event.stopPropagation()
return true
}
})
})
})
@@ -1,78 +1,78 @@
/*global $, Morris, gettext, formatPrice*/
/* global i18nToString, formatPrice */
$(function () {
// Question view
if (!$("#item_variations").length) {
return;
}
// Question view
if (!$('#item_variations').length) {
return
}
function update_variation_summary($el) {
var var_names = Object.fromEntries(
$el
.find("input[name*=-value_]")
.filter(function () {
return !!this.value;
})
.map(function () {
return [[this.getAttribute("lang"), this.value]];
})
.get()
);
var var_name = i18nToString(var_names);
var price = $el.find("input[name*=-default_price]").val();
if (price) {
var currency = $el.find("[name*=-default_price] + .input-group-addon").text();
price = formatPrice(price, currency);
}
function update_variation_summary ($el) {
let var_names = Object.fromEntries(
$el
.find('input[name*=-value_]')
.filter(function () {
return !!this.value
})
.map(function () {
return [[this.getAttribute('lang'), this.value]]
})
.get()
)
let var_name = i18nToString(var_names)
let price = $el.find('input[name*=-default_price]').val()
if (price) {
let currency = $el.find('[name*=-default_price] + .input-group-addon').text()
price = formatPrice(price, currency)
}
$el.find(".variation-name").text(var_name);
$el.find(".variation-price").text(price);
$el.find(".variation-timeframe").toggleClass("variation-icon-hidden", !(
!!$el.find("input[name$=-available_from_0]").val() ||
!!$el.find("input[name$=-available_until_0]").val()
));
$el.find(".variation-name").toggleClass("variation-disabled", !(
!!$el.find("input[name$=-active]").prop("checked")
));
$el.find(".variation-voucher").toggleClass("variation-icon-hidden", !(
!!$el.find("input[name$=-hide_without_voucher]").prop("checked")
));
$el.find(".variation-membership").toggleClass("variation-icon-hidden", !(
!!$el.find("input[name$=-require_membership]").prop("checked")
));
$el.find(".variation-warning").toggleClass("hidden", !(
$el.find(".alert-warning").length
));
$el.find(".variation-error").toggleClass("hidden", !(
$el.find(".alert-danger, .has-error").length
));
$el.find("input[name$=-limit_sales_channels]").each(function () {
$el.find(".variation-channel-" + $(this).val()).toggleClass("variation-icon-hidden", !(
(
$(this).closest("[data-formset-form]").find("input[name$=-all_sales_channels]").prop("checked") ||
$(this).prop("checked")
) && (
$("input[name=all_sales_channels]").prop("checked") ||
$("input[name=limit_sales_channels][value=" + $(this).val() + "]").prop("checked")
)
));
})
}
$el.find('.variation-name').text(var_name)
$el.find('.variation-price').text(price)
$el.find('.variation-timeframe').toggleClass('variation-icon-hidden', !(
!!$el.find('input[name$=-available_from_0]').val()
|| !!$el.find('input[name$=-available_until_0]').val()
))
$el.find('.variation-name').toggleClass('variation-disabled', !(
$el.find('input[name$=-active]').prop('checked')
))
$el.find('.variation-voucher').toggleClass('variation-icon-hidden', !(
$el.find('input[name$=-hide_without_voucher]').prop('checked')
))
$el.find('.variation-membership').toggleClass('variation-icon-hidden', !(
$el.find('input[name$=-require_membership]').prop('checked')
))
$el.find('.variation-warning').toggleClass('hidden', !(
$el.find('.alert-warning').length
))
$el.find('.variation-error').toggleClass('hidden', !(
$el.find('.alert-danger, .has-error').length
))
$el.find('input[name$=-limit_sales_channels]').each(function () {
$el.find('.variation-channel-' + $(this).val()).toggleClass('variation-icon-hidden', !(
(
$(this).closest('[data-formset-form]').find('input[name$=-all_sales_channels]').prop('checked')
|| $(this).prop('checked')
) && (
$('input[name=all_sales_channels]').prop('checked')
|| $('input[name=limit_sales_channels][value=' + $(this).val() + ']').prop('checked')
)
))
})
}
$("#item_variations [data-formset-form]").each(function () {
var $el = $(this);
update_variation_summary($el);
$(this).on("change dp.change", "input", function () {update_variation_summary($el)});
});
$("input[name=limit_sales_channels] input[name=all_sales_channels]").on("change", function() {
$("#item_variations [data-formset-form]").each(function () {
update_variation_summary($(this));
});
});
$("#item_variations").on("formAdded", "details", function (event) {
var $el = $(event.target);
update_variation_summary($el);
$(this).on("change dp.change", "input", function () {update_variation_summary($el)});
setup_collapsible_details($("#item_variations"));
form_handlers($(event.target));
});
});
$('#item_variations [data-formset-form]').each(function () {
let $el = $(this)
update_variation_summary($el)
$(this).on('change dp.change', 'input', function () { update_variation_summary($el) })
})
$('input[name=limit_sales_channels] input[name=all_sales_channels]').on('change', function () {
$('#item_variations [data-formset-form]').each(function () {
update_variation_summary($(this))
})
})
$('#item_variations').on('formAdded', 'details', function (event) {
let $el = $(event.target)
update_variation_summary($el)
$(this).on('change dp.change', 'input', function () { update_variation_summary($el) })
setup_collapsible_details($('#item_variations'))
form_handlers($(event.target))
})
})
+142 -145
View File
@@ -1,32 +1,32 @@
/*global $,u2f */
/* global base64js */
function b64enc(buf) {
return base64js.fromByteArray(buf)
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
function b64enc (buf) {
return base64js.fromByteArray(buf)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '')
}
function b64RawEnc(buf) {
return base64js.fromByteArray(buf)
.replace(/\+/g, "-")
.replace(/\//g, "_");
function b64RawEnc (buf) {
return base64js.fromByteArray(buf)
.replace(/\+/g, '-')
.replace(/\//g, '_')
}
function hexEncode(buf) {
return Array.from(buf)
.map(function(x) {
return ("0" + x.toString(16)).substr(-2);
})
.join("");
function hexEncode (buf) {
return Array.from(buf)
.map(function (x) {
return ('0' + x.toString(16)).substr(-2)
})
.join('')
}
async function fetch_json(url, options) {
const response = await fetch(url, options);
const body = await response.json();
if (body.fail)
throw body.fail;
return body;
async function fetch_json (url, options) {
const response = await fetch(url, options)
const body = await response.json()
if (body.fail)
throw body.fail
return body
}
/**
@@ -35,27 +35,26 @@ async function fetch_json(url, options) {
* @param {Object} credentialCreateOptionsFromServer
*/
const transformCredentialCreateOptions = function (credentialCreateOptionsFromServer) {
let {challenge, user, excludeCredentials} = credentialCreateOptionsFromServer;
user.id = user.id.replace(/\_/g, "/").replace(/\-/g, "+");
user.id = Uint8Array.from(atob(user.id), c => c.charCodeAt(0));
let { challenge, user, excludeCredentials } = credentialCreateOptionsFromServer
user.id = user.id.replace(/_/g, '/').replace(/-/g, '+')
user.id = Uint8Array.from(atob(user.id), c => c.charCodeAt(0))
challenge = challenge.replace(/\_/g, "/").replace(/\-/g, "+");
challenge = Uint8Array.from(atob(challenge), c => c.charCodeAt(0));
challenge = challenge.replace(/_/g, '/').replace(/-/g, '+')
challenge = Uint8Array.from(atob(challenge), c => c.charCodeAt(0))
excludeCredentials = excludeCredentials.map(credentialDescriptor => {
let {id} = credentialDescriptor;
id = id.replace(/\_/g, "/").replace(/\-/g, "+");
id = Uint8Array.from(atob(id), c => c.charCodeAt(0));
return Object.assign({}, credentialDescriptor, {id});
});
excludeCredentials = excludeCredentials.map(credentialDescriptor => {
let { id } = credentialDescriptor
id = id.replace(/_/g, '/').replace(/-/g, '+')
id = Uint8Array.from(atob(id), c => c.charCodeAt(0))
return Object.assign({}, credentialDescriptor, { id })
})
const transformedCredentialCreateOptions = Object.assign(
{}, credentialCreateOptionsFromServer,
{challenge, user, excludeCredentials});
return transformedCredentialCreateOptions;
};
const transformedCredentialCreateOptions = Object.assign(
{}, credentialCreateOptionsFromServer,
{ challenge, user, excludeCredentials })
return transformedCredentialCreateOptions
}
/**
* Transforms the binary data in the credential into base64 strings
@@ -63,134 +62,132 @@ const transformCredentialCreateOptions = function (credentialCreateOptionsFromSe
* @param {PublicKeyCredential} newAssertion
*/
const transformNewAssertionForServer = (newAssertion) => {
const attObj = new Uint8Array(newAssertion.response.attestationObject);
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON);
const rawId = new Uint8Array(newAssertion.rawId);
const transports = newAssertion.response.getTransports();
const authenticatorAttachment = newAssertion.authenticatorAttachment;
const attObj = new Uint8Array(newAssertion.response.attestationObject)
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON)
const rawId = new Uint8Array(newAssertion.rawId)
const transports = newAssertion.response.getTransports()
const authenticatorAttachment = newAssertion.authenticatorAttachment
const registrationClientExtensions = newAssertion.getClientExtensionResults();
return {
id: newAssertion.id,
rawId: b64enc(rawId),
response: {
attestationObject: b64enc(attObj),
clientDataJSON: b64enc(clientDataJSON),
transports: transports,
},
type: newAssertion.type,
clientExtensionResults: JSON.stringify(registrationClientExtensions),
authenticatorAttachment: authenticatorAttachment,
};
};
const registrationClientExtensions = newAssertion.getClientExtensionResults()
return {
id: newAssertion.id,
rawId: b64enc(rawId),
response: {
attestationObject: b64enc(attObj),
clientDataJSON: b64enc(clientDataJSON),
transports: transports,
},
type: newAssertion.type,
clientExtensionResults: JSON.stringify(registrationClientExtensions),
authenticatorAttachment: authenticatorAttachment,
}
}
const transformCredentialRequestOptions = (credentialRequestOptionsFromServer) => {
let {challenge, allowCredentials} = credentialRequestOptionsFromServer;
let { challenge, allowCredentials } = credentialRequestOptionsFromServer
challenge = challenge.replace(/\_/g, "/").replace(/\-/g, "+");
challenge = Uint8Array.from(atob(challenge), c => c.charCodeAt(0));
challenge = challenge.replace(/_/g, '/').replace(/-/g, '+')
challenge = Uint8Array.from(atob(challenge), c => c.charCodeAt(0))
allowCredentials = allowCredentials.map(credentialDescriptor => {
let {id} = credentialDescriptor;
id = id.replace(/\_/g, "/").replace(/\-/g, "+");
id = Uint8Array.from(atob(id), c => c.charCodeAt(0));
return Object.assign({}, credentialDescriptor, {id});
});
allowCredentials = allowCredentials.map(credentialDescriptor => {
let { id } = credentialDescriptor
id = id.replace(/_/g, '/').replace(/-/g, '+')
id = Uint8Array.from(atob(id), c => c.charCodeAt(0))
return Object.assign({}, credentialDescriptor, { id })
})
const transformedCredentialRequestOptions = Object.assign(
{},
credentialRequestOptionsFromServer,
{challenge, allowCredentials});
const transformedCredentialRequestOptions = Object.assign(
{},
credentialRequestOptionsFromServer,
{ challenge, allowCredentials })
return transformedCredentialRequestOptions;
};
return transformedCredentialRequestOptions
}
/**
* Encodes the binary data in the assertion into strings for posting to the server.
* @param {PublicKeyCredential} newAssertion
*/
const transformAssertionForServer = (newAssertion) => {
const authData = new Uint8Array(newAssertion.response.authenticatorData);
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON);
const rawId = new Uint8Array(newAssertion.rawId);
const sig = new Uint8Array(newAssertion.response.signature);
const userHandle = new Uint8Array(newAssertion.response.userHandle);
const assertionClientExtensions = newAssertion.getClientExtensionResults();
const authenticatorAttachment = newAssertion.authenticatorAttachment;
const authData = new Uint8Array(newAssertion.response.authenticatorData)
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON)
const rawId = new Uint8Array(newAssertion.rawId)
const sig = new Uint8Array(newAssertion.response.signature)
const userHandle = new Uint8Array(newAssertion.response.userHandle)
const assertionClientExtensions = newAssertion.getClientExtensionResults()
const authenticatorAttachment = newAssertion.authenticatorAttachment
return {
id: newAssertion.id,
rawId: b64enc(rawId),
type: newAssertion.type,
response: {
authenticatorData: b64RawEnc(authData),
clientDataJSON: b64RawEnc(clientDataJSON),
signature: b64RawEnc(sig),
userHandle: b64RawEnc(userHandle),
},
authenticatorAttachment: authenticatorAttachment,
clientExtensionResults: JSON.stringify(assertionClientExtensions)
};
};
return {
id: newAssertion.id,
rawId: b64enc(rawId),
type: newAssertion.type,
response: {
authenticatorData: b64RawEnc(authData),
clientDataJSON: b64RawEnc(clientDataJSON),
signature: b64RawEnc(sig),
userHandle: b64RawEnc(userHandle),
},
authenticatorAttachment: authenticatorAttachment,
clientExtensionResults: JSON.stringify(assertionClientExtensions)
}
}
const startRegister = async (e) => {
const publicKeyCredentialCreateOptions = transformCredentialCreateOptions(JSON.parse($("#webauthn-enroll").text()));
const startRegister = async () => {
const publicKeyCredentialCreateOptions = transformCredentialCreateOptions(JSON.parse($('#webauthn-enroll').text()))
// request the authenticator(s) to create a new credential keypair.
let credential;
try {
credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreateOptions
});
} catch (err) {
$("#webauthn-error").removeClass("hidden");
return console.error("Error creating credential:", err);
}
// request the authenticator(s) to create a new credential keypair.
let credential
try {
credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreateOptions
})
} catch (err) {
$('#webauthn-error').removeClass('hidden')
return console.error('Error creating credential:', err)
}
// we now have a new credential! We now need to encode the byte arrays
// in the credential into strings, for posting to our server.
const newAssertionForServer = transformNewAssertionForServer(credential);
// we now have a new credential! We now need to encode the byte arrays
// in the credential into strings, for posting to our server.
const newAssertionForServer = transformNewAssertionForServer(credential)
$("#webauthn-response").val(JSON.stringify(newAssertionForServer));
$("#webauthn-form").submit();
};
$('#webauthn-response').val(JSON.stringify(newAssertionForServer))
$('#webauthn-form').submit()
}
const startLogin = async () => {
const transformedCredentialRequestOptions = transformCredentialRequestOptions(JSON.parse($('#webauthn-login').text()))
console.log(transformedCredentialRequestOptions)
const startLogin = async (e) => {
const transformedCredentialRequestOptions = transformCredentialRequestOptions(JSON.parse($("#webauthn-login").text()));
console.log(transformedCredentialRequestOptions);
// request the authenticator to create an assertion signature using the
// credential private key
let assertion
try {
assertion = await navigator.credentials.get({
publicKey: transformedCredentialRequestOptions,
})
} catch (err) {
$('#webauthn-error').removeClass('hidden')
return console.error('Error when creating credential:', err)
}
// request the authenticator to create an assertion signature using the
// credential private key
let assertion;
try {
assertion = await navigator.credentials.get({
publicKey: transformedCredentialRequestOptions,
});
} catch (err) {
$("#webauthn-error").removeClass("hidden");
return console.error("Error when creating credential:", err);
}
// we now have an authentication assertion! encode the byte arrays contained
// in the assertion data as strings for posting to the server
const transformedAssertionForServer = transformAssertionForServer(assertion)
// we now have an authentication assertion! encode the byte arrays contained
// in the assertion data as strings for posting to the server
const transformedAssertionForServer = transformAssertionForServer(assertion);
// post the assertion to the server for verification.
$("input, select, textarea").prop("required", false);
$("#webauthn-response, #id_password").val(JSON.stringify(transformedAssertionForServer));
$("#webauthn-form").submit();
};
// post the assertion to the server for verification.
$('input, select, textarea').prop('required', false)
$('#webauthn-response, #id_password').val(JSON.stringify(transformedAssertionForServer))
$('#webauthn-form').submit()
}
$(function () {
$("#webauthn-progress").hide();
if ($("#webauthn-enroll").length) {
$("#webauthn-progress").show();
startRegister();
} else if ($("#webauthn-login").length) {
$("#webauthn-progress").show();
startLogin();
}
});
$('#webauthn-progress').hide()
if ($('#webauthn-enroll').length) {
$('#webauthn-progress').show()
startRegister()
} else if ($('#webauthn-login').length) {
$('#webauthn-progress').show()
startLogin()
}
})
@@ -1,15 +1,15 @@
document.addEventListener("DOMContentLoaded", () => {
const COOKIE_NAME = "__Host-pretix_csrftoken";
const RELOAD_FLAG = "csrfReloadPerformed";
document.addEventListener('DOMContentLoaded', () => {
const COOKIE_NAME = '__Host-pretix_csrftoken'
const RELOAD_FLAG = 'csrfReloadPerformed'
const hasCookie = document.cookie
.split("; ")
.some((c) => c.startsWith(COOKIE_NAME + "="));
const hasCookie = document.cookie
.split('; ')
.some((c) => c.startsWith(COOKIE_NAME + '='))
if (!hasCookie && !sessionStorage.getItem(RELOAD_FLAG)) {
sessionStorage.setItem(RELOAD_FLAG, "1");
location.reload();
} else if (hasCookie && sessionStorage.getItem(RELOAD_FLAG)) {
sessionStorage.removeItem(RELOAD_FLAG);
}
});
if (!hasCookie && !sessionStorage.getItem(RELOAD_FLAG)) {
sessionStorage.setItem(RELOAD_FLAG, '1')
location.reload()
} else if (hasCookie && sessionStorage.getItem(RELOAD_FLAG)) {
sessionStorage.removeItem(RELOAD_FLAG)
}
})
@@ -1,10 +1,8 @@
/*global $ */
$(function () {
window.addEventListener("message", (event) => {
if (event.data && event.data.__process === "popup_close") {
window.close()
}
});
window.opener.postMessage(JSON.parse($("#postmessage").text()), $("#origin").text())
})
window.addEventListener('message', (event) => {
if (event.data && event.data.__process === 'popup_close') {
window.close()
}
})
window.opener.postMessage(JSON.parse($('#postmessage').text()), $('#origin').text())
})
+173 -173
View File
@@ -1,191 +1,191 @@
/*global $,gettext,ngettext */
/* global gettext,ngettext,moment,django */
var cart = {
_deadline: null,
_deadline_timeout: null,
_deadline_call: 0,
_time_offset: 0,
_prev_diff_minutes: 0,
_deadline: null,
_deadline_timeout: null,
_deadline_call: 0,
_time_offset: 0,
_prev_diff_minutes: 0,
_get_now: function () {
return moment().add(cart._time_offset, 'ms');
},
_get_now: function () {
return moment().add(cart._time_offset, 'ms')
},
_calc_offset: function () {
if (typeof window.performance === "undefined") {
return;
}
var perf = window.performance.timing;
var server_time = Math.round(parseFloat($("body").attr("data-now")) * 1000);
// We use requestStart as we don't know how latency is distributed and we rather want to err on the safe side
var client_time = perf.requestStart;
cart._time_offset = server_time - client_time;
},
_calc_offset: function () {
if (typeof window.performance === 'undefined') {
return
}
let perf = window.performance.timing
let server_time = Math.round(parseFloat($('body').attr('data-now')) * 1000)
// We use requestStart as we don't know how latency is distributed and we rather want to err on the safe side
let client_time = perf.requestStart
cart._time_offset = server_time - client_time
},
show_expiry_notification: function () {
document.getElementById("dialog-cart-extend").showModal();
cart._expiry_notified = true;
},
show_expiry_notification: function () {
document.getElementById('dialog-cart-extend').showModal()
cart._expiry_notified = true
},
draw_deadline: function () {
function pad(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
draw_deadline: function () {
function pad (n, width, z) {
z = z || '0'
n = n + ''
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n
}
cart._deadline_call++;
if ((typeof django === 'undefined' || typeof django.gettext === 'undefined') && cart._deadline_call < 5) {
// Language files are not loaded yet, don't run during the first seconds
return;
}
var now = cart._get_now();
var diff_total_seconds = cart._deadline.diff(now) / 1000;
var diff_minutes = Math.floor(diff_total_seconds / 60);
var diff_seconds = Math.floor(diff_total_seconds % 60);
cart._deadline_call++
if ((typeof django === 'undefined' || typeof django.gettext === 'undefined') && cart._deadline_call < 5) {
// Language files are not loaded yet, don't run during the first seconds
return
}
let now = cart._get_now()
let diff_total_seconds = cart._deadline.diff(now) / 1000
let diff_minutes = Math.floor(diff_total_seconds / 60)
let diff_seconds = Math.floor(diff_total_seconds % 60)
if (diff_minutes < 0) {
$("#cart-deadline").text(gettext("The items in your cart are no longer reserved for you. You can still complete your order as long as theyre available."));
$("#cart-deadline-short").text(
gettext("Cart expired")
);
if (!cart._deadline_timeout) {
// no timeout => first time draw_deadline is invoked, but cart already expired => do not show dialog
cart._expiry_notified = true;
}
} else {
if (diff_minutes !== cart._prev_diff_minutes) {
if (diff_minutes == 0) {
$("#cart-deadline").text(gettext("Your cart is about to expire."))
} else {
$("#cart-deadline").text(
ngettext(
"The items in your cart are reserved for you for one minute.",
"The items in your cart are reserved for you for {num} minutes.",
diff_minutes
).replace(/\{num\}/g, diff_minutes)
);
}
cart._prev_diff_minutes = diff_minutes;
}
if (diff_minutes < 0) {
$('#cart-deadline').text(gettext('The items in your cart are no longer reserved for you. You can still complete your order as long as theyre available.'))
$('#cart-deadline-short').text(
gettext('Cart expired')
)
if (!cart._deadline_timeout) {
// no timeout => first time draw_deadline is invoked, but cart already expired => do not show dialog
cart._expiry_notified = true
}
} else {
if (diff_minutes !== cart._prev_diff_minutes) {
if (diff_minutes == 0) {
$('#cart-deadline').text(gettext('Your cart is about to expire.'))
} else {
$('#cart-deadline').text(
ngettext(
'The items in your cart are reserved for you for one minute.',
'The items in your cart are reserved for you for {num} minutes.',
diff_minutes
).replace(/\{num\}/g, diff_minutes)
)
}
cart._prev_diff_minutes = diff_minutes
}
$("#cart-deadline-short").text(
pad(diff_minutes.toString(), 2) + ':' + pad(diff_seconds.toString(), 2)
);
$('#cart-deadline-short').text(
pad(diff_minutes.toString(), 2) + ':' + pad(diff_seconds.toString(), 2)
)
cart._deadline_timeout = window.setTimeout(cart.draw_deadline, 500);
}
var already_expired = diff_total_seconds <= 0;
var can_extend_cart = diff_minutes < 3 && (already_expired || cart._deadline < cart._max_extend);
$("#cart-extend-button").toggle(can_extend_cart);
if (can_extend_cart && diff_total_seconds < 45) {
if (!cart._expiry_notified) cart.show_expiry_notification();
$("#dialog-cart-extend-title").text(already_expired
? gettext("Your cart has expired.")
: gettext("Your cart is about to expire."));
$("#dialog-cart-extend-description").text(already_expired
? gettext("The items in your cart are no longer reserved for you. You can still complete your order as long as they're available.")
: gettext("Do you want to renew the reservation period?"));
$("#dialog-cart-extend .modal-card-confirm button").text(already_expired
? gettext("Continue")
: gettext("Renew reservation"));
}
},
cart._deadline_timeout = window.setTimeout(cart.draw_deadline, 500)
}
let already_expired = diff_total_seconds <= 0
let can_extend_cart = diff_minutes < 3 && (already_expired || cart._deadline < cart._max_extend)
$('#cart-extend-button').toggle(can_extend_cart)
if (can_extend_cart && diff_total_seconds < 45) {
if (!cart._expiry_notified) cart.show_expiry_notification()
$('#dialog-cart-extend-title').text(already_expired
? gettext('Your cart has expired.')
: gettext('Your cart is about to expire.'))
$('#dialog-cart-extend-description').text(already_expired
? gettext('The items in your cart are no longer reserved for you. You can still complete your order as long as they\'re available.')
: gettext('Do you want to renew the reservation period?'))
$('#dialog-cart-extend .modal-card-confirm button').text(already_expired
? gettext('Continue')
: gettext('Renew reservation'))
}
},
init: function () {
"use strict";
cart._calc_offset();
cart.set_deadline(
$("#cart-deadline").attr("data-expires"),
$("#cart-deadline").attr("data-max-expiry-extend")
);
},
init: function () {
'use strict'
cart._calc_offset()
cart.set_deadline(
$('#cart-deadline').attr('data-expires'),
$('#cart-deadline').attr('data-max-expiry-extend')
)
},
set_deadline: function (expiry, max_extend, renewed_message) {
"use strict";
cart._expiry_notified = false;
cart._deadline = moment(expiry);
if (cart._deadline_timeout) {
window.clearTimeout(cart._deadline_timeout);
}
cart._deadline_timeout = null;
cart._max_extend = moment(max_extend);
cart.draw_deadline();
}
};
set_deadline: function (expiry, max_extend, renewed_message) {
'use strict'
cart._expiry_notified = false
cart._deadline = moment(expiry)
if (cart._deadline_timeout) {
window.clearTimeout(cart._deadline_timeout)
}
cart._deadline_timeout = null
cart._max_extend = moment(max_extend)
cart.draw_deadline()
}
}
$(function () {
"use strict";
'use strict'
if ($("#cart-deadline").length) {
cart.init();
$("#cart-extend-confirmation-button").hide().on("blur", function() {
$(this).hide();
});
}
if ($('#cart-deadline').length) {
cart.init()
$('#cart-extend-confirmation-button').hide().on('blur', function () {
$(this).hide()
})
}
$("#cart-extend-form").on("pretix:async-task-success", function(e, data) {
if (data.success) {
cart.set_deadline(data.expiry, data.max_expiry_extend);
} else {
alert(data.message);
}
});
// renew-button in cart-panel is clicked, show inline dialog
$("#cart-extend-button").on("click", function() {
$("#cart-extend-form").one("pretix:async-task-success", function(e, data) {
if (data.success) {
document.getElementById("cart-extend-confirmation-dialog").show();
}
});
});
$("#cart-extend-confirmation-dialog").on("keydown", function (e) {
if(e.key === "Escape") {
this.close();
}
});
$('#cart-extend-form').on('pretix:async-task-success', function (_e, data) {
if (data.success) {
cart.set_deadline(data.expiry, data.max_expiry_extend)
} else {
alert(data.message)
}
})
// renew-button in cart-panel is clicked, show inline dialog
$('#cart-extend-button').on('click', function () {
$('#cart-extend-form').one('pretix:async-task-success', function (_e, data) {
if (data.success) {
document.getElementById('cart-extend-confirmation-dialog').show()
}
})
})
$('#cart-extend-confirmation-dialog').on('keydown', function (e) {
if (e.key === 'Escape') {
this.close()
}
})
// renew-button in modal dialog is clicked, show modal dialog
$("#dialog-cart-extend form").submit(function() {
$("#cart-extend-form").one("pretix:async-task-success", function(e, data) {
if (data.success) {
$("#dialog-cart-extended-title").text(data.message);
$("#dialog-cart-extended-description").text($("#cart-deadline").text());
document.getElementById("dialog-cart-extended").showModal();
}
}).submit();
});
// renew-button in modal dialog is clicked, show modal dialog
$('#dialog-cart-extend form').submit(function () {
$('#cart-extend-form').one('pretix:async-task-success', function (_e, data) {
if (data.success) {
$('#dialog-cart-extended-title').text(data.message)
$('#dialog-cart-extended-description').text($('#cart-deadline').text())
document.getElementById('dialog-cart-extended').showModal()
}
}).submit()
})
$(".toggle-container").each(function() {
var summary = $(".toggle-summary", this);
var content = $("> :not(.toggle-summary)", this);
var toggle = summary.find(".toggle").on("click", function(e) {
this.ariaExpanded = !this.ariaExpanded;
if (this.classList.contains("toggle-remove")) summary.attr("hidden", true);
content.show().find(":input:visible").first().focus();
});
if (toggle.attr("aria-expanded")) {
content.hide();
}
});
$('.toggle-container').each(function () {
let summary = $('.toggle-summary', this)
let content = $('> :not(.toggle-summary)', this)
let toggle = summary.find('.toggle').on('click', function () {
this.ariaExpanded = !this.ariaExpanded
if (this.classList.contains('toggle-remove')) summary.attr('hidden', true)
content.show().find(':input:visible').first().focus()
})
if (toggle.attr('aria-expanded')) {
content.hide()
}
})
$(".cart-icon-details.collapse-lines").each(function () {
var $content = $(this).find(".content");
var original_html = $content.html();
var br_exp = /<br\s*\/?>/i;
$content.text(original_html.split(br_exp).join(', '));
if ($content.get(0).scrollWidth > $content.get(0).offsetWidth) {
var $handler = $("<button>")
.text($(this).attr("data-expand-text"))
.addClass("btn btn-link collapse-handler")
.attr("type", "button")
.attr("aria-controls", $content.attr('id'))
.attr("aria-expanded", "false");
$handler.on("click", function (ev) {
$content.html(original_html).removeClass("content");
$handler.attr("aria-expanded", "true").attr("aria-hidden", "true");
$handler.hide();
});
$(this).append($handler);
}
})
});
$('.cart-icon-details.collapse-lines').each(function () {
let $content = $(this).find('.content')
let original_html = $content.html()
let br_exp = /<br\s*\/?>/i
$content.text(original_html.split(br_exp).join(', '))
if ($content.get(0).scrollWidth > $content.get(0).offsetWidth) {
let $handler = $('<button>')
.text($(this).attr('data-expand-text'))
.addClass('btn btn-link collapse-handler')
.attr('type', 'button')
.attr('aria-controls', $content.attr('id'))
.attr('aria-expanded', 'false')
$handler.on('click', function () {
$content.html(original_html).removeClass('content')
$handler.attr('aria-expanded', 'true').attr('aria-hidden', 'true')
$handler.hide()
})
$(this).append($handler)
}
})
})
@@ -1,145 +1,143 @@
/*global $ */
$(function () {
window.pretix = window.pretix || {};
window.pretix = window.pretix || {}
var storage_key = $("#cookie-consent-storage-key").text();
var widget_consent = $("#cookie-consent-from-widget").text();
var consent_checkboxes = $("#cookie-consent-details input[type=checkbox][name]");
var consent_modal = document.getElementById("cookie-consent-modal");
let storage_key = $('#cookie-consent-storage-key').text()
let widget_consent = $('#cookie-consent-from-widget').text()
let consent_checkboxes = $('#cookie-consent-details input[type=checkbox][name]')
let consent_modal = document.getElementById('cookie-consent-modal')
function update_consent(consent, sessionOnly) {
if (storage_key && window.sessionStorage && sessionOnly) {
if (!window.localStorage[storage_key] || window.localStorage[storage_key] !== JSON.stringify(consent)) {
// No need to write to sessionStorage if the value is identical to the one in localStorage
window.sessionStorage[storage_key] = JSON.stringify(consent);
}
} else if (storage_key && window.localStorage) {
window.localStorage[storage_key] = JSON.stringify(consent);
// When saving permanent storage, clear session storage
window.sessionStorage.removeItem(storage_key);
}
window.pretix.cookie_consent = consent;
function update_consent (consent, sessionOnly) {
if (storage_key && window.sessionStorage && sessionOnly) {
if (!window.localStorage[storage_key] || window.localStorage[storage_key] !== JSON.stringify(consent)) {
// No need to write to sessionStorage if the value is identical to the one in localStorage
window.sessionStorage[storage_key] = JSON.stringify(consent)
}
} else if (storage_key && window.localStorage) {
window.localStorage[storage_key] = JSON.stringify(consent)
// When saving permanent storage, clear session storage
window.sessionStorage.removeItem(storage_key)
}
window.pretix.cookie_consent = consent
// Event() is not supported by IE11, see ployfill here:
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#polyfill
var e = document.createEvent('CustomEvent');
e.initCustomEvent('pretix:cookie-consent:change', true, true, consent);
document.dispatchEvent(e)
}
// Event() is not supported by IE11, see ployfill here:
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#polyfill
let e = document.createEvent('CustomEvent')
e.initCustomEvent('pretix:cookie-consent:change', true, true, consent)
document.dispatchEvent(e)
}
if (!storage_key) {
// We are not on a page where the consent should run, fire the change event with empty consent but don't
// actually store anything.
update_consent(null, false);
return;
}
if (!storage_key) {
// We are not on a page where the consent should run, fire the change event with empty consent but don't
// actually store anything.
update_consent(null, false)
return
}
if (!window.localStorage) {
// Consent not supported. Even IE8 supports it, so we're on a weird embedded device.
// Let's just say we don't consent then.
update_consent({}, false)
return;
}
if (!window.localStorage) {
// Consent not supported. Even IE8 supports it, so we're on a weird embedded device.
// Let's just say we don't consent then.
update_consent({}, false)
return
}
var storage_val, consent_source, save_for_session_only;
if (window.sessionStorage[storage_key]) {
// A manual input was given inside a widget. This is the user's last explicit choice and takes precedence
// as long as they are in the widget.
storage_val = JSON.parse(window.sessionStorage[storage_key]);
consent_source = 'sessionStorage';
save_for_session_only = true;
} else if (widget_consent) {
// An input was given through the widget. This takes precedence over localStorage as we need to assume the
// widget embedder is doing a correct job. If the user never visited the page without the widget, we also
// use it to prefill local storage to save the user from seeing more cookie banners. (This will stop working
// when browsers partition local storage of iframes, anyway.) If the user does have visited the page without
// the widget before and has a consent setting in localStorage, we respect the widget consent *only* within
// the widget -- hence, we save it into sessionStorage. We need to save it into sessionStorage because the
// widget_data value itself will not "survive" the entire lifetime of the tab, i.e. it is no longer present
// after the order was confirmed.
widget_consent = JSON.parse(widget_consent);
storage_val = {};
consent_checkboxes.each(function () {
this.checked = storage_val[this.name] = widget_consent.indexOf(this.name) > -1;
});
consent_source = 'widget';
save_for_session_only = !!window.localStorage[storage_key];
} else if (window.localStorage[storage_key]) {
// The user made a specific selection, let's use that.
storage_val = JSON.parse(window.localStorage[storage_key]) || {};
consent_source = 'localStorage';
save_for_session_only = false;
} else {
// No consent given, dialog will be shown.
storage_val = {};
consent_source = 'new';
save_for_session_only = false;
}
let storage_val, consent_source, save_for_session_only
if (window.sessionStorage[storage_key]) {
// A manual input was given inside a widget. This is the user's last explicit choice and takes precedence
// as long as they are in the widget.
storage_val = JSON.parse(window.sessionStorage[storage_key])
consent_source = 'sessionStorage'
save_for_session_only = true
} else if (widget_consent) {
// An input was given through the widget. This takes precedence over localStorage as we need to assume the
// widget embedder is doing a correct job. If the user never visited the page without the widget, we also
// use it to prefill local storage to save the user from seeing more cookie banners. (This will stop working
// when browsers partition local storage of iframes, anyway.) If the user does have visited the page without
// the widget before and has a consent setting in localStorage, we respect the widget consent *only* within
// the widget -- hence, we save it into sessionStorage. We need to save it into sessionStorage because the
// widget_data value itself will not "survive" the entire lifetime of the tab, i.e. it is no longer present
// after the order was confirmed.
widget_consent = JSON.parse(widget_consent)
storage_val = {}
consent_checkboxes.each(function () {
this.checked = storage_val[this.name] = widget_consent.indexOf(this.name) > -1
})
consent_source = 'widget'
save_for_session_only = !!window.localStorage[storage_key]
} else if (window.localStorage[storage_key]) {
// The user made a specific selection, let's use that.
storage_val = JSON.parse(window.localStorage[storage_key]) || {}
consent_source = 'localStorage'
save_for_session_only = false
} else {
// No consent given, dialog will be shown.
storage_val = {}
consent_source = 'new'
save_for_session_only = false
}
var show_dialog = false;
consent_checkboxes.each(function () {
if (typeof storage_val[this.name] === "undefined") {
// A new cookie type has been added that we haven't asked for yet
if (consent_source === "widget") {
// Trust the widget, keep it as "no consent"
} else {
show_dialog = true;
}
} else if (storage_val[this.name]) {
this.checked = true;
}
})
let show_dialog = false
consent_checkboxes.each(function () {
if (typeof storage_val[this.name] === 'undefined') {
// A new cookie type has been added that we haven't asked for yet
if (consent_source === 'widget') {
// Trust the widget, keep it as "no consent"
} else {
show_dialog = true
}
} else if (storage_val[this.name]) {
this.checked = true
}
})
update_consent(storage_val, save_for_session_only);
update_consent(storage_val, save_for_session_only)
if (!consent_modal) {
// Cookie consent is active, but no provider defined
return;
}
if (!consent_modal) {
// Cookie consent is active, but no provider defined
return
}
function _set_button_text () {
var btn = $("#cookie-consent-button-no");
btn.text(
consent_checkboxes.filter(":checked").length ?
btn.attr("data-detail-text") :
btn.attr("data-summary-text")
);
}
function _set_button_text () {
let btn = $('#cookie-consent-button-no')
btn.text(
consent_checkboxes.filter(':checked').length
? btn.attr('data-detail-text')
: btn.attr('data-summary-text')
)
}
if (consent_checkboxes.filter(":checked").length) {
$("#cookie-consent-details").prop("open", true).find("> *:not(summary)").show();
}
if (consent_checkboxes.filter(':checked').length) {
$('#cookie-consent-details').prop('open', true).find('> *:not(summary)').show()
}
_set_button_text();
if (show_dialog) {
consent_modal.showModal();
consent_modal.addEventListener("cancel", function() {
// Dialog was initially shown, interpret Escape as „do not consent to new providers“
var consent = {};
consent_checkboxes.each(function () {
consent[this.name] = storage_val[this.name] || false;
});
update_consent(consent, false);
}, {once : true});
}
_set_button_text()
if (show_dialog) {
consent_modal.showModal()
consent_modal.addEventListener('cancel', function () {
// Dialog was initially shown, interpret Escape as „do not consent to new providers“
let consent = {}
consent_checkboxes.each(function () {
consent[this.name] = storage_val[this.name] || false
})
update_consent(consent, false)
}, { once: true })
}
consent_modal.addEventListener("close", function () {
if (!consent_modal.returnValue) {// ESC, do not save
return;
}
var consent = {};
var consent_all = consent_modal.returnValue == "yes";
consent_checkboxes.each(function () {
consent[this.name] = this.checked = consent_all || this.checked;
});
if (consent_all) _set_button_text();
update_consent(consent, false);
});
consent_checkboxes.on("change", _set_button_text);
$("#cookie-consent-reopen").on("click", function (e) {
consent_modal.showModal()
e.preventDefault()
return true
})
});
consent_modal.addEventListener('close', function () {
if (!consent_modal.returnValue) { // ESC, do not save
return
}
let consent = {}
let consent_all = consent_modal.returnValue == 'yes'
consent_checkboxes.each(function () {
consent[this.name] = this.checked = consent_all || this.checked
})
if (consent_all) _set_button_text()
update_consent(consent, false)
})
consent_checkboxes.on('change', _set_button_text)
$('#cookie-consent-reopen').on('click', function (e) {
consent_modal.showModal()
e.preventDefault()
return true
})
})
+16 -16
View File
@@ -1,18 +1,18 @@
var inIframe = function () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
};
let inIframe = function () {
try {
return window.self !== window.top
} catch (_e) {
return true
}
}
if (inIframe()) {
document.documentElement.classList.add('in-iframe');
try {
window.parent.postMessage({
type: "pretix:widget:title",
title: document.title,
}, "*");
} catch (e) {
console.error("Could not post message to parent.", e);
}
document.documentElement.classList.add('in-iframe')
try {
window.parent.postMessage({
type: 'pretix:widget:title',
title: document.title,
}, '*')
} catch (e) {
console.error('Could not post message to parent.', e)
}
}
File diff suppressed because it is too large Load Diff
+426 -434
View File
@@ -1,134 +1,132 @@
/*global $ */
function questions_toggle_dependent (ev) {
function q_should_be_shown ($el) {
if (!$el.attr('data-question-dependency')) {
return true
}
function questions_toggle_dependent(ev) {
function q_should_be_shown($el) {
if (!$el.attr('data-question-dependency')) {
return true;
}
let dependency_name = $el.attr('name').split('_')[0] + '_' + $el.attr('data-question-dependency')
let dependency_values = JSON.parse($el.attr('data-question-dependency-values'))
let $dependency_el
var dependency_name = $el.attr("name").split("_")[0] + "_" + $el.attr("data-question-dependency");
var dependency_values = JSON.parse($el.attr("data-question-dependency-values"));
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) && $.inArray($dependency_el.val(), dependency_values) > -1
}
} else if ($('input[type=checkbox][name=' + dependency_name + ']').length) {
// dependency type is B or M
if ($.inArray('True', dependency_values) > -1 || $.inArray('False', dependency_values) > -1) {
$dependency_el = $('input[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) && (
($.inArray('True', dependency_values) > -1 && $dependency_el.prop('checked'))
|| ($.inArray('False', dependency_values) > -1 && !$dependency_el.prop('checked'))
)
}
} else {
let filter = ''
for (let i = 0; i < dependency_values.length; i++) {
if (filter) filter += ', '
filter += 'input[value=' + dependency_values[i] + '][name=' + dependency_name + ']:checked'
}
$dependency_el = $('input[value=' + dependency_values[0] + '][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) && $(filter).length
}
}
}
}
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) && $.inArray($dependency_el.val(), dependency_values) > -1;
}
} else if ($("input[type=checkbox][name=" + dependency_name + "]").length) {
// dependency type is B or M
if ($.inArray("True", dependency_values) > -1 || $.inArray("False", dependency_values) > -1) {
$dependency_el = $("input[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) && (
($.inArray("True", dependency_values) > -1 && $dependency_el.prop('checked'))
|| ($.inArray("False", dependency_values) > -1 && !$dependency_el.prop('checked'))
);
}
} else {
var filter = "";
for (var i = 0; i < dependency_values.length; i++) {
if (filter) filter += ", ";
filter += "input[value=" + dependency_values[i] + "][name=" + dependency_name + "]:checked";
}
$dependency_el = $("input[value=" + dependency_values[0] + "][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) && $(filter).length;
}
}
}
}
$('[data-question-dependency]').each(function () {
let $dependent = $(this).closest('.form-group')
let is_shown = !$dependent.hasClass('dependency-hidden')
let should_be_shown = q_should_be_shown($(this))
$("[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");
});
}
});
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')
})
}
})
}
function questions_init_photos(el) {
if (!FileReader) {
// No browser support
return
}
function questions_init_photos (el) {
if (!FileReader) {
// No browser support
return
}
el.find("input[data-portrait-photo]").each(function () {
var $inp = $(this)
var $container = $inp.parent().parent()
el.find('input[data-portrait-photo]').each(function () {
let $inp = $(this)
let $container = $inp.parent().parent()
$inp.prop("required", false)
$container.find(".photo-input").addClass("hidden")
$container.find(".photo-buttons").removeClass("hidden")
$inp.prop('required', false)
$container.find('.photo-input').addClass('hidden')
$container.find('.photo-buttons').removeClass('hidden')
$container.find("button[data-action=upload]").click(function () {
$inp.click();
})
$container.find('button[data-action=upload]').click(function () {
$inp.click()
})
var cropper = new Cropper($container.find(".photo-preview img").get(0), {
aspectRatio: 3 / 4,
viewMode: 1,
zoomable: false,
crop: function (event) {
$container.find("input[type=hidden]").val(JSON.stringify(cropper.getData(true)));
},
});
/* This rule is very important, please don't ignore this */
var cropper = new Cropper($container.find('.photo-preview img').get(0), {
aspectRatio: 3 / 4,
viewMode: 1,
zoomable: false,
crop: function (event) {
$container.find('input[type=hidden]').val(JSON.stringify(cropper.getData(true)))
},
})
/* This rule is very important, please don't ignore this */
$inp.on("change", function () {
if (!$inp.get(0).files[0]) return
$container.find("button[data-action=upload]").append("<span class='fa fa-spin fa-cog'></span>")
var fr = new FileReader()
fr.onload = function () {
cropper.replace(fr.result)
$container.find(".photo-preview").removeClass("hidden")
$container.find("button[data-action=upload] .fa-spin").remove()
}
fr.readAsDataURL($inp.get(0).files[0])
})
});
$inp.on('change', function () {
if (!$inp.get(0).files[0]) return
$container.find('button[data-action=upload]').append('<span class=\'fa fa-spin fa-cog\'></span>')
let fr = new FileReader()
fr.onload = function () {
cropper.replace(fr.result)
$container.find('.photo-preview').removeClass('hidden')
$container.find('button[data-action=upload] .fa-spin').remove()
}
fr.readAsDataURL($inp.get(0).files[0])
})
})
}
function questions_init_profiles(el) {
/*
function questions_init_profiles (el) {
/*
Auto-fill answers with profiles and addresses from customer account.
There are two types of profiles:
1. profiles for answers and
1. profiles for answers and
2. profiles for invoice addresses
Both are handled the same way.
Each form section/fieldset has its own auto-fill and save to profile
inputs. Each fieldset can define its own profiles by providing the
Each form section/fieldset has its own auto-fill and save to profile
inputs. Each fieldset can define its own profiles by providing the
HTML-attribute data-profiles-id, which defaults to "profiles_json".
Currently only the invoice address fieldset uses this to load a
Currently only the invoice address fieldset uses this to load a
different set of profiles.
For each section each profiles answers are matched to inputs inside
@@ -141,349 +139,343 @@ function questions_init_profiles(el) {
in the original profile description, strikethrough which answer
will be overwritten, followed by the new answer
add new answers with a + in front
change <select> to a list of radio-buttons for multiline-display
change <select> to a list of radio-buttons for multiline-display
of profiles?
*/
var profilesById = {};
function getProfilesById(id) {
if (!(id in profilesById)) {
var element = document.getElementById(id);
profilesById[id] = (!element || !element.textContent) ? [] : JSON.parse(element.textContent);
}
return profilesById[id];
}
let profilesById = {}
function getProfilesById (id) {
if (!(id in profilesById)) {
let element = document.getElementById(id)
profilesById[id] = (!element || !element.textContent) ? [] : JSON.parse(element.textContent)
}
return profilesById[id]
}
function matchProfilesToInputs(profiles, scope) {
var filtered = [];
var data;
var matched_field;
var addSpecialKey;
// special fields are used for substition with human readable or pre-formatted values
var addSpecialFieldMap = {
"country": "_country_for_address",
"state": "_state_for_address",
"name_parts_0": "_name",
"attendee_name_parts_0": "_attendee_name",
}
for (var p of profiles) {
data = {};
for (var key of Object.keys(p)) {
if (key.startsWith("_") || p[key] === null) {
continue;
}
matched_field = getMatchingInput(key, p[key], scope);
if (matched_field) {
// TODO: only add if no other answer matches same fields?
data[key] = {
"value": (typeof p[key] == "string") ? p[key] : p[key]["value"],
"field": matched_field
};
if (p[key]["label"]) data[key]["label"] = p[key]["label"];
if (p[key]["type"]) data[key]["type"] = p[key]["type"];
if (addSpecialKey = addSpecialFieldMap[key]) {
data[addSpecialKey] = p[addSpecialKey];
}
}
}
if (Object.keys(data).length) filtered.push(data);
};
return filtered;
}
// For auto-fill with few inputs it could happen that multiple profiles
// only match with the same fields that have the same values. It makes
// no sense to show multiple profiles if all fill the same value(s).
// Therefore filter profiles to unique ones.
function uniqueProfiles(profiles) {
var uniques = [];
var matchIndex;
for (var p of profiles) {
matchIndex = uniques.findIndex(function(element, index, array) {
return _profilesAreEqual(element, p);
});
if (matchIndex === -1) uniques.push(p);
}
return uniques;
}
function _profilesAreEqual(a, b) {
var keysA = Object.keys(a);
var keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
keysA.sort();
keysB.sort();
if (!keysA.every((val, index) => val === keysB[index])) return false;
if (!keysA.every((key, index) => a[key].value === b[key].value)) return false;
return true;
}
function matchProfilesToInputs (profiles, scope) {
let filtered = []
let data
let matched_field
let addSpecialKey
// special fields are used for substition with human readable or pre-formatted values
let addSpecialFieldMap = {
country: '_country_for_address',
state: '_state_for_address',
name_parts_0: '_name',
attendee_name_parts_0: '_attendee_name',
}
for (let p of profiles) {
data = {}
for (let key of Object.keys(p)) {
if (key.startsWith('_') || p[key] === null) {
continue
}
matched_field = getMatchingInput(key, p[key], scope)
if (matched_field) {
// TODO: only add if no other answer matches same fields?
data[key] = {
value: (typeof p[key] == 'string') ? p[key] : p[key]['value'],
field: matched_field
}
if (p[key]['label']) data[key]['label'] = p[key]['label']
if (p[key]['type']) data[key]['type'] = p[key]['type']
if (addSpecialKey = addSpecialFieldMap[key]) {
data[addSpecialKey] = p[addSpecialKey]
}
}
}
if (Object.keys(data).length) filtered.push(data)
};
return filtered
}
// For auto-fill with few inputs it could happen that multiple profiles
// only match with the same fields that have the same values. It makes
// no sense to show multiple profiles if all fill the same value(s).
// Therefore filter profiles to unique ones.
function uniqueProfiles (profiles) {
let uniques = []
let matchIndex
for (var p of profiles) {
matchIndex = uniques.findIndex(function (element, index, array) {
return _profilesAreEqual(element, p)
})
if (matchIndex === -1) uniques.push(p)
}
return uniques
}
function _profilesAreEqual (a, b) {
let keysA = Object.keys(a)
let keysB = Object.keys(b)
if (keysA.length !== keysB.length) return false
keysA.sort()
keysB.sort()
if (!keysA.every((val, index) => val === keysB[index])) return false
if (!keysA.every((key, index) => a[key].value === b[key].value)) return false
return true
}
function _getInputForLabel(label) {
if (!label) return null;
var input;
if (label.getAttribute("for")) {
input = document.getElementById(label.getAttribute("for"));
if (input) return input;
}
// for grouped inputs like phone number the "label" is more a fieldset/legend
return label.closest(".form-group").querySelectorAll("select, input, textarea");
}
function getMatchingInput(key, answer, scope) {
var $label;
// _0 and _1 are e.g. for phone-fields. name-fields have their parts/keys already split
var $fields = $('[name$="' + key + '"], [name$="' + key + '_0"], [name$="' + key + '_1"]', scope).not(":disabled");
if ($fields.length) return $fields;
if (!answer) return null;
function _getInputForLabel (label) {
if (!label) return null
let input
if (label.getAttribute('for')) {
input = document.getElementById(label.getAttribute('for'))
if (input) return input
}
// for grouped inputs like phone number the "label" is more a fieldset/legend
return label.closest('.form-group').querySelectorAll('select, input, textarea')
}
function getMatchingInput (key, answer, scope) {
let $label
// _0 and _1 are e.g. for phone-fields. name-fields have their parts/keys already split
let $fields = $('[name$="' + key + '"], [name$="' + key + '_0"], [name$="' + key + '_1"]', scope).not(':disabled')
if ($fields.length) return $fields
if (!answer) return null
if (answer.identifier) {
$label = $('[data-identifier="' + answer.identifier + '"]', scope);
var input = _getInputForLabel($label.get(0));
if (input) return $(input);
}
for (var label of scope.getElementsByTagName("label")) {
if (label.textContent === answer.label) {
var input = _getInputForLabel(label);
if (input) return $(input);
break;
}
}
return null;
}
if (answer.identifier) {
$label = $('[data-identifier="' + answer.identifier + '"]', scope)
var input = _getInputForLabel($label.get(0))
if (input) return $(input)
}
for (let label of scope.getElementsByTagName('label')) {
if (label.textContent === answer.label) {
var input = _getInputForLabel(label)
if (input) return $(input)
break
}
}
return null
}
function formatAnswerHumanReadable(answer) {
if (typeof answer == "string") return answer;
if (typeof answer == "number") return answer.toString();
if (!answer && answer !== false) return "";
var value = answer.value;
if ("type" in answer) {
if (answer.type === "TEL") {
// TODO: format phone number with locale or use pre-formatted like with names?
return value;
}
if (answer.type === "W") {
return moment(value).format(document.body.getAttribute("data-datetimeformat"));
}
if (answer.type === "D") {
return moment(value).format(document.body.getAttribute("data-dateformat"));
}
if (answer.type === "H") {
var format = document.body.getAttribute("data-timeformat");
return moment(value, "HH:mm:ss").format(format);
}
if (answer.type === "B") {
return value ? gettext("Yes") : gettext("No");
}
}
if (typeof value == "string") return value;
if (!value) return "";
return Object.values(value).join(", ");
}
function formatAnswerHumanReadable (answer) {
if (typeof answer == 'string') return answer
if (typeof answer == 'number') return answer.toString()
if (!answer && answer !== false) return ''
let value = answer.value
if ('type' in answer) {
if (answer.type === 'TEL') {
// TODO: format phone number with locale or use pre-formatted like with names?
return value
}
if (answer.type === 'W') {
return moment(value).format(document.body.getAttribute('data-datetimeformat'))
}
if (answer.type === 'D') {
return moment(value).format(document.body.getAttribute('data-dateformat'))
}
if (answer.type === 'H') {
let format = document.body.getAttribute('data-timeformat')
return moment(value, 'HH:mm:ss').format(format)
}
if (answer.type === 'B') {
return value ? gettext('Yes') : gettext('No')
}
}
if (typeof value == 'string') return value
if (!value) return ''
return Object.values(value).join(', ')
}
// TODO: add as few info as possible to make a distinction between available profiles?
function labelForProfile(p, profiles, scope = null) {
var parts = describeProfile(p);
var label = parts.join(", ");
if (label.length > 74) {
var len = label.lastIndexOf(' ', 74);
label = label.substr(0, Math.max(len, 48)) + " …";
}
return label;
}
function getAnswer(a) {
if (typeof a == "string") return a;
return a && "value" in a ? a["value"] : "";
}
function describeProfile(p) {
if (!p) return [];
var lines = [
getAnswer(p["company"]),
p["_name"],
[p["_attendee_name"], getAnswer(p["attendee_email"])].filter(v => v).join(", "),
[
getAnswer(p["street"]),
[getAnswer(p["zipcode"]), getAnswer(p["city"]), p["_state_for_address"]].filter(v => v).join(" "),
p["_country_for_address"]
].filter(v => v).join(", ")
];
lines = lines.filter(line => line && line.trim());
// TODO: add as few info as possible to make a distinction between available profiles?
function labelForProfile (p, profiles, scope = null) {
let parts = describeProfile(p)
let label = parts.join(', ')
if (label.length > 74) {
let len = label.lastIndexOf(' ', 74)
label = label.substr(0, Math.max(len, 48)) + ' …'
}
return label
}
function getAnswer (a) {
if (typeof a == 'string') return a
return a && 'value' in a ? a['value'] : ''
}
function describeProfile (p) {
if (!p) return []
let lines = [
getAnswer(p['company']),
p['_name'],
[p['_attendee_name'], getAnswer(p['attendee_email'])].filter(v => v).join(', '),
[
getAnswer(p['street']),
[getAnswer(p['zipcode']), getAnswer(p['city']), p['_state_for_address']].filter(v => v).join(' '),
p['_country_for_address']
].filter(v => v).join(', ')
]
lines = lines.filter(line => line && line.trim())
var answer;
var label;
for (var key of Object.keys(p)) {
if (!key.startsWith("question_")) continue;
answer = p[key];
label = answer["label"] || "";
lines.push(label + ("!?.:".split("").indexOf(label.slice(-1)) > -1 ? " " : ": ") + formatAnswerHumanReadable(answer))
}
return lines;
}
function escapeHTML(t) {
return $("<div>").text(t).get(0).innerHTML;
}
function describeProfileHTML(p) {
return describeProfile(p).map(escapeHTML).join("<br>");
}
let answer
let label
for (let key of Object.keys(p)) {
if (!key.startsWith('question_')) continue
answer = p[key]
label = answer['label'] || ''
lines.push(label + ('!?.:'.split('').indexOf(label.slice(-1)) > -1 ? ' ' : ': ') + formatAnswerHumanReadable(answer))
}
return lines
}
function escapeHTML (t) {
return $('<div>').text(t).get(0).innerHTML
}
function describeProfileHTML (p) {
return describeProfile(p).map(escapeHTML).join('<br>')
}
function _updateDescription (select, profile, $help) {
// show additional description if different from option-text
let label = select.options[select.selectedIndex].textContent
let lines = describeProfile(profile).map(escapeHTML)
if (!lines.length || label === lines.join(', ')) {
$help.slideUp(function () {
$help.html('')
})
} else {
$help.html(lines.join('<br>')).slideDown()
}
}
function _updateDescription(select, profile, $help) {
// show additional description if different from option-text
var label = select.options[select.selectedIndex].textContent;
var lines = describeProfile(profile).map(escapeHTML);
if (!lines.length || label === lines.join(", ")) {
$help.slideUp(function() {
$help.html("");
});
}
else {
$help.html(lines.join("<br>")).slideDown();
}
}
function setupSaveToProfile (scope, profiles) {
let $select = $('[name$="saved_id"]', scope)
let $selectContainer = $select.closest('.form-group').addClass('profile-save-id')
let $checkbox = $('[name$="save"]', scope)
let $checkboxContainer = $checkbox.closest('.form-group').addClass('profile-save')
let $help = $selectContainer.find('.help-block')
function setupSaveToProfile(scope, profiles) {
var $select = $('[name$="saved_id"]', scope);
var $selectContainer = $select.closest(".form-group").addClass("profile-save-id");
var $checkbox = $('[name$="save"]', scope);
var $checkboxContainer = $checkbox.closest(".form-group").addClass("profile-save");
var $help = $selectContainer.find(".help-block");
let $container = $('<div class=\'profile-save-container js-do-not-copy-answers\'></div>')
$selectContainer.after($container)
$container.append($checkboxContainer)
$container.append($selectContainer)
var $container = $("<div class='profile-save-container js-do-not-copy-answers'></div>");
$selectContainer.after($container);
$container.append($checkboxContainer);
$container.append($selectContainer);
if (!profiles || !profiles.length) {
$selectContainer.hide();
return;
}
if (!profiles || !profiles.length) {
$selectContainer.hide()
return
}
$checkbox.change(function() {
if (this.checked) $selectContainer.slideDown();
else $selectContainer.slideUp();
});
$checkbox.change(function () {
if (this.checked) $selectContainer.slideDown()
else $selectContainer.slideUp()
})
for (var p of profiles) {
$select.append($('<option>').attr('value', p._pk).text(labelForProfile(p, profiles)));
}
$select.append('<option value="" disabled></option>');
$select.append($select.find("option").first());
$select.get(0).selectedIndex = 0;
$select.change(function() {
_updateDescription(this, profiles[this.selectedIndex], $help);
}).trigger("change");
$checkbox.trigger("change");
}
for (let p of profiles) {
$select.append($('<option>').attr('value', p._pk).text(labelForProfile(p, profiles)))
}
$select.append('<option value="" disabled></option>')
$select.append($select.find('option').first())
$select.get(0).selectedIndex = 0
$select.change(function () {
_updateDescription(this, profiles[this.selectedIndex], $help)
}).trigger('change')
$checkbox.trigger('change')
}
// setup auto-fill for each scope/fieldset
// match profiles answers to inputs in scope
// if none match, do not show auto-fill
// if one matches, only show button to auto-fill
// else show select with profiles and button to auto-fill
function setupAutoFill(scope, profiles) {
var matchedProfiles = uniqueProfiles(matchProfilesToInputs(profiles, scope));
if (!matchedProfiles.length) {
$(scope).addClass("profile-none-matched");
return;
}
// setup auto-fill for each scope/fieldset
// match profiles answers to inputs in scope
// if none match, do not show auto-fill
// if one matches, only show button to auto-fill
// else show select with profiles and button to auto-fill
function setupAutoFill (scope, profiles) {
let matchedProfiles = uniqueProfiles(matchProfilesToInputs(profiles, scope))
if (!matchedProfiles.length) {
$(scope).addClass('profile-none-matched')
return
}
var selectedProfile = matchedProfiles[0];
var $select = $(".profile-select", scope);
var $button = $(".profile-apply", scope);
var $help = $(".profile-desc", scope);
let selectedProfile = matchedProfiles[0]
let $select = $('.profile-select', scope)
let $button = $('.profile-apply', scope)
let $help = $('.profile-desc', scope)
if (matchedProfiles.length === 1) {
$(".profile-select-control", scope).hide().parent().addClass("form-control-text");
$help.html(describeProfileHTML(selectedProfile)).addClass("single-profile-desc").after($button);
}
else {
var i = 0;
for (p of matchedProfiles) {
$select.append($("<option>").text(labelForProfile(p, matchedProfiles, scope)).attr("value", i));
i++;
}
$select.change(function() {
selectedProfile = matchedProfiles[this.value];
_updateDescription(this, selectedProfile, $help);
}).trigger("change");
}
// Add-Ons sit on same level as their parent product scope
// Therefore use .prevUntil("legend") as an Add-On is
// offset by a <legend>
// if no <legend> is present e.g. on invoice-address the
// containing <summary> would be selected, which is not what we want
$(scope).prevUntil("legend").not("summary").addClass("profile-pre-select");
if (matchedProfiles.length === 1) {
$('.profile-select-control', scope).hide().parent().addClass('form-control-text')
$help.html(describeProfileHTML(selectedProfile)).addClass('single-profile-desc').after($button)
} else {
let i = 0
for (p of matchedProfiles) {
$select.append($('<option>').text(labelForProfile(p, matchedProfiles, scope)).attr('value', i))
i++
}
$select.change(function () {
selectedProfile = matchedProfiles[this.value]
_updateDescription(this, selectedProfile, $help)
}).trigger('change')
}
// Add-Ons sit on same level as their parent product scope
// Therefore use .prevUntil("legend") as an Add-On is
// offset by a <legend>
// if no <legend> is present e.g. on invoice-address the
// containing <summary> would be selected, which is not what we want
$(scope).prevUntil('legend').not('summary').addClass('profile-pre-select')
$button.click(function() {
Object.keys(selectedProfile).forEach(function(key) {
var answer = selectedProfile[key].value;
var $field = selectedProfile[key].field;
if (!$field || !$field.length) return;
if ($field.attr("type") === "checkbox") {
if (answer === true || answer === false) {
// boolean
$field.prop("checked", answer).trigger("change");
}
else if (typeof answer !== 'string') {
answer = Object.keys(answer);
$field.each(function() {
var checked = answer.indexOf(this.value) > -1;
if (checked !== this.checked) {
this.checked = checked;
$(this).trigger("change");
}
});
}
} else if ($field.attr("type") === "radio") {
$field.filter('[value="' + answer + '"]').prop("checked", true).trigger("change");
} else if ($field.length > 1) {
// multiple matching fields, could be phone number or datetime
var $field_0 = $field.filter('[name$="_0"]');
var $field_1 = $field.filter('[name$="_1"]');
if (answer.substr(0, 1) === "+") {
var prefix = "";
var options = $field_0.get(0).options;
for (var i = 0; i < options.length; i++) {
var v = options[i].value;
if (v && answer.substr(0, v.length) === v) {
prefix = v;
break;
}
}
var number = answer.substr(prefix.length);
$field_0.val(prefix).trigger("change");
$field_1.val(number).trigger("change");
}
else if ($field_0.hasClass("datepickerfield")) {
$field_0.data('DateTimePicker').date(moment(answer));
$field_1.data('DateTimePicker').date(moment(answer));
}
} else if ($field.is("select")) {
if (answer && typeof answer !== 'string') {
answer = Object.keys(answer);
}
// save answer as data-attribute so if external event changes select-element/options it can select correct entries
// currently used when country => state changes
$field.prop("data-selected-value", answer);
$field.find("option").each(function() {
this.selected = this.value === answer || (answer && answer.indexOf && answer.indexOf(this.value) > -1);
});
$field.trigger("change");
} else {
if ($field.hasClass("datepickerfield")) {
$field.data('DateTimePicker').date(moment(answer));
}
else {
$field.val(answer).trigger("change");
}
}
});
})
}
$button.click(function () {
Object.keys(selectedProfile).forEach(function (key) {
let answer = selectedProfile[key].value
let $field = selectedProfile[key].field
if (!$field || !$field.length) return
// each fieldset is its own scope for auto-fill and save
el.find(".profile-scope").each(function () {
var profiles = getProfilesById(this.getAttribute("data-profiles-id") || "profiles_json");
if ($field.attr('type') === 'checkbox') {
if (answer === true || answer === false) {
// boolean
$field.prop('checked', answer).trigger('change')
} else if (typeof answer !== 'string') {
answer = Object.keys(answer)
$field.each(function () {
let checked = answer.indexOf(this.value) > -1
if (checked !== this.checked) {
this.checked = checked
$(this).trigger('change')
}
})
}
} else if ($field.attr('type') === 'radio') {
$field.filter('[value="' + answer + '"]').prop('checked', true).trigger('change')
} else if ($field.length > 1) {
// multiple matching fields, could be phone number or datetime
let $field_0 = $field.filter('[name$="_0"]')
let $field_1 = $field.filter('[name$="_1"]')
if (answer.substr(0, 1) === '+') {
let prefix = ''
let options = $field_0.get(0).options
for (let i = 0; i < options.length; i++) {
let v = options[i].value
if (v && answer.substr(0, v.length) === v) {
prefix = v
break
}
}
let number = answer.substr(prefix.length)
$field_0.val(prefix).trigger('change')
$field_1.val(number).trigger('change')
} else if ($field_0.hasClass('datepickerfield')) {
$field_0.data('DateTimePicker').date(moment(answer))
$field_1.data('DateTimePicker').date(moment(answer))
}
} else if ($field.is('select')) {
if (answer && typeof answer !== 'string') {
answer = Object.keys(answer)
}
// save answer as data-attribute so if external event changes select-element/options it can select correct entries
// currently used when country => state changes
$field.prop('data-selected-value', answer)
$field.find('option').each(function () {
this.selected = this.value === answer || (answer && answer.indexOf && answer.indexOf(this.value) > -1)
})
$field.trigger('change')
} else {
if ($field.hasClass('datepickerfield')) {
$field.data('DateTimePicker').date(moment(answer))
} else {
$field.val(answer).trigger('change')
}
}
})
})
}
setupSaveToProfile(this, profiles);
setupAutoFill(this, profiles);
// each fieldset is its own scope for auto-fill and save
el.find('.profile-scope').each(function () {
let profiles = getProfilesById(this.getAttribute('data-profiles-id') || 'profiles_json')
this.classList.add("profile-select-initialized");
});
setupSaveToProfile(this, profiles)
setupAutoFill(this, profiles)
this.classList.add('profile-select-initialized')
})
}
+43 -45
View File
@@ -1,53 +1,51 @@
/*global $ */
$(function () {
var popup_window = null
var popup_check_interval = null
let popup_window = null
let popup_check_interval = null
$("a[data-open-in-popup-window]").on("click", function (e) {
e.preventDefault()
$('a[data-open-in-popup-window]').on('click', function (e) {
e.preventDefault()
$("#popupmodal a").attr("href", this.href)
$('#popupmodal a').attr('href', this.href)
var url = this.href
if (url.includes("?")) {
url += "&popup_origin=" + window.location.origin
} else {
url += "?popup_origin=" + window.location.origin
}
popup_window = window.open(
url,
"presale-popup",
"scrollbars=yes,resizable=yes,status=yes,location=yes,toolbar=no,menubar=no,width=940,height=620,left=50,top=50"
)
$("body").addClass("has-popup has-modal-dialog")
$("#popupmodal").removeAttr("hidden");
let url = this.href
if (url.includes('?')) {
url += '&popup_origin=' + window.location.origin
} else {
url += '?popup_origin=' + window.location.origin
}
popup_window = window.open(
url,
'presale-popup',
'scrollbars=yes,resizable=yes,status=yes,location=yes,toolbar=no,menubar=no,width=940,height=620,left=50,top=50'
)
$('body').addClass('has-popup has-modal-dialog')
$('#popupmodal').removeAttr('hidden')
popup_check_interval = window.setInterval(function () {
if (popup_window.closed) {
$("body").removeClass("has-popup has-modal-dialog")
$("#popupmodal").attr("hidden", true);
window.clearInterval(popup_check_interval)
}
}, 250)
popup_check_interval = window.setInterval(function () {
if (popup_window.closed) {
$('body').removeClass('has-popup has-modal-dialog')
$('#popupmodal').attr('hidden', true)
window.clearInterval(popup_check_interval)
}
}, 250)
return false
});
return false
})
window.addEventListener("message", function (event) {
if (event.source !== popup_window)
return
if (event.data && event.data.__process === "customer_sso_popup") {
if (event.data.status === "ok") {
$("#customer_login .alert.alert-danger").addClass("hidden");
$("#login_sso_data").val(event.data.value)
$("#login_sso_data").closest("form").get(0).submit()
} else {
$("#customer_login .alert.alert-danger").html(event.data.value);
$("#customer_login .alert.alert-danger").removeClass("hidden");
}
event.source.postMessage({'__process': 'popup_close'}, "*")
}
console.log(event)
}, false);
window.addEventListener('message', function (event) {
if (event.source !== popup_window)
return
if (event.data && event.data.__process === 'customer_sso_popup') {
if (event.data.status === 'ok') {
$('#customer_login .alert.alert-danger').addClass('hidden')
$('#login_sso_data').val(event.data.value)
$('#login_sso_data').closest('form').get(0).submit()
} else {
$('#customer_login .alert.alert-danger').html(event.data.value)
$('#customer_login .alert.alert-danger').removeClass('hidden')
}
event.source.postMessage({ __process: 'popup_close' }, '*')
}
console.log(event)
}, false)
})
@@ -1,71 +1,72 @@
'use strict';
/* global google, gettext */
'use strict'
var walletdetection = {
applepay: async function () {
// This is a weak check for Apple Pay - in order to do a proper check, we would need to also call
// canMakePaymentsWithActiveCard(merchantIdentifier)
let walletdetection = {
applepay: async function () {
// This is a weak check for Apple Pay - in order to do a proper check, we would need to also call
// canMakePaymentsWithActiveCard(merchantIdentifier)
return !!(window.ApplePaySession && window.ApplePaySession.canMakePayments());
},
googlepay: async function () {
// Checking for Google Pay is a little bit more involved, since it requires including the Google Pay JS SDK, and
// providing a lot of information.
// So for the time being, we only check if Google Pay is available in TEST-mode, which should hopefully give us a
// good enough idea if Google Pay could be present on this device; even though there are still a lot of other
// factors that could inhibit Google Pay from actually being offered to the customer.
return !!(window.ApplePaySession && window.ApplePaySession.canMakePayments())
},
googlepay: async function () {
// Checking for Google Pay is a little bit more involved, since it requires including the Google Pay JS SDK, and
// providing a lot of information.
// So for the time being, we only check if Google Pay is available in TEST-mode, which should hopefully give us a
// good enough idea if Google Pay could be present on this device; even though there are still a lot of other
// factors that could inhibit Google Pay from actually being offered to the customer.
return $.ajax({
url: 'https://pay.google.com/gp/p/js/pay.js',
dataType: 'script',
}).then(function() {
const paymentsClient = new google.payments.api.PaymentsClient({environment: 'TEST'});
return paymentsClient.isReadyToPay({
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: [{
type: 'CARD',
parameters: {
allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
allowedCardNetworks: ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"]
}
}],
})
}).then(function (response) {
return !!response.result;
});
},
name_map: {
applepay: gettext('Apple Pay'),
googlepay: gettext('Google Pay'),
}
return $.ajax({
url: 'https://pay.google.com/gp/p/js/pay.js',
dataType: 'script',
}).then(function () {
const paymentsClient = new google.payments.api.PaymentsClient({ environment: 'TEST' })
return paymentsClient.isReadyToPay({
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: [{
type: 'CARD',
parameters: {
allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
allowedCardNetworks: ['AMEX', 'DISCOVER', 'INTERAC', 'JCB', 'MASTERCARD', 'VISA']
}
}],
})
}).then(function (response) {
return !!response.result
})
},
name_map: {
applepay: gettext('Apple Pay'),
googlepay: gettext('Google Pay'),
}
}
$(function () {
const wallets = $('[data-wallets]')
.map(function(index, pm) {
return pm.getAttribute("data-wallets").split("|");
})
.get()
.flat()
.filter(function(item, pos, self) {
// filter out empty or duplicate values
return item && self.indexOf(item) == pos;
});
const wallets = $('[data-wallets]')
.map(function (_index, pm) {
return pm.getAttribute('data-wallets').split('|')
})
.get()
.flat()
.filter(function (item, pos, self) {
// filter out empty or duplicate values
return item && self.indexOf(item) == pos
})
wallets.forEach(function(wallet) {
const labels = $('[data-wallets*='+wallet+'] + .accordion-label-text')
.append('<span class="wallet wallet-loading" data-wallet="'+wallet+'"> <span aria-hidden="true" class="fa fa-cog fa-spin"></span></span>')
walletdetection[wallet]()
.then(function(result) {
const spans = labels.find(".wallet-loading[data-wallet=" + wallet + "]");
if (result) {
spans.removeClass('wallet-loading').hide().text(', ' + walletdetection.name_map[wallet]).fadeIn(300);
} else {
spans.remove();
}
})
.catch(function(result) {
labels.find(".wallet-loading[data-wallet=" + wallet + "]").remove();
})
});
});
wallets.forEach(function (wallet) {
const labels = $('[data-wallets*=' + wallet + '] + .accordion-label-text')
.append('<span class="wallet wallet-loading" data-wallet="' + wallet + '"> <span aria-hidden="true" class="fa fa-cog fa-spin"></span></span>')
walletdetection[wallet]()
.then(function (result) {
const spans = labels.find('.wallet-loading[data-wallet=' + wallet + ']')
if (result) {
spans.removeClass('wallet-loading').hide().text(', ' + walletdetection.name_map[wallet]).fadeIn(300)
} else {
spans.remove()
}
})
.catch(function () {
labels.find('.wallet-loading[data-wallet=' + wallet + ']').remove()
})
})
})
@@ -2,80 +2,80 @@
// by John Friend, https://github.com/jfriend00/docReady
// MIT License
(function(funcName, baseObj) {
"use strict";
// The public function name defaults to window.docReady
// but you can modify the last line of this function to pass in a different object or method name
// if you want to put them in a different namespace and those will be used instead of
// window.docReady(...)
funcName = funcName || "docReady";
baseObj = baseObj || window;
var readyList = [];
var readyFired = false;
var readyEventHandlersInstalled = false;
(function (funcName, baseObj) {
'use strict'
// The public function name defaults to window.docReady
// but you can modify the last line of this function to pass in a different object or method name
// if you want to put them in a different namespace and those will be used instead of
// window.docReady(...)
funcName = funcName || 'docReady'
baseObj = baseObj || window
let readyList = []
let readyFired = false
let readyEventHandlersInstalled = false
// call this when the document is ready
// this function protects itself against being called more than once
function ready() {
if (!readyFired) {
// this must be set to true before we start calling callbacks
readyFired = true;
for (var i = 0; i < readyList.length; i++) {
// if a callback here happens to add new ready handlers,
// the docReady() function will see that it already fired
// and will schedule the callback to run right after
// this event loop finishes so all handlers will still execute
// in order and no new ones will be added to the readyList
// while we are processing the list
readyList[i].fn.call(window, readyList[i].ctx);
}
// allow any closures held by these functions to free
readyList = [];
}
}
// call this when the document is ready
// this function protects itself against being called more than once
function ready () {
if (!readyFired) {
// this must be set to true before we start calling callbacks
readyFired = true
for (let i = 0; i < readyList.length; i++) {
// if a callback here happens to add new ready handlers,
// the docReady() function will see that it already fired
// and will schedule the callback to run right after
// this event loop finishes so all handlers will still execute
// in order and no new ones will be added to the readyList
// while we are processing the list
readyList[i].fn.call(window, readyList[i].ctx)
}
// allow any closures held by these functions to free
readyList = []
}
}
function readyStateChange() {
if ( document.readyState === "complete" ) {
ready();
}
}
function readyStateChange () {
if (document.readyState === 'complete') {
ready()
}
}
// This is the one public interface
// docReady(fn, context);
// the context argument is optional - if present, it will be passed
// as an argument to the callback
baseObj[funcName] = function(callback, context) {
if (typeof callback !== "function") {
throw new TypeError("callback for docReady(fn) must be a function");
}
// if ready has already fired, then just schedule the callback
// to fire asynchronously, but right away
if (readyFired) {
setTimeout(function() {callback(context);}, 1);
return;
} else {
// add the function and context to the list
readyList.push({fn: callback, ctx: context});
}
// if document already ready to go, schedule the ready function to run
// IE only safe when readyState is "complete", others safe when readyState is "interactive"
if (document.readyState === "complete" || (!document.attachEvent && document.readyState === "interactive")) {
setTimeout(ready, 1);
} else if (!readyEventHandlersInstalled) {
// otherwise if we don't have event handlers installed, install them
if (document.addEventListener) {
// first choice is DOMContentLoaded event
document.addEventListener("DOMContentLoaded", ready, false);
// backup is window load event
window.addEventListener("load", ready, false);
} else {
// must be IE
document.attachEvent("onreadystatechange", readyStateChange);
window.attachEvent("onload", ready);
}
readyEventHandlersInstalled = true;
}
}
})("docReady", window);
// This is the one public interface
// docReady(fn, context);
// the context argument is optional - if present, it will be passed
// as an argument to the callback
baseObj[funcName] = function (callback, context) {
if (typeof callback !== 'function') {
throw new TypeError('callback for docReady(fn) must be a function')
}
// if ready has already fired, then just schedule the callback
// to fire asynchronously, but right away
if (readyFired) {
setTimeout(function () { callback(context) }, 1)
return
} else {
// add the function and context to the list
readyList.push({ fn: callback, ctx: context })
}
// if document already ready to go, schedule the ready function to run
// IE only safe when readyState is "complete", others safe when readyState is "interactive"
if (document.readyState === 'complete' || (!document.attachEvent && document.readyState === 'interactive')) {
setTimeout(ready, 1)
} else if (!readyEventHandlersInstalled) {
// otherwise if we don't have event handlers installed, install them
if (document.addEventListener) {
// first choice is DOMContentLoaded event
document.addEventListener('DOMContentLoaded', ready, false)
// backup is window load event
window.addEventListener('load', ready, false)
} else {
// must be IE
document.attachEvent('onreadystatechange', readyStateChange)
window.attachEvent('onload', ready)
}
readyEventHandlersInstalled = true
}
}
})('docReady', window)
// modify this previous line to pass in your own method name
// and object for the method to be attached to
@@ -1,36 +1,34 @@
/*global django*/
var roundTo = function (n, digits) {
if (digits === undefined) {
digits = 0;
}
/* global django */
let roundTo = function (n, digits) {
if (digits === undefined) {
digits = 0
}
var multiplicator = Math.pow(10, digits);
n = parseFloat((n * multiplicator).toFixed(11));
return Math.round(n) / multiplicator;
};
let multiplicator = Math.pow(10, digits)
n = parseFloat((n * multiplicator).toFixed(11))
return Math.round(n) / multiplicator
}
let floatformat = function (val, places) {
'use strict'
if (places === undefined) {
places = 2
}
if (typeof val === 'string') {
val = parseFloat(val)
}
let parts = roundTo(val, places).toFixed(places).split('.')
if (places === 0) {
return parts[0]
}
parts[0] = parts[0].replace(new RegExp('\\B(?=(\\d{' + django.get_format('NUMBER_GROUPING') + '})+(?!\\d))', 'g'), django.get_format('THOUSAND_SEPARATOR'))
return parts[0] + django.get_format('DECIMAL_SEPARATOR') + parts[1]
}
var floatformat = function (val, places) {
"use strict";
if (places === undefined) {
places = 2;
}
if (typeof val === "string") {
val = parseFloat(val);
}
var parts = roundTo(val, places).toFixed(places).split(".");
if (places === 0) {
return parts[0];
}
parts[0] = parts[0].replace(new RegExp("\\B(?=(\\d{" + django.get_format("NUMBER_GROUPING") + "})+(?!\\d))", "g"), django.get_format("THOUSAND_SEPARATOR"));
return parts[0] + django.get_format("DECIMAL_SEPARATOR") + parts[1];
};
var autofloatformat = function (val, places) {
"use strict";
if (val == roundTo(val, 0)) {
places = 0;
}
return floatformat(val, places);
};
let autofloatformat = function (val, places) {
'use strict'
if (val == roundTo(val, 0)) {
places = 0
}
return floatformat(val, places)
}
File diff suppressed because it is too large Load Diff