1$(function () { 2 var financeMonthly, financeCash, financeTime, financeRest, financeRate, financeEffectiveRate, financeStart, financeFee, financeRemaining; 3 var sliderCashValue, sliderTimeValue, sliderRestValue, sliderRemainingValue, sliderInterestRateValue; 4 var minimumCash, maxRepaymentMonths, minRepaymentMonths, interestRate, startCost, administrationFee, carPrice, carYear, maxRestValue, minimumRemainingPercentage, maximumRemainingPercentage, interestRateMin, interestRateMax; 5 var maxRemainingAmountMonths, restValueEnabled = false; 6 7 var inCalc = false; 8 9 function calculateMonthlyCost(loanAmount, futureValue = 0) { 10 if (loanAmount <= 0) { 11 return 0; 12 } 13 var periodRate = (interestRate / 100.0) / 12.0; 14 15 16 17 if (periodRate === 0) { 18 return Math.round((loanAmount - futureValue) / sliderTimeValue); 19 } 20 21 try { 22 var totalrate = Math.pow((1.0 + periodRate), sliderTimeValue); 23 // Standard PMT formula with future value: 24 // PMT = (PV à r à (1+r)^n - FV à r) / ((1+r)^n - 1) 25 var cost = (loanAmount * periodRate * totalrate - futureValue * periodRate) / (totalrate - 1.0); 26 return cost > 0 ? Math.round(cost) : 0; 27 } catch (e) { 28 return 0; 29 } 30 } 31 32 // function calculateMaxRest() { 33 //// var carAgeInMonths = ((new Date().getFullYear() - carYear) * 12) + sliderTimeValue; 34 //// if (carAgeInMonths > 18) { 35 //// return 0; 36 //// } 37 38 // var maxRest = 0; 39 // 40 // switch (sliderTimeValue) { 41 // case 12: return 80; 42 // case 24: return 65; 43 // case 36: return 50; 44 // case 48: return 40; 45 // case 60: return 30; 46 // case 72: return 20; 47 // case 84: return 10; 48 // } 49 50 // return maxRest; 51 // } 52 53 function calculate() { 54 55 if (sliderCashValue > carPrice) { 56 sliderCashValue = carPrice; 57 } 58 59 if (sliderTimeValue > maxRepaymentMonths) { 60 sliderTimeValue = maxRepaymentMonths; 61 } 62 63 64 if (sliderRemainingValue > maximumRemainingPercentage) { 65 sliderRemainingValue = maximumRemainingPercentage; 66 } 67 if (sliderInterestRateValue > interestRateMax) { 68 sliderInterestRateValue = interestRateMax; 69 } 70 interestRate = sliderInterestRateValue; 71 financeRate = interestRate; 72 financeStart = startCost; 73 financeFee = administrationFee; 74 financeTime = sliderTimeValue; 75 financeCash = sliderCashValue; 76 financeRemaining = sliderRemainingValue; 77 const residualValue = carPrice * (parseFloat(sliderRemainingValue) / 100); 78 const loanAmount = carPrice - sliderCashValue; 79 financeMonthly = calculateMonthlyCost(loanAmount, residualValue); 80 81 // var maxRestValue = calculateMaxRest(); 82 83 84 // financeRest = parseInt(carPrice * (sliderRestValue / 100)); 85 // 86 // while (financeRest + sliderCashValue > carPrice) { 87 // sliderRestValue -= 1; 88 // financeRest = parseInt(carPrice * (sliderRestValue / 100)); 89 // } 90 financeEffectiveRate = ((Math.pow((1 + (interestRate / 100.0) / 12), 12) - 1) * 100).toFixed(2); 91 //var extra = financeStart / parseInt(sliderTimeValue) + parseInt(financeFee); 92 //console.log("extra=" + extra + " amount=" + (parseInt(carPrice) - parseInt(sliderCashValue)) + " upplaggingsavgif=" + financeStart / parseInt(sliderTimeValue)); 93 94 //var addition = parseInt(extra) / parseInt(financeMonthly) * 100; 95 96 //financeEffectiveRate = (addition + ((Math.pow((1 + (interestRate / 100.0) / 12), 12) - 1) * 100)).toFixed(2); 97 } 98 99 function refreshDisplay() { 100 $('#FinanceMonthly').text(formatMoneyAmountWithSeparator(financeMonthly) + " kr/mån"); 101 //$('#FinanceCash').text(financeCash + " kr"); 102 $('#FinanceTime').text(financeTime + " mån"); 103 $('#FinanceRest').text(formatMoneyAmountWithSeparator(financeRest) + " kr"); 104 $('#FinanceRate').text(financeRate + " %"); 105 //$('#FinanceEffectiveRate').text(financeEffectiveRate + " %"); 106 $('#FinanceStart').text(formatMoneyAmountWithSeparator(financeStart) + " kr"); 107 $('#FinanceFee').text(formatMoneyAmountWithSeparator(financeFee) + " kr"); 108 109 $('#SliderCashValue').text(formatMoneyAmountWithSeparator(sliderCashValue) + " kr"); 110 $('#SliderTimeValue').text(sliderTimeValue + " mån"); 111 $('#sliderInterestValue').text(sliderInterestRateValue + " %");
112 let remainingAmount = parseInt(sliderRemainingValue) / 100 * carPrice; 113 $('#FinanceRemainingValue').text(sliderRemainingValue + " % (" + formatMoneyAmountWithSeparator(Math.round(remainingAmount)) + " kr)" ); 114 $('#FinanceRemainingAmountMoneyValue').text(formatMoneyAmountWithSeparator(Math.round(remainingAmount)) + " kr") 115 116 // $('#sliderCash').val(sliderCashValue).change(); 117 // $('#sliderTime').val(sliderTimeValue).change(); 118 // $('#sliderRest').val(sliderRestValue).change(); 119 120 // $('#sliderRest').attr('max', maxRestValue); 121 } 122 123 function sliderCashChanged(value) { 124 if (inCalc) return true; 125 inCalc = true; 126 127 sliderCashValue = value; 128 129 calculate(); 130 refreshDisplay(); 131 132 inCalc = false; 133 } 134 135 function sliderTimeChanged(value) { 136 if (inCalc) return true; 137 inCalc = true; 138 sliderTimeValue = value; 139 140 calculate(); 141 refreshDisplay(); 142 143 inCalc = false; 144 } 145 146 function sliderRemainingValueChanged(value) { 147 if (inCalc) return true; 148 inCalc = true; 149 sliderRemainingValue = value; 150 151 calculate(); 152 refreshDisplay(); 153 154 inCalc = false; 155 } 156 157 function sliderInterestRateValueChanged(value) { 158 if (inCalc) return true; 159 inCalc = true; 160 sliderInterestRateValue = value; 161 162 calculate(); 163 refreshDisplay(); 164 165 inCalc = false; 166 } 167 168 // function sliderRestChanged(value) { 169 // if (inCalc) return true; 170 // inCalc = true; 171 172 // sliderRestValue = value; 173 174 // calculate(); 175 // refreshDisplay(); 176 177 // inCalc = false; 178 // } 179 180 function applyRestValueToggle(enabled) { 181 restValueEnabled = enabled; 182 183 var currentMaxMonths = enabled ? maxRemainingAmountMonths : maxRepaymentMonths; 184 185 $('#sliderTime').attr('max', currentMaxMonths); 186 if (sliderTimeValue > currentMaxMonths) { 187 sliderTimeValue = currentMaxMonths; 188 $('#sliderTime').val(currentMaxMonths); 189 } 190 $("#sliderTime").rangeslider('update', true); 191 if (enabled) { 192 $('.restValueSection').show(); 193 sliderRemainingValue = maximumRemainingPercentage; 194 $('#sliderRemaining').val(maximumRemainingPercentage); 195 $("#sliderRemaining").rangeslider('update', true); 196 } else { 197 $('.restValueSection').hide(); 198 sliderRemainingValue = 0; 199 } 200 201 calculate(); 202 refreshDisplay(); 203 } 204 205 function initialize() { 206 maxRepaymentMonths = $('#FinanceMaxRepaymentMonths').val(); 207 minRepaymentMonths = $('#FinanceMinRepaymentMonths').val(); 208 interestRate = $('#FinanceInterestRate').val(); 209 interestRateMin = $('#FinanceInterestRateMin').val(); 210 interestRateMax = $('#FinanceInterestRateMax').val(); 211 startCost = $('#FinanceStartCost').val(); 212 administrationFee = $('#FinanceAdministrationFee').val(); 213 carPrice = parseInt($('#FinanceCarPrice').val()); 214 carYear = parseInt($('#FinanceCarYear').val()); 215 minimumCash = (parseInt($('#FinanceMinimumCash').val()) / 100) * carPrice; 216 minimumRemainingPercentage = $('#FinanceMinimumRemainingPercentage').val(); 217 maximumRemainingPercentage = $('#FinanceMaximumRemainingPercentage').val(); 218 219 // Default to 50 if not set 220 if (!maximumRemainingPercentage || maximumRemainingPercentage === '0') { 221 maximumRemainingPercentage = '50'; 222 } 223 224 if (!interestRateMax || interestRateMax === '0'){ 225 interestRateMax = interestRate; 226 } 227 228 // Get max months for remaining amount, default to 36 if empty or 0 229 var rawMaxRemainingMonths = $('#FinanceMaximumRemainingAmountMonths').val(); 230 maxRemainingAmountMonths = (rawMaxRemainingMonths && parseInt(rawMaxRemainingMonths) > 0) ? parseInt(rawMaxRemainingMonths) : 36; 231 232 $('#sliderCash').attr('min', minimumCash); 233 $('#sliderCash').attr('max', carPrice); 234 $('#sliderCash').attr('step', 1000); 235 236 $('#sliderTime').attr('min', minRepaymentMonths);
237 $('#sliderTime').attr('max', maxRemainingAmountMonths); 238 $('#sliderTime').attr('step', 12); 239 $('#sliderTime').val(maxRemainingAmountMonths); 240 241 $('#sliderRemaining').attr('min', minimumRemainingPercentage); 242 $('#sliderRemaining').attr('max', maximumRemainingPercentage); 243 $('#sliderRemaining').attr('step', 0.1); 244 $('#sliderRemaining').val(maximumRemainingPercentage); 245 246 $('#sliderInterestRate').attr('min', interestRateMin); 247 $('#sliderInterestRate').attr('max', interestRateMax); 248 $('#sliderInterestRate').attr('step', 0.01); 249 $('#sliderInterestRate').val(interestRate); 250 251 $("#sliderCash").rangeslider({ polyfill: false, onSlide: function (position, value) { sliderCashChanged(value) } }); 252 $("#sliderTime").rangeslider({ polyfill: false, onSlide: function (position, value) { sliderTimeChanged(value) } }); 253 $("#sliderRemaining").rangeslider({ polyfill: false, onSlide: function (position, value) { sliderRemainingValueChanged(value) } }); 254 $("#sliderInterestRate").rangeslider({ polyfill: false, onSlide: function (position, value) { sliderInterestRateValueChanged(value) } }); 255 256 // Toggle defaults to ON 257 sliderRemainingValue = maximumRemainingPercentage; 258 $('#toggleRestValue').prop('checked', true); 259 $('.restValueSection').show(); 260 261 $('#toggleRestValue').on('change', function () { 262 applyRestValueToggle($(this).is(':checked')); 263 }); 264 265 sliderTimeChanged(maxRemainingAmountMonths); 266 } 267 268 initialize(); 269 refreshDisplay(); 270}) 271 272function formatMoneyAmountWithSeparator(text, separator = ' ', numberOfCharsInASector = 3){ 273 274 if (text === undefined) { 275 return ''; 276 } 277 text = text.toString() 278 if (text.length <= 3){ 279 return text; 280 } 281 282 let result = '';
283 let currentSectionChars = 0; 284 for (let i = text.length - 1; i >= 0; i--) { 285 result = text[i] + result; 286 287 currentSectionChars++; 288 if (i > 0 && currentSectionChars % numberOfCharsInASector === 0) { 289 result = separator + result; 290 currentSectionChars = 0; 291 } 292 } 293 return result; 294}
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.