PageSourceSearch

https://goandgrow.eu/wp-content/themes/bricks-child/custom-functions/investor-js/fundCalculator.js

js goandgrow.eu collected 2026-10-01 15:05:31 UTC 16,979 bytes, 416 lines download raw bytes

1function fundCalculator(percent) {
2    var self = this,
3        startingAmountInput = $('input[name="StartingAmount"]'),
4        monthlyAmountInput = $('input[name="MonthlyAmount"]'),
5        targetAmountInput = $('input[name="TargetAmount"]'),
6        investPeriodInput = $('input[name="InvestPeriod"]'),
7        contributionPeriodInput = $('select[name="Contributions"]'),
8        targetInput = $('input[name="Target"]');
9
10    self.percent = percent;
11    self.init = function () {
12        self.initSliders();
13    };
14
15    self.trackSlider = function () {
16        var path = window.location.pathname;
17
18        switch (true) {
19            case (path.indexOf("gogrow/changegoal") > -1):
20                SendGGChangePurpopseSliderTouchedData();
21                break;
22            case (path.indexOf("identification/unlimitedgoal") > -1):
23                SendFlowInvestmentGoalSliderTouchedData();
24                break;
25            case (path.indexOf("gogrow/addunlimitedgoal") > -1):
26                SendGGUGoalSliderTouchedData();
27                break;
28        }
29    };
30
31    self.setInvestPeriod = function (val) { investPeriodInput.val(val); };
32    self.setMonthlyAmount = function (val) { monthlyAmountInput.val(val); };
33    self.setTargetAmount = function (val) { targetAmountInput.val(val); };
34    self.setStartingAmount = function (val) { startingAmountInput.val(val); };
35    self.setContributionPeriod = function (val) { contributionPeriodInput.val(val); };
36    self.setTarget = function (val) { targetInput.val(val); };
37
38    self.getInvestPeriod = function () { return parseInt(investPeriodInput.val()); };
39    self.getMonthlyAmount = function () { return parseInt(monthlyAmountInput.val()); };
40    self.getTargetAmount = function () { return parseInt(targetAmountInput.val()); };
41    self.getStartingAmount = function () { return parseInt(startingAmountInput.val()); };
42    self.getContributionPeriod = function () { return contributionPeriodInput.val(); };
43    self.getTarget = function () { return targetInput.val(); };
44
45    self.initWithoutSliders = function (validInputCallback) {
46        var regex = /[^0-9\.\,]/g;
47        $('.validatable-input').on("keyup", function (e) {
48            if (e.target.value.length === 0) return;
49            if (regex.test(e.target.value)) {
50                e.target.value = e.target.value.replace(regex, '');
51                return;
52            }
53
54            var inputValue = parseInt(e.target.value.replace(',', '.'), 10),
55                minVal = e.target.dataset.minVal,
56                maxVal = e.target.dataset.maxVal,
57                errorMessage = e.target.dataset.errorMessage;
58
59            self.validateNumericInput(errorMessage ? self.getErrorTip(errorMessage) : null, parseInt(minVal, 10), parseInt(maxVal, 10), inputValue, e.target);
60            if (validInputCallback) validInputCallback();
61        });
62    };
63
64    self.validateNumericInput = function (errorNode, minVal, maxVal, inputValue, target) {
65        if (Number.isNaN(inputValue) || inputValue < minVal || inputValue > maxVal) {
66            if (inputValue < minVal) target.value = minVal;
67            if (inputValue > maxVal) target.value = maxVal;
68            if (errorNode) {
69                target.parentNode.appendChild(errorNode);
70                setTimeout(function () { target.parentNode.removeChild(errorNode); }, 3000);
71            }
72        }
73    }
74
75    self.getErrorTip = function (errorMessage) {
76        var errContainer = document.createElement('div');
77        errContainer.className = 'validation-error-container';
78
79        var errMsgContainer = document.createElement('div');
80        errMsgContainer.className = 'validation-error-message';
81        errMsgContainer.innerHTML = errorMessage;
82        errContainer.appendChild(errMsgContainer);
83
84        var errMsgArrow = document.createElement('div');
85        errMsgArrow.className = 'validation-error-arrow';
86        errContainer.appendChild(errMsgArrow);
87
88        return errContainer;
89    }
90
91    self.initSliders = function () {
92        var startingAmountRange = document.getElementById('startingAmountRange'),
93            monthlyAmountRange = document.getElementById('monthlyAmountRange'),
94            investPeriodRange = document.getElementById('investPeriodRange'),
95
96            moneyFormat = wNumb({
97                decimals: 0,
98                thousand: ' ',
99                mark: ','
100            }),
101            yearsFormat = wNumb({
102                decimals: 0
103            }),
104            pips = {
105                mode: 'count',
106                values: 2,
107                density: 100,
108                format: moneyFormat
109            };
110
111        noUiSlider.create(startingAmountRange,
112            {
113                start: self.getStartingAmount(),
114                range: {
115                    'min': 0,
116                    '25%': 1000,
117                    '50%': 25000,
118                    '75%': 75000,
119                    'max': 100000
120                },
121                connect: [true, false],
122                step: 5,
123                pips: pips,
124                format: moneyFormat
125            });
126
127        startingAmountRange.noUiSlider.on('update', function (values, handle) {
128            var form = $(startingAmountRange).parents('form');
129            form.find('input[name="StartingAmount"]').val(values[handle].replace(' ', '').replace('€', ''));
130            form.find('input[name="StartingAmountVisible"]').val(values[handle]);
131            form.find('.js-starting-amount-placeholder').html(values[handle]);
132
133            self.calculatePotentialGain();
134            self.calculateYourContribution();
135            self.calculateTotalValue();
136        });
137
138        startingAmountRange.noUiSlider.on('end', function () {
139            self.trackSlider();
140        });
141
142        $(document).on('change', 'input[name="StartingAmountVisible"]', function () {
143            startingAmountRange.noUiSlider.set($(this).val());
144        });
145
146        noUiSlider.create(monthlyAmountRange,
147            {
148                start: self.getMonthlyAmount(),
149                range: {
150                    'min': 0,
151                    '25%': 500,
152                    '50%': 2500,
153                    '75%': 7500,
154                    'max': 10000
155                },
156                connect: [true, false],
157                step: 5,
158                pips: pips,
159                format: moneyFormat
160            });
161
162        monthlyAmountRange.noUiSlider.on('update', function (values, handle) {
163            var form = $(monthlyAmountRange).parents('form');
164            form.find('input[name="MonthlyAmount"]').val(values[handle].replace(' ', '').replace('€', ''));
165            form.find('input[name="MonthlyAmountVisible"]').val(values[handle]);
166            form.find('.js-monthly-amount-placeholder').html(values[handle]);
167
168            self.calculatePotentialGain();
169            self.calculateYourContribution();
170            self.calculateTotalValue();
171        });
172
173        monthlyAmountRange.noUiSlider.on('end', function () {
174            self.trackSlider();
175        });
176
177        $(document).on('change', 'input[name="MonthlyAmountVisible"]', function () {
178            monthlyAmountRange.noUiSlider.set($(this).val());
179        });
180
181        noUiSlider.create(investPeriodRange,
182            {
183                start: self.getInvestPeriod(),
184                range: {
185                    min: 1,
186                    max: 20
187                },
188                connect: [true, false],
189                pips: {
190                    mode: 'count',
191                    values: 2,
192                    density: 100,
193                    format: yearsFormat
194                },
195                format: yearsFormat
196            });
197
198        investPeriodRange.noUiSlider.on('update', function (values, handle) {
199            var form = $(investPeriodRange).parents('form');
200            form.find('input[name="InvestPeriod"]').val(values[handle].split(' ')[0]); //cut years off
201            form.find('input[name="InvestPeriodVisible"]').val(values[handle]);
202            form.find('.js-invest-period-placeholder').html(values[handle]);
203
204            self.calculatePotentialGain();
205            self.calculateYourContribution();
206            self.calculateTotalValue();
207        });
208
209        investPeriodRange.noUiSlider.on('end', function () {
210            self.trackSlider();
211        });
212
213        $(document).on('change', 'input[name="InvestPeriodVisible"]', function () {
214            investPeriodRange.noUiSlider.set($(this).val());
215        });
216    };
217
218    self.calculatePotentialGain = function () {
219        firstDeposit = self.getStartingAmount();
220        monthlyDeposit = self.getMonthlyAmount();
221        period = self.getInvestPeriod();
222        contributionPeriod = self.getContributionPeriod();
223        if (isNaN(contributionPeriod))
224            contributionPeriod = 12;
225
226        var compoundedPerYear = 12,
227            moneyFormat = wNumb({
228                decimals: 0,
229                thousand: ' ',
230                postfix: ' €',
231                mark: ','
232            }),
233            deposits = firstDeposit + period * contributionPeriod * monthlyDeposit,
234            xirr = Math.pow(1 + (self.percent / 100), 1 / contributionPeriod) - 1,
235            futureValueOfPrincipal = firstDeposit * Math.pow((1 + xirr), compoundedPerYear * period),
236            futureValueOfMonthlyContributions = monthlyDeposit * (Math.pow((1 + xirr), compoundedPerYear * period) - 1) / xirr,
237            result = Math.round(futureValueOfPrincipal + futureValueOfMonthlyContributions - deposits);
238
239        $('.js-potential-gain').text(moneyFormat.to(result));
240        $('.js-potential-gain-value').val(result);
241    };
242
243    self.calculatePotentialGainOverPeriod = function (locale = null) {
244        firstDeposit = self.getStartingAmount();
245        monthlyDeposit = self.getMonthlyAmount();
246        period = self.getInvestPeriod();
247        contributionPeriod = self.getContributionPeriod();
248        customerTargetAmount = self.getTarget();
249
250        var contributePeriod = self.findContributionTimeInYear(contributionPeriod);
251
252        var compoundedPerYear = contributePeriod,
253            maxDots = 24,
254            moneyFormat = wNumb({
255                decimals: 0,
256                thousand: ' ',
257                postfix: ' €',
258                mark: ','
259            }),
260            year = new Date().getFullYear(),
261            allValues = [],
262            returnableValues = [];
263
264        // Target Amount calculations
265        var selection = $("input[name$='calculateBy']:checked").attr("id");
266        if (selection == "targetAmount") {
267
268            if (Number.isNaN(parseInt(firstDeposit))) {
269                firstDeposit = 0;
270            }
271            if (Number.isNaN(parseInt(customerTargetAmount))) {
272                customerTargetAmount = 0;
273            }
274
275            var xirr = Math.pow(1 + (self.percent / 100), 1 / contributePeriod) - 1;
276            var yearsToGo = self.findTargetYearsWithoutDepo(compoundedPerYear, xirr);
277            var accountBalanceWithoutDepo = firstDeposit * Math.pow((1 + xirr), compoundedPerYear * period);
278            var depositResults = 1 * (Math.pow((1 + xirr), compoundedPerYear * period) - 1) / xirr;
279            customerTargetAmount = customerTargetAmount - accountBalanceWithoutDepo;
280            var monthlyDepositTotalValue = depositResults;
281            // Need to deposit every period
282            var monthlyDepositOfGivenTarget = customerTargetAmount / monthlyDepositTotalValue;
283            monthlyDeposit = monthlyDepositOfGivenTarget;
284
285        } else if (selection == "contributions") {
286            if (Number.isNaN(parseInt(firstDeposit))) {
287                firstDeposit = 0;
288            }
289            if (Number.isNaN(parseInt(monthlyDeposit))) {
290                monthlyDeposit = 0;
291            }
292        }
293
294        for (let i = 0; i <= period; i++) {
295            var xirr = Math.pow(1 + (self.percent / 100), 1 / contributePeriod) - 1,
296                deposits = firstDeposit + i * contributePeriod * monthlyDeposit,
297                futureValueOfPrincipal = firstDeposit * Math.pow((1 + xirr), compoundedPerYear * i),
298                futureValueOfMonthlyContributions = monthlyDeposit * (Math.pow((1 + xirr), compoundedPerYear * i) - 1) / xirr,
299
300                result = Math.round(futureValueOfPrincipal + futureValueOfMonthlyContributions),
301                resultWithoutMonthlyDeposit = Math.round(futureValueOfPrincipal);
302
303            allValues.push({
304                year: (i + year).toString(),
305                accountBalanceWithDepo: result,
306                accountBalanceWithoutDepo: resultWithoutMonthlyDeposit,
307                withDepoTooltip: locale ? self.numberToLocale(result, locale) : moneyFormat.to(result),
308                withoutDepoTooltip: locale ? self.numberToLocale(resultWithoutMonthlyDeposit, locale) : moneyFormat.to(resultWithoutMonthlyDeposit),
309                totalGainWithDepo: result - Math.round(deposits),
310                totalGainWithoutDepo: resultWithoutMonthlyDeposit - firstDeposit,
311                yearsToGo: yearsToGo,
312                xirr: xirr,
313                monthlyDepositOfGivenTarget: monthlyDepositOfGivenTarget
314            });
315        }
316
317        if (period + 1 > maxDots) {
318            for (var i = 0; i < maxDots; i++) {
319                var yearToKeep = parseInt((period / maxDots) * i, 10) + year;
320                for (var j = 0; j < allValues.length; j++) {
321                    if (allValues[j].year === yearToKeep.toString()) {
322                        returnableValues.push(allValues[j]);
323                        break;
324                    }
325                }
326            }
327
328            if (returnableValues[returnableValues.length - 1].year !== all
328Values[allValues.length - 1].year)
329                returnableValues.push(allValues[allValues.length - 1]);
330            return returnableValues;
331        }
332
333        return allValues;
334    };
335
336    self.calculateYourContribution = function () {
337        firstDeposit = self.getStartingAmount();
338        monthlyDeposit = self.getMonthlyAmount();
339        period = self.getInvestPeriod();
340
341        var moneyFormat = wNumb({
342            decimals: 0,
343            thousand: ' ',
344            postfix: ' €',
345            mark: ','
346        });
347
348        var deposits = firstDeposit + period * 12 * monthlyDeposit;
349
350        $('.js-your-contribution').text(moneyFormat.to(deposits));
351        $('.js-your-contribution-value').val(deposits);
352    };
353
354    self.calculateTotalValue = function () {
355        yourContribution = parseInt($('.js-your-contribution-value').val());
356        potentialGain = parseInt($('.js-potential-gain-value').val());
357
358        var moneyFormat = wNumb({
359            decimals: 0,
360            thousand: ' ',
361            postfix: ' €',
362            mark: ','
363        });
364
365        var total = yourContribution + potentialGain;
366
367        $('.js-total').text(moneyFormat.to(total));
368        $('.js-total-value').val(total);
369    };
370
371    self.areInputsValid = function () {
372        investPeriodInput.css({ borderColor: Number.isNaN(self.getInvestPeriod()) ? 'red' : '#d8d8d8' });
373        monthlyAmountInput.css({ borderColor: Number.isNaN(self.getMonthlyAmount()) ? 'red' : '#d8d8d8' });
374        startingAmountInput.css({ borderColor: Number.isNaN(self.getStartingAmount()) ? 'red' : '#d8d8d8' });
375
376        return !Number.isNaN(self.getInvestPeriod()) &&
377            !Number.isNaN(self.getMonthlyAmount()) &&
378            !Number.isNaN(self.getStartingAmount());
379    };
380
381    self.numberToLocale = function (number, locale) {
382        return (number && locale)
383            ? number.toLocaleString(locale, { style: 'currency', currency: 'EUR', minimumFractionDigits: 0, maximumFractionDigits: 0 })
384            : "0 €";
385    }
386    self.findContributionTimeInYear = function (period) {
387        if (period === 'Monthly') {
388            return 12;
389        }
390        else if (period === 'Quarterly') {
391            return 4;
392        }
393        else if (period === 'Weekly') {
394            return 52;
395        }
396        else if (period === 'Bi-weekly') {
397            return 26;
398        }
399        return 0;
400    }
401    self.findTargetYearsWithoutDepo = function (compoundedPerYear, xirr) {
402        var tempFirstDeposit = firstDeposit;
403        if (tempFirstDeposit == 0)
404            tempFirstDeposit = 1;
405        var years = 0,
406            targetRemaning = customerTargetAmount / tempFirstDeposit;
407
408        while (targetRemaning > 1) {
409            years++;
410            targetRemaning /= (1 + xirr);
411        }
412
413        var yearsToGo = Math.ceil(years / compoundedPerYear);
414        return yearsToGo;
415    }
416}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.