PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.21
VikAppointments Services Booking Calendar v1.2.21
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / site / assets / js / currency.js
vikappointments / site / assets / js Last commit date
charts-framework 4 days ago colorpicker 4 days ago select2 4 days ago tel 4 days ago contextmenu.js 4 days ago currency.js 4 days ago index.html 4 days ago jquery-ui.draggable.min.js 4 days ago jquery-ui.min.js 4 days ago jquery-ui.sortable.min.js 4 days ago jquery.fancybox.js 4 days ago jquery.min.js 4 days ago sortablelist.js 4 days ago statuscodes.js 4 days ago toast.js 4 days ago utils.js 4 days ago vap-emparea.js 4 days ago vikappointments.js 4 days ago
currency.js
196 lines
1 (function($, w) {
2 'use strict';
3
4 /**
5 * Class used to deal with prices.
6 *
7 * How to instantiate the singleton:
8 * VAPCurrency.getInstance('$', {
9 * position: 2, // display currency before price
10 * decimals: '.',
11 * thousands: ',',
12 * digits: 2,
13 * });
14 *
15 * How to format prices:
16 * VAPCurrency.getInstance().format(15.32);
17 * // get rid of decimals on the fly
18 * VAPCurrency.getInstance().format(15.00, 0);
19 */
20 w['VAPCurrency'] = class VAPCurrency {
21
22 /**
23 * Singleton entry-point.
24 *
25 * @see construct()
26 */
27 static getInstance(symbol, options) {
28 if (typeof VAPCurrency.instance === 'undefined' || !VAPCurrency.instance.symbol) {
29 VAPCurrency.instance = new VAPCurrency(symbol, options);
30 }
31
32 return VAPCurrency.instance;
33 }
34
35 /**
36 * Class constructor
37 *
38 * @param string symbol The currency symbol (such as €, $, £ and so on).
39 * @param array options An array of currency options:
40 * - position int The position of the currency (1 before, 2 after). In case the amount is negative
41 * the space between the currency and the amount won't be used.
42 * - decimals string The decimals separator character ("." or ",").
43 * - thousands string The thousands separator character ("," or ".").
44 * - digits int The number of decimal digits.
45 * - conversionRatio float The currency conversion ratio.
46 */
47 constructor(symbol, options) {
48 if (options === undefined) {
49 options = {};
50 }
51
52 this.symbol = symbol;
53 this.position = (options.hasOwnProperty('position') ? options.position : 1);
54 this.decimals = (options.hasOwnProperty('separator') ? options.separator : '.');
55 this.thousands = (options.hasOwnProperty('thousands') ? options.thousands : ',');
56 this.digits = (options.hasOwnProperty('digits') ? parseInt(options.digits) : 2);
57
58 this.conversionRatio = Math.abs((options.hasOwnProperty('conversionRatio') ? parseFloat(options.conversionRatio) : 1));
59 }
60
61 /**
62 * Formats the given price according to the configuration preferences.
63 *
64 * @param float price The price to format.
65 * @param int dig Temporarily overrides the number of decimal digits.
66 *
67 * @return string The formatted price.
68 */
69 format(price, dig) {
70 if (dig === undefined) {
71 dig = this.digits;
72 }
73
74 price = parseFloat(price) / this.conversionRatio;
75
76 // check whether the price is negative
77 const isNegative = price < 0;
78
79 // adjust to given decimals
80 price = Math.abs(price).toFixed(dig);
81
82 let _d = this.decimals;
83 let _t = this.thousands;
84
85 // make sure the decimal separator is a valid character
86 if (!_d.match(/[.,\s]/)) {
87 // revert to default one
88 _d = '.';
89 }
90
91 // make sure the thousands separator is a valid character
92 if (!_t.match(/[.,\s]/)) {
93 // revert to default one
94 _t = ',';
95 }
96
97 // make sure both the separators are not equals
98 if (_d == _t) {
99 _t = _d == ',' ? '.' : ',';
100 }
101
102 price = price.split('.');
103
104 price[0] = price[0].replace(/./g, function(c, i, a) {
105 return i > 0 && (a.length - i) % 3 === 0 ? _t + c : c;
106 });
107
108 if (isNegative) {
109 // re-add negative sign
110 price[0] = '-' + price[0];
111 }
112
113 if (price.length > 1) {
114 price = price[0] + _d + price[1];
115 } else {
116 price = price[0];
117 }
118
119 if (Math.abs(this.position) == 1) {
120 // do not use space in case the position is "-1"
121 return price + (this.position == 1 ? ' ' : '') + this.symbol;
122 }
123
124 // do not use space in case the position is "-2"
125 return this.symbol + (this.position == 2 ? ' ' : '') + price;
126 }
127
128 /**
129 * Safely sums 2 prices (a + b).
130 *
131 * @param float a
132 * @param float b
133 *
134 * @return The resulting sum.
135 */
136 sum(a, b) {
137 // get rid of decimals for higher precision
138 a *= Math.pow(10, this.digits);
139 b *= Math.pow(10, this.digits);
140
141 // do sum and go back to decimal
142 return (Math.round(a) + Math.round(b)) / Math.pow(10, this.digits);
143 }
144
145 /**
146 * Safely subtracts 2 prices (a - b).
147 *
148 * @param float a
149 * @param float b
150 *
151 * @return The resulting difference.
152 */
153 diff(a, b) {
154 // get rid of decimals for higher precision
155 a *= Math.pow(10, this.digits);
156 b *= Math.pow(10, this.digits);
157
158 // do difference and go back to decimal
159 return (Math.round(a) - Math.round(b)) / Math.pow(10, this.digits);
160 }
161
162 /**
163 * Safely multiplies 2 prices (a * b).
164 *
165 * @param float a
166 * @param float b
167 *
168 * @return The resulting multiplication.
169 */
170 multiply(a, b) {
171 // get rid of decimals for higher precision
172 a *= Math.pow(10, this.digits);
173 b *= Math.pow(10, this.digits);
174
175 // do multiplication and go back to decimal
176 return (Math.round(a) * Math.round(b)) / Math.pow(10, this.digits * 2);
177 }
178 }
179
180 // flag used to prevent the system from logging the same warning more than once
181 let warningShown = false;
182
183 /**
184 * Deprecated Currency instance.
185 */
186 w['Currency'] = class Currency {
187 static getInstance(symbol, options) {
188 if (!warningShown) {
189 console.warn('The Currency object is deprecated and will be removed soon. VAPCurrency should be used instead.');
190 warningShown = true;
191 }
192
193 return VAPCurrency.getInstance(symbol, options);
194 }
195 }
196 })(jQuery, window);