// @ts-check
import { isHTMLElement, maybe, ensure } from '../../../shared/js/typeAssertions';
(function (shoptet) {
/**
* This function replaces decimal separator of given value with a dot to make it a valid float.
* @param {string | number} value a value to be converted
* @returns {number}
*/
function toFloat(value) {
return parseFloat(String(value).replace(shoptet.config.decSeparator, '.'));
}
/**
* This function converts a number to a localized float.
* @param {number} value a number to be converted
* @param {number} [decimals] number of decimal places (optional)
* @param {boolean} [trim] True if trailing zeros should be removed (optional)
* @returns {string}
*/
function toLocaleFloat(value, decimals, trim) {
let finalValue = String(value);
if (typeof value === 'number') {
finalValue = value.toFixed(typeof decimals === 'undefined' ? 0 : decimals);
if (trim && finalValue.includes('.')) {
finalValue = finalValue.replace(/\.?0*$/, '');
}
return finalValue.replace('.', shoptet.config.decSeparator);
}
return finalValue;
}
/**
* This function returns a character that is used as a decimal separator.
* @param {string} [decimalSeparator] separator of decimals (optional)
* @returns {string}
*/
function resolveDecimalSeparator(decimalSeparator) {
if (typeof decimalSeparator !== 'undefined') {
return decimalSeparator;
}
return shoptet.config.decSeparator;
}
/**
* This function returns a character that is used as a thousand separator.
* @param {string} [thousandSeparator] separator of thousands (optional)
* @returns {string}
*/
function resolveThousandSeparator(thousandSeparator) {
if (typeof thousandSeparator !== 'undefined') {
return thousandSeparator;
}
return shoptet.config.thousandSeparator;
}
/**
* This function returns a number of decimal places.
* @param {number} [decimalPlaces] number of decimal places (optional)
* @returns {number}
*/
function resolveDecimalPlaces(decimalPlaces) {
if (typeof decimalPlaces !== 'undefined') {
if (!isNaN(decimalPlaces)) {
return Math.abs(decimalPlaces);
}
}
if (!isNaN(shoptet.config.decPlaces)) {
return Math.abs(shoptet.config.decPlaces);
}
return 0;
}
/**
* This function returns a currency symbol.
* @param {string} [symbol] symbol or code of currency (optional)
* @returns {string}
*/
function resolveCurrencySymbol(symbol) {
if (typeof symbol !== 'undefined') {
return symbol;
}
return shoptet.config.currencySymbol;
}
/**
* This function returns a boolean value that determines if the currency symbol is located left to the number.
* @param {boolean} [symbolPositionLeft] True to place the symbol left to the number (optional)
* @returns {boolean}
*/
function resolveCurrencySymbolPosition(symbolPositionLeft) {
if (typeof symbolPositionLeft !== 'undefined') {
return symbolPositionLeft;
}
return Boolean(parseInt(shoptet.config.currencySymbolLeft));
}
/**
* This function formats a number based on the backend settings. If you omit all arguments, default values will be used.
* @param {number} [decimalPlaces] number of decimal places (optional)
* @param {string} [decimalSeparator] separator of decimals (optional)
* @param {string} [thousandSeparator] separator of thousands (optional)
* @returns {string}
*/
function formatNumber(decimalPlaces, decimalSeparator, thousandSeparator) {
let number = this;
let decSep, decPlaces;
const thSep = resolveThousandSeparator(thousandSeparator);
if (!Number.isInteger(number.valueOf())) {
decSep = resolveDecimalSeparator(decimalSeparator);
decPlaces = resolveDecimalPlaces(decimalPlaces);
} else {
decSep = 0;
decPlaces = 0;
}
const s = number < 0 ? '-' : '';
const i = String(parseInt((number = Math.abs(+number || 0).toFixed(decPlaces))));
const j = i.length > 3 ? i.length % 3 : 0;
return (
s +
(j ? i.slice(0, j) + thSep : '') +
i.slice(j).replace(/(\d{3})(?=\d)/g, '$1' + thSep) +
(decPlaces
? decSep +
Math.abs(number - Number(i))
.toFixed(decPlaces)
.slice(2)
: '')
);
}
/**
* Format currency the same way as on backend. If you omit all arguments, default values of currency will be used.
*
* @param {string} [currencySymbol] symbol or code of currency (optional)
* @param {boolean} [currencyPositionLeft] whether the symbol is located left to the number (optional)
* @param {number} [decimalPlaces] number of decimal places (optional)
* @param {string} [decimalSeparator] separator of decimals (optional)
* @param {string} [thousandSeparator] separator of thousands (optional)
*/
function formatAsCurrency(currencySymbol, currencyPositionLeft, decimalPlaces, decimalSeparator, thousandSeparator) {
const number = this;
const symbol = resolveCurrencySymbol(currencySymbol);
const positionLeft = resolveCurrencySymbolPosition(currencyPositionLeft);
return (
(positionLeft ? symbol : '') +
number.ShoptetFormatNumber(decimalPlaces, decimalSeparator, thousandSeparator) +
(!positionLeft ? ' ' + symbol : '')
).trim();
}
/**
* This function rounds the number to the nearest 5 (for Slovak market).
* @param {number} price Price to be rounded
* @returns {number}
*/
function roundForSk(price) {
if (price === 0) {
return 0.0;
}
if (Math.abs(price) <= 0.02) {
return (0.05 * price) / Math.abs(price);
}
return (Math.round((price * 100) / 5) / 100) * 5;
}
/**
* This function rounds the price to the nearest 5 (for Hungarian market).
* @param {number} price Price to be rounded
* @returns {number}
*/
function roundForHu(price) {
return Math.round(price / 5) * 5;
}
/**
* This function rounds the number to the nearest value based on the document rounding mode.
* @param {number} [rounding] The rounding mode (optional)
* @param {number} [documentPriceDecimalPlaces] The number of decimal places (optional)
* @returns {number}
* @see PriceHelper.php::roundForDocumentWithMode()
*/
function roundForDocument(
rounding = Number(shoptet.config.documentsRounding),
documentPriceDecimalPlaces = Number(shoptet.config.documentPriceDecimalPlaces)
) {
const number = this;
const pow = Math.pow(10, Number(documentPriceDecimalPlaces));
switch (Number(rounding)) {
case 1:
return Math.ceil(number * pow) / pow;
case 2:
return Math.floor(number * pow) / pow;
case 3:
return Math.round(number * pow) / pow;
case 4:
return roundForHu(number);
case 5:
return roundForSk(number);
case 6:
return Math.round(number);
default:
return number;
}
}
/**
* This function resolves minimum amount based on decimal places.
* @param {number} decimals Amount of decimal places
* @returns {number}
*/
function resolveMinimumAmount(decimals) {
switch (decimals) {
case 1:
return 0.1;
case 2:
return 0.01;
case 3:
return 0.001;
default:
return 1;
}
}
/**
* This function checks if the device is a touch device.
* @returns {boolean}
*/
function isTouchDevice() {
const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
if ('ontouchstart' in window || (window.DocumentTouch && document instanceof DocumentTouch)) {
return true;
}
const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
return window.matchMedia(query).matches;
}
/**
* This function enables the local preview of the update with the given code for the next year.
* @param {string} updateCode
*/
function enableUpdatePreview(updateCode) {
shoptet.cookie.create(`update_management_preview_${updateCode}`, 1, { years: 1 });
window.location.reload();
}
$('html').on('click', function (e) {
if (!$(e.target).is('.decrease, .increase, .remove-pcs, .add-pcs, .quantity-discounts__item')) {
if ($('.tooltip').length) {
shoptet.variantsCommon.hideQuantityTooltips();
}
}
});
$('.cart-widget, .product').on('mouseleave', function () {
if ($('.tooltip').length) {
shoptet.variantsCommon.hideQuantityTooltips();
}
});
document.addEventListener('ShoptetCartUpdated', function () {
if ($('.tooltip').length) {
shoptet.variantsCommon.hideQuantityTooltips();
}
});
Number.prototype.ShoptetFormatNumber = formatNumber;
Number.prototype.ShoptetFormatAsCurrency = formatAsCurrency;
Number.prototype.ShoptetRoundForDocument = roundForDocument;
shoptet.helpers = shoptet.helpers || {};
shoptet.scripts.libs.helpers.forEach(function (fnName) {
var fn = eval(fnName);
shoptet.scripts.registerFunction(fn, 'helpers');
});
shoptet.helpers.isApplePayAvailable = () => {
shoptet.dev.deprecated('2025-12-31', 'shoptet.helpers.isApplePayAvailable()', 'shoptet.layout.showApplePay()');
return shoptet.layout.showApplePay();
};
})(shoptet);