Odoo18-Base/addons/website_payment/static/src/snippets/s_donation/000.js
2025-03-10 11:12:23 +07:00

176 lines
6.6 KiB
JavaScript

/** @odoo-module **/
import {_t} from 'web.core';
import publicWidget from 'web.public.widget';
const CUSTOM_BUTTON_EXTRA_WIDTH = 10;
publicWidget.registry.DonationSnippet = publicWidget.Widget.extend({
selector: '.s_donation',
disabledInEditableMode: false,
events: {
'click .s_donation_btn': '_onClickPrefilledButton',
'click .s_donation_donate_btn': '_onClickDonateNowButton',
'input #s_donation_range_slider': '_onInputRangeSlider',
},
/**
* @override
*/
async start() {
await this._super(...arguments);
this.$rangeSlider = this.$('#s_donation_range_slider');
this.defaultAmount = this.$target[0].dataset.defaultAmount;
if (this.$rangeSlider.length) {
this.$rangeSlider.val(this.defaultAmount);
this._setBubble(this.$rangeSlider);
}
await this._displayCurrencies();
const customButtonEl = this.el.querySelector("#s_donation_amount_input");
if (customButtonEl) {
const canvasEl = document.createElement("canvas");
const context = canvasEl.getContext("2d");
context.font = window.getComputedStyle(customButtonEl).font;
const width = context.measureText(customButtonEl.placeholder).width;
customButtonEl.style.maxWidth = `${Math.ceil(width) + CUSTOM_BUTTON_EXTRA_WIDTH}px`;
}
},
/**
* @override
*/
destroy() {
const customButtonEl = this.el.querySelector("#s_donation_amount_input");
if (customButtonEl) {
customButtonEl.style.maxWidth = "";
}
this.$target.find('.s_donation_currency').remove();
this._deselectPrefilledButtons();
this.$('.alert-danger').remove();
this._super(...arguments);
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
*/
_deselectPrefilledButtons() {
this.$('.s_donation_btn').removeClass('active');
},
/**
* @private
* @param {jQuery} $range
*/
_setBubble($range) {
const $bubble = this.$('.s_range_bubble');
const val = $range.val();
const min = $range[0].min || 0;
const max = $range[0].max || 100;
const newVal = Number(((val - min) * 100) / (max - min));
const tipOffsetLow = 8 - (newVal * 0.16); // the range thumb size is 16px*16px. The '8' and the '0.16' are related to that 16px (50% and 1% of 16px)
$bubble.contents().filter(function () {
return this.nodeType === 3;
}).replaceWith(val);
// Sorta magic numbers based on size of the native UI thumb (source: https://css-tricks.com/value-bubbles-for-range-inputs/)
$bubble[0].style.insetInlineStart = `calc(${newVal}% + (${tipOffsetLow}px))`;
},
/**
* @private
*/
_displayCurrencies() {
return this._rpc({
route: '/website/get_current_currency',
}).then((result) => {
this.currency = result;
this.$('.s_donation_currency').remove();
const $prefilledButtons = this.$('.s_donation_btn, .s_range_bubble');
_.each($prefilledButtons, button => {
const before = result.position === "before";
const $currencySymbol = document.createElement('span');
$currencySymbol.innerText = result.symbol;
$currencySymbol.classList.add('s_donation_currency', before ? "pe-1" : "ps-1");
if (before) {
$(button).prepend($currencySymbol);
} else {
$(button).append($currencySymbol);
}
});
});
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @private
*/
_onClickPrefilledButton(ev) {
const $button = $(ev.currentTarget);
this._deselectPrefilledButtons();
$button.addClass('active');
if (this.$rangeSlider.length) {
this.$rangeSlider.val($button[0].dataset.donationValue);
this._setBubble(this.$rangeSlider);
}
},
/**
* @private
*/
_onClickDonateNowButton(ev) {
if (this.editableMode) {
return;
};
this.$('.alert-danger').remove();
const $buttons = this.$('.s_donation_btn');
const $selectedButton = $buttons.filter('.active');
let amount = $selectedButton.length ? $selectedButton[0].dataset.donationValue : 0;
if (this.$target[0].dataset.displayOptions && !amount) {
if (this.$rangeSlider.length) {
amount = this.$rangeSlider.val();
} else if ($buttons.length) {
amount = parseFloat(this.$('#s_donation_amount_input').val());
let errorMessage = '';
const minAmount = this.$target[0].dataset.minimumAmount;
if (!amount) {
errorMessage = _t("Please select or enter an amount");
} else if (amount < parseFloat(minAmount)) {
const before = this.currency.position === "before" ? this.currency.symbol : "";
const after = this.currency.position === "after" ? this.currency.symbol : "";
errorMessage = _.str.sprintf(_t("The minimum donation amount is %s%s%s"), before, minAmount, after);
}
if (errorMessage) {
$(ev.currentTarget).before($('<p>', {
class: 'alert alert-danger',
text: errorMessage,
}));
return;
}
}
}
if (!amount) {
amount = this.defaultAmount;
}
const $form = this.$('.s_donation_form');
$('<input>').attr({type: 'hidden', name: 'amount', value: amount}).appendTo($form);
$('<input>').attr({type: 'hidden', name: 'currency_id', value: this.currency.id}).appendTo($form);
$('<input>').attr({type: 'hidden', name: 'csrf_token', value: odoo.csrf_token}).appendTo($form);
$('<input>').attr({type: 'hidden', name: 'donation_options', value: JSON.stringify(this.el.dataset)}).appendTo($form);
$form.submit();
},
/**
* @private
*/
_onInputRangeSlider(ev) {
this._deselectPrefilledButtons();
this._setBubble($(ev.currentTarget));
},
});
export default {
DonationSnippet: publicWidget.registry.DonationSnippet,
};