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.