我的 JavaScript 无法正常工作或未连接
My JavaScript is Not working Correctly or is not connecting
我正在尝试制作一个带有直方图的 Intrest 计算器 我在网上找到了这些脚本,因为我是 javaScript 的新手。
所以我想要的输出是这样的Desired Outpyt
我得到的输出是 comming output
所以我真的需要一些帮助
第一,带有 + 和 - 符号的蓝色按钮太疯狂了。
其次,直方图没有显示。
所以请帮助我,我将不胜感激。
我已从该站点复制粘贴代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css" >
<meta charset="UTF-8">
<title>Savings Calculator</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="initial_deposit">Initial Deposit</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="initial_deposit">−</button>
</div>
<input class="form-control text-center" id="initial_deposit" type="text" name="initial_deposit" min="100" max="1000000" step="100" value="00" data-value="5000" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="initial_deposit">+</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="contribution_amount">Contributions</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="contribution_amount">−</button>
</div>
<input class="form-control text-center" id="contribution_amount" type="text" name="contribution_amount" min="0" max="10000" step="50" value="0" data-value="100" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="contribution_amount">+</button>
</div>
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_monthly" type="radio" name="contribution_period" value="12" checked>
<label class="form-check-label" for="contribution_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_annually" type="radio" name="contribution_period" value="1">
<label class="form-check-label" for="contribution_period_annually">annually</label>
</div>
</div>
<div class="form-group">
<label for="investment_timespan">Investment Time Span</label>
<div class="row">
<div class="col-md-6 col-sm-8">
<input class="form-control" id="investment_timespan" type="range" name="investment_timespan" min="2" max="50" step="1" value="5">
</div>
</div>
<span id="investment_timespan_text">5 years</span>
</div>
<div class="form-group">
<label for="estimated_return">Estimated Rate of Return</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="estimated_return">−</button>
</div>
<input class="form-control text-center" id="estimated_return" type="text" name="estimated_return" min="0" max="50" step="0.25" value="5.00%" data-value="5.00" data-append="%">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="estimated_return">+</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<div>Compound Frequency</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_daily" type="radio" name="compound_period" value="365">
<label class="form-check-label" for="compound_period_daily">daily</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_monthly" type="radio" name="compound_period" value="12" checked>
<label class="form-check-label" for="compound_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_annually" type="radio" name="compound_period" value="1">
<label class="form-check-label" for="compound_period_annually">annually</label>
</div>
</div>
</div>
</div>
<div class="col-md-6 text-center">
<div>Future Balance</div>
<div class="h3" id="future_balance">?</div>
<canvas id="myChart"></canvas>
</div>
</div>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"> </script>
</html>
Script.js
(function () {
var initial_deposit = document.querySelector('#initial_deposit'),
contribution_amount = document.querySelector('#contribution_amount'),
investment_timespan = document.querySelector('#investment_timespan'),
investment_timespan_text = document.querySelector('#investment_timespan_text'),
estimated_return = document.querySelector('#estimated_return'),
future_balance = document.querySelector('#future_balance');
function updateValue(element, action) {
var min = parseFloat(element.getAttribute('min')),
max = parseFloat(element.getAttribute('max')),
step = parseFloat(element.getAttribute('step')) || 1,
oldValue = element.dataset.value || element.defaultValue || 0,
newValue = parseFloat(element.value.replace(/$/, ''));
if (isNaN(parseFloat(newValue))) {
newValue = oldValue;
} else {
if (action == 'add') {
newValue += step;
} else if (action == 'sub') {
newValue -= step;
}
newValue = newValue < min ? min : newValue > max ? max : newValue;
}
element.dataset.value = newValue;
element.value = (element.dataset.prepend || '') + newValue + (element.dataset.append || '');
updateChart();
}
function getChartData() {
var P = parseFloat(initial_deposit.dataset.value), // Principal
r = parseFloat(estimated_return.dataset.value / 100), // Annual Interest Rate
c = parseFloat(contribution_amount.dataset.value), // Contribution Amount
n = parseInt(document.querySelector('[name="compound_period"]:checked').value), // Compound Period
n2 = parseInt(document.querySelector('[name="contribution_period"]:checked').value), // Contribution Period
t = parseInt(investment_timespan.value), // Investment Time Span
currentYear = (new Date()).getFullYear()
;
var labels = [];
for (var year = currentYear; year < currentYear + t; year++) {
labels.push(year);
}
var principal_dataset = {
label: 'Total Principal',
backgroundColor: 'rgb(0, 123, 255)',
data: []
};
var interest_dataset = {
label: "Total Interest",
backgroundColor: 'rgb(23, 162, 184)',
data: []
};
for (var i = 1; i <= t; i++) {
var principal = P + ( c * n2 * i ),
interest = 0,
balance = principal;
if (r) {
var x = Math.pow(1 + r / n, n * i),
compound_interest = P * x,
contribution_interest = c * (x - 1) / (r / n2);
interest = (compound_interest + contribution_interest - principal).toFixed(0)
balance = (compound_interest + contribution_interest).toFixed(0);
}
future_balance.innerHTML = '$' + balance;
principal_dataset.data.push(principal);
interest_dataset.data.push(interest);
}
return {
labels: labels,
datasets: [principal_dataset, interest_dataset]
}
}
function updateChart() {
var data = getChartData();
chart.data.labels = data.labels;
chart.data.datasets[0].data = data.datasets[0].data;
chart.data.datasets[1].data = data.datasets[1].data;
chart.update();
}
initial_deposit.addEventListener('change', function () {
updateValue(this);
});
contribution_amount.addEventListener('change', function () {
updateValue(this);
});
estimated_return.addEventListener('change', function () {
updateValue(this);
});
investment_timespan.addEventListener('change', function () {
investment_timespan_text.innerHTML = this.value + ' years';
updateChart();
});
investment_timespan.addEventListener('input', function () {
investment_timespan_text.innerHTML = this.value + ' years';
});
var radios = document.querySelectorAll('[name="contribution_period"], [name="compound_period"]');
for (var j = 0; j < radios.length; j++) {
radios[j].addEventListener('change', updateChart);
}
var buttons = document.querySelectorAll('[data-counter]');
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
button.addEventListener('click', function () {
var field = document.querySelector('[name="' + this.dataset.field + '"]'),
action = this.dataset.counter;
if (field) {
updateValue(field, action);
}
});
}
var ctx = document.getElementById('myChart').getContext('2d'),
chart = new Chart(ctx, {
type: 'bar',
data: getChartData(),
options: {
legend: {
display: false
},
tooltips: {
mode: 'index',
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ': $' + tooltipItem.yLabel;
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: 'Year'
}
}],
yAxes: [{
stacked: true,
ticks: {
callback: function (value) {
return '$' + value;
}
},
scaleLabel: {
display: true,
labelString: 'Balance'
}
}]
}
}
});
})();
你需要做四件事
- 添加
bootstrap.min.css
替换
future_balance.innerHTML = ' + balance;
和
future_balance.innerHTML = '' + balance;
第 74 行
替换
return data.datasets[tooltipItem.datasetIndex].label + ': + tooltipItem.yLabel;
和
return data.datasets[tooltipItem.datasetIndex].label + ':' + tooltipItem.yLabel;
第 148 行
替换
return ' + value;
和
return '' + value;
第 166 行
(function() {
var initial_deposit = document.querySelector('#initial_deposit'),
contribution_amount = document.querySelector('#contribution_amount'),
investment_timespan = document.querySelector('#investment_timespan'),
investment_timespan_text = document.querySelector('#investment_timespan_text'),
estimated_return = document.querySelector('#estimated_return'),
future_balance = document.querySelector('#future_balance');
function updateValue(element, action) {
var min = parseFloat(element.getAttribute('min')),
max = parseFloat(element.getAttribute('max')),
step = parseFloat(element.getAttribute('step')) || 1,
oldValue = element.dataset.value || element.defaultValue || 0,
newValue = parseFloat(element.value.replace(/$/, ''));
if (isNaN(parseFloat(newValue))) {
newValue = oldValue;
} else {
if (action == 'add') {
newValue += step;
} else if (action == 'sub') {
newValue -= step;
}
newValue = newValue < min ? min : newValue > max ? max : newValue;
}
element.dataset.value = newValue;
element.value = (element.dataset.prepend || '') + newValue + (element.dataset.append || '');
updateChart();
}
function getChartData() {
var P = parseFloat(initial_deposit.dataset.value), // Principal
r = parseFloat(estimated_return.dataset.value / 100), // Annual Interest Rate
c = parseFloat(contribution_amount.dataset.value), // Contribution Amount
n = parseInt(document.querySelector('[name="compound_period"]:checked').value), // Compound Period
n2 = parseInt(document.querySelector('[name="contribution_period"]:checked').value), // Contribution Period
t = parseInt(investment_timespan.value), // Investment Time Span
currentYear = (new Date()).getFullYear();
var labels = [];
for (var year = currentYear; year < currentYear + t; year++) {
labels.push(year);
}
var principal_dataset = {
label: 'Total Principal',
backgroundColor: 'rgb(0, 123, 255)',
data: []
};
var interest_dataset = {
label: "Total Interest",
backgroundColor: 'rgb(23, 162, 184)',
data: []
};
for (var i = 1; i <= t; i++) {
var principal = P + (c * n2 * i),
interest = 0,
balance = principal;
if (r) {
var x = Math.pow(1 + r / n, n * i),
compound_interest = P * x,
contribution_interest = c * (x - 1) / (r / n2);
interest = (compound_interest + contribution_interest - principal).toFixed(0)
balance = (compound_interest + contribution_interest).toFixed(0);
}
future_balance.innerHTML = '' + balance;
principal_dataset.data.push(principal);
interest_dataset.data.push(interest);
}
return {
labels: labels,
datasets: [principal_dataset, interest_dataset]
}
}
function updateChart() {
var data = getChartData();
chart.data.labels = data.labels;
chart.data.datasets[0].data = data.datasets[0].data;
chart.data.datasets[1].data = data.datasets[1].data;
chart.update();
}
initial_deposit.addEventListener('change', function() {
updateValue(this);
});
contribution_amount.addEventListener('change', function() {
updateValue(this);
});
estimated_return.addEventListener('change', function() {
updateValue(this);
});
investment_timespan.addEventListener('change', function() {
investment_timespan_text.innerHTML = this.value + ' years';
updateChart();
});
investment_timespan.addEventListener('input', function() {
investment_timespan_text.innerHTML = this.value + ' years';
});
var radios = document.querySelectorAll('[name="contribution_period"], [name="compound_period"]');
for (var j = 0; j < radios.length; j++) {
radios[j].addEventListener('change', updateChart);
}
var buttons = document.querySelectorAll('[data-counter]');
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
button.addEventListener('click', function() {
var field = document.querySelector('[name="' + this.dataset.field + '"]'),
action = this.dataset.counter;
if (field) {
updateValue(field, action);
}
});
}
var ctx = document.getElementById('myChart').getContext('2d'),
chart = new Chart(ctx, {
type: 'bar',
data: getChartData(),
options: {
legend: {
display: false
},
tooltips: {
mode: 'index',
intersect: false,
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ':' + tooltipItem.yLabel;
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: 'Year'
}
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value) {
return '' + value;
}
},
scaleLabel: {
display: true,
labelString: 'Balance'
}
}]
}
}
});
})();
body {
margin-top: 60px;
}
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="initial_deposit">Initial Deposit</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="initial_deposit">−</button>
</div>
<input class="form-control text-center" id="initial_deposit" type="text" name="initial_deposit" min="100" max="1000000" step="100" value="00" data-value="5000" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="initial_deposit">+</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="contribution_amount">Contributions</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="contribution_amount">−</button>
</div>
<input class="form-control text-center" id="contribution_amount" type="text" name="contribution_amount" min="0" max="10000" step="50" value="0" data-value="100" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="contribution_amount">+</button>
</div>
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_monthly" type="radio" name="contribution_period" value="12" checked>
<label class="form-check-label" for="contribution_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_annually" type="radio" name="contribution_period" value="1">
<label class="form-check-label" for="contribution_period_annually">annually</label>
</div>
</div>
<div class="form-group">
<label for="investment_timespan">Investment Time Span</label>
<div class="row">
<div class="col-md-6 col-sm-8">
<input class="form-control" id="investment_timespan" type="range" name="investment_timespan" min="2" max="50" step="1" value="5">
</div>
</div>
<span id="investment_timespan_text">5 years</span>
</div>
<div class="form-group">
<label for="estimated_return">Estimated Rate of Return</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="estimated_return">−</button>
</div>
<input class="form-control text-center" id="estimated_return" type="text" name="estimated_return" min="0" max="50" step="0.25" value="5.00%" data-value="5.00" data-append="%">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="estimated_return">+</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<div>Compound Frequency</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_daily" type="radio" name="compound_period" value="365">
<label class="form-check-label" for="compound_period_daily">daily</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_monthly" type="radio" name="compound_period" value="12" checked>
<label class="form-check-label" for="compound_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_annually" type="radio" name="compound_period" value="1">
<label class="form-check-label" for="compound_period_annually">annually</label>
</div>
</div>
</div>
</div>
<div class="col-md-6 text-center">
<div>Future Balance</div>
<div class="h3" id="future_balance">?</div>
<canvas id="myChart"></canvas>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"></script>
这些事情在你的尝试中是错误的
- Bootstrap 引用应该是
link
而不是 script
。你的代码应该是
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css" rel="stylesheet"/>
而不是
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css"></script>
确保您的 HTML HIERARCHY 正常
<head>
<link href="link to file" rel="stylesheet">
</head>
<body>
your code
<script src="">
</body>
您的图表无法正常工作,因为您在 Javascript 代码中存在语法错误。
第 74,148,166
行有未关闭的 ''
future_balance.innerHTML = ' + balance; //74
return data.datasets[tooltipItem.datasetIndex].label + ': + tooltipItem.yLabel;//148
return ' + value;//166
将它们处理为
future_balance.innerHTML = '' + balance; //74
return data.datasets[tooltipItem.datasetIndex].label + ':' + tooltipItem.yLabel;//148
return '' + value;//166
这是您的工作代码
如果您想在此处复制粘贴 运行 代码
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="initial_deposit">Initial Deposit</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="initial_deposit">−</button>
</div>
<input class="form-control text-center" id="initial_deposit" type="text" name="initial_deposit" min="100" max="1000000" step="100" value="00" data-value="5000" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="initial_deposit">+</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="contribution_amount">Contributions</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="contribution_amount">−</button>
</div>
<input class="form-control text-center" id="contribution_amount" type="text" name="contribution_amount" min="0" max="10000" step="50" value="0" data-value="100" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="contribution_amount">+</button>
</div>
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_monthly" type="radio" name="contribution_period" value="12" checked>
<label class="form-check-label" for="contribution_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_annually" type="radio" name="contribution_period" value="1">
<label class="form-check-label" for="contribution_period_annually">annually</label>
</div>
</div>
<div class="form-group">
<label for="investment_timespan">Investment Time Span</label>
<div class="row">
<div class="col-md-6 col-sm-8">
<input class="form-control" id="investment_timespan" type="range" name="investment_timespan" min="2" max="50" step="1" value="5">
</div>
</div>
<span id="investment_timespan_text">5 years</span>
</div>
<div class="form-group">
<label for="estimated_return">Estimated Rate of Return</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="estimated_return">−</button>
</div>
<input class="form-control text-center" id="estimated_return" type="text" name="estimated_return" min="0" max="50" step="0.25" value="5.00%" data-value="5.00" data-append="%">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="estimated_return">+</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<div>Compound Frequency</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_daily" type="radio" name="compound_period" value="365">
<label class="form-check-label" for="compound_period_daily">daily</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_monthly" type="radio" name="compound_period" value="12" checked>
<label class="form-check-label" for="compound_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_annually" type="radio" name="compound_period" value="1">
<label class="form-check-label" for="compound_period_annually">annually</label>
</div>
</div>
</div>
</div>
<div class="col-md-6 text-center">
<div>Future Balance</div>
<div class="h3" id="future_balance">?</div>
<canvas id="myChart"></canvas>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"></script>
<script>
(function() {
var initial_deposit = document.querySelector('#initial_deposit'),
contribution_amount = document.querySelector('#contribution_amount'),
investment_timespan = document.querySelector('#investment_timespan'),
investment_timespan_text = document.querySelector('#investment_timespan_text'),
estimated_return = document.querySelector('#estimated_return'),
future_balance = document.querySelector('#future_balance');
function updateValue(element, action) {
var min = parseFloat(element.getAttribute('min')),
max = parseFloat(element.getAttribute('max')),
step = parseFloat(element.getAttribute('step')) || 1,
oldValue = element.dataset.value || element.defaultValue || 0,
newValue = parseFloat(element.value.replace(/$/, ''));
if (isNaN(parseFloat(newValue))) {
newValue = oldValue;
} else {
if (action == 'add') {
newValue += step;
} else if (action == 'sub') {
newValue -= step;
}
newValue = newValue < min ? min : newValue > max ? max : newValue;
}
element.dataset.value = newValue;
element.value = (element.dataset.prepend || '') + newValue + (element.dataset.append || '');
updateChart();
}
function getChartData() {
var P = parseFloat(initial_deposit.dataset.value), // Principal
r = parseFloat(estimated_return.dataset.value / 100), // Annual Interest Rate
c = parseFloat(contribution_amount.dataset.value), // Contribution Amount
n = parseInt(document.querySelector('[name="compound_period"]:checked').value), // Compound Period
n2 = parseInt(document.querySelector('[name="contribution_period"]:checked').value), // Contribution Period
t = parseInt(investment_timespan.value), // Investment Time Span
currentYear = (new Date()).getFullYear();
var labels = [];
for (var year = currentYear; year < currentYear + t; year++) {
labels.push(year);
}
var principal_dataset = {
label: 'Total Principal',
backgroundColor: 'rgb(0, 123, 255)',
data: []
};
var interest_dataset = {
label: "Total Interest",
backgroundColor: 'rgb(23, 162, 184)',
data: []
};
for (var i = 1; i <= t; i++) {
var principal = P + (c * n2 * i),
interest = 0,
balance = principal;
if (r) {
var x = Math.pow(1 + r / n, n * i),
compound_interest = P * x,
contribution_interest = c * (x - 1) / (r / n2);
interest = (compound_interest + contribution_interest - principal).toFixed(0)
balance = (compound_interest + contribution_interest).toFixed(0);
}
future_balance.innerHTML = '' +
balance;
principal_dataset.data.push(principal);
interest_dataset.data.push(interest);
}
return {
labels: labels,
datasets: [principal_dataset, interest_dataset]
}
}
function updateChart() {
var data = getChartData();
chart.data.labels = data.labels;
chart.data.datasets[0].data = data.datasets[0].data;
chart.data.datasets[1].data = data.datasets[1].data;
chart.update();
}
initial_deposit.addEventListener('change', function() {
updateValue(this);
});
contribution_amount.addEventListener('change', function() {
updateValue(this);
});
estimated_return.addEventListener('change', function() {
updateValue(this);
});
investment_timespan.addEventListener('change', function() {
investment_timespan_text.innerHTML = this.value + ' years';
updateChart();
});
investment_timespan.addEventListener('input', function() {
investment_timespan_text.innerHTML = this.value + ' years';
});
var radios = document.querySelectorAll('[name="contribution_period"], [name="compound_period"]');
for (var j = 0; j < radios.length; j++) {
radios[j].addEventListener('change', updateChart);
}
var buttons = document.querySelectorAll('[data-counter]');
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
button.addEventListener('click', function() {
var field = document.querySelector('[name="' + this.dataset.field + '"]'),
action = this.dataset.counter;
if (field) {
updateValue(field, action);
}
});
}
var ctx = document.getElementById('myChart').getContext('2d'),
chart = new Chart(ctx, {
type: 'bar',
data: getChartData(),
options: {
legend: {
display: false
},
tooltips: {
mode: 'index',
intersect: false,
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ':' +
tooltipItem.yLabel;
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: 'Year'
}
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value) {
return '' +
value;
}
},
scaleLabel: {
display: true,
labelString: 'Balance'
}
}]
}
}
});
})();
</script>
</body>
请使用 returns 上的符号和分隔符。评论错误并给出更正。
// return data.datasets[tooltipItem.datasetIndex].label + ':
// + tooltipItem.yLabel;
return data.datasets[tooltipItem.datasetIndex].label + ': ' + tooltipItem.yLabel;
// future_balance.innerHTML = '
// + balance;
future_balance.innerHTML = '$' + balance;
// return '
// + value;
return '$' + value;
我正在尝试制作一个带有直方图的 Intrest 计算器 我在网上找到了这些脚本,因为我是 javaScript 的新手。 所以我想要的输出是这样的Desired Outpyt 我得到的输出是 comming output 所以我真的需要一些帮助 第一,带有 + 和 - 符号的蓝色按钮太疯狂了。 其次,直方图没有显示。
所以请帮助我,我将不胜感激。
我已从该站点复制粘贴代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css" >
<meta charset="UTF-8">
<title>Savings Calculator</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="initial_deposit">Initial Deposit</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="initial_deposit">−</button>
</div>
<input class="form-control text-center" id="initial_deposit" type="text" name="initial_deposit" min="100" max="1000000" step="100" value="00" data-value="5000" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="initial_deposit">+</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="contribution_amount">Contributions</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="contribution_amount">−</button>
</div>
<input class="form-control text-center" id="contribution_amount" type="text" name="contribution_amount" min="0" max="10000" step="50" value="0" data-value="100" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="contribution_amount">+</button>
</div>
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_monthly" type="radio" name="contribution_period" value="12" checked>
<label class="form-check-label" for="contribution_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_annually" type="radio" name="contribution_period" value="1">
<label class="form-check-label" for="contribution_period_annually">annually</label>
</div>
</div>
<div class="form-group">
<label for="investment_timespan">Investment Time Span</label>
<div class="row">
<div class="col-md-6 col-sm-8">
<input class="form-control" id="investment_timespan" type="range" name="investment_timespan" min="2" max="50" step="1" value="5">
</div>
</div>
<span id="investment_timespan_text">5 years</span>
</div>
<div class="form-group">
<label for="estimated_return">Estimated Rate of Return</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="estimated_return">−</button>
</div>
<input class="form-control text-center" id="estimated_return" type="text" name="estimated_return" min="0" max="50" step="0.25" value="5.00%" data-value="5.00" data-append="%">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="estimated_return">+</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<div>Compound Frequency</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_daily" type="radio" name="compound_period" value="365">
<label class="form-check-label" for="compound_period_daily">daily</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_monthly" type="radio" name="compound_period" value="12" checked>
<label class="form-check-label" for="compound_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_annually" type="radio" name="compound_period" value="1">
<label class="form-check-label" for="compound_period_annually">annually</label>
</div>
</div>
</div>
</div>
<div class="col-md-6 text-center">
<div>Future Balance</div>
<div class="h3" id="future_balance">?</div>
<canvas id="myChart"></canvas>
</div>
</div>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"> </script>
</html>
Script.js
(function () {
var initial_deposit = document.querySelector('#initial_deposit'),
contribution_amount = document.querySelector('#contribution_amount'),
investment_timespan = document.querySelector('#investment_timespan'),
investment_timespan_text = document.querySelector('#investment_timespan_text'),
estimated_return = document.querySelector('#estimated_return'),
future_balance = document.querySelector('#future_balance');
function updateValue(element, action) {
var min = parseFloat(element.getAttribute('min')),
max = parseFloat(element.getAttribute('max')),
step = parseFloat(element.getAttribute('step')) || 1,
oldValue = element.dataset.value || element.defaultValue || 0,
newValue = parseFloat(element.value.replace(/$/, ''));
if (isNaN(parseFloat(newValue))) {
newValue = oldValue;
} else {
if (action == 'add') {
newValue += step;
} else if (action == 'sub') {
newValue -= step;
}
newValue = newValue < min ? min : newValue > max ? max : newValue;
}
element.dataset.value = newValue;
element.value = (element.dataset.prepend || '') + newValue + (element.dataset.append || '');
updateChart();
}
function getChartData() {
var P = parseFloat(initial_deposit.dataset.value), // Principal
r = parseFloat(estimated_return.dataset.value / 100), // Annual Interest Rate
c = parseFloat(contribution_amount.dataset.value), // Contribution Amount
n = parseInt(document.querySelector('[name="compound_period"]:checked').value), // Compound Period
n2 = parseInt(document.querySelector('[name="contribution_period"]:checked').value), // Contribution Period
t = parseInt(investment_timespan.value), // Investment Time Span
currentYear = (new Date()).getFullYear()
;
var labels = [];
for (var year = currentYear; year < currentYear + t; year++) {
labels.push(year);
}
var principal_dataset = {
label: 'Total Principal',
backgroundColor: 'rgb(0, 123, 255)',
data: []
};
var interest_dataset = {
label: "Total Interest",
backgroundColor: 'rgb(23, 162, 184)',
data: []
};
for (var i = 1; i <= t; i++) {
var principal = P + ( c * n2 * i ),
interest = 0,
balance = principal;
if (r) {
var x = Math.pow(1 + r / n, n * i),
compound_interest = P * x,
contribution_interest = c * (x - 1) / (r / n2);
interest = (compound_interest + contribution_interest - principal).toFixed(0)
balance = (compound_interest + contribution_interest).toFixed(0);
}
future_balance.innerHTML = '$' + balance;
principal_dataset.data.push(principal);
interest_dataset.data.push(interest);
}
return {
labels: labels,
datasets: [principal_dataset, interest_dataset]
}
}
function updateChart() {
var data = getChartData();
chart.data.labels = data.labels;
chart.data.datasets[0].data = data.datasets[0].data;
chart.data.datasets[1].data = data.datasets[1].data;
chart.update();
}
initial_deposit.addEventListener('change', function () {
updateValue(this);
});
contribution_amount.addEventListener('change', function () {
updateValue(this);
});
estimated_return.addEventListener('change', function () {
updateValue(this);
});
investment_timespan.addEventListener('change', function () {
investment_timespan_text.innerHTML = this.value + ' years';
updateChart();
});
investment_timespan.addEventListener('input', function () {
investment_timespan_text.innerHTML = this.value + ' years';
});
var radios = document.querySelectorAll('[name="contribution_period"], [name="compound_period"]');
for (var j = 0; j < radios.length; j++) {
radios[j].addEventListener('change', updateChart);
}
var buttons = document.querySelectorAll('[data-counter]');
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
button.addEventListener('click', function () {
var field = document.querySelector('[name="' + this.dataset.field + '"]'),
action = this.dataset.counter;
if (field) {
updateValue(field, action);
}
});
}
var ctx = document.getElementById('myChart').getContext('2d'),
chart = new Chart(ctx, {
type: 'bar',
data: getChartData(),
options: {
legend: {
display: false
},
tooltips: {
mode: 'index',
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ': $' + tooltipItem.yLabel;
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: 'Year'
}
}],
yAxes: [{
stacked: true,
ticks: {
callback: function (value) {
return '$' + value;
}
},
scaleLabel: {
display: true,
labelString: 'Balance'
}
}]
}
}
});
})();
你需要做四件事
- 添加
bootstrap.min.css
替换
future_balance.innerHTML = ' + balance;
和
future_balance.innerHTML = '' + balance;
第 74 行
替换
return data.datasets[tooltipItem.datasetIndex].label + ': + tooltipItem.yLabel;
和
return data.datasets[tooltipItem.datasetIndex].label + ':' + tooltipItem.yLabel;
第 148 行
替换
return ' + value;
和
return '' + value;
第 166 行
(function() {
var initial_deposit = document.querySelector('#initial_deposit'),
contribution_amount = document.querySelector('#contribution_amount'),
investment_timespan = document.querySelector('#investment_timespan'),
investment_timespan_text = document.querySelector('#investment_timespan_text'),
estimated_return = document.querySelector('#estimated_return'),
future_balance = document.querySelector('#future_balance');
function updateValue(element, action) {
var min = parseFloat(element.getAttribute('min')),
max = parseFloat(element.getAttribute('max')),
step = parseFloat(element.getAttribute('step')) || 1,
oldValue = element.dataset.value || element.defaultValue || 0,
newValue = parseFloat(element.value.replace(/$/, ''));
if (isNaN(parseFloat(newValue))) {
newValue = oldValue;
} else {
if (action == 'add') {
newValue += step;
} else if (action == 'sub') {
newValue -= step;
}
newValue = newValue < min ? min : newValue > max ? max : newValue;
}
element.dataset.value = newValue;
element.value = (element.dataset.prepend || '') + newValue + (element.dataset.append || '');
updateChart();
}
function getChartData() {
var P = parseFloat(initial_deposit.dataset.value), // Principal
r = parseFloat(estimated_return.dataset.value / 100), // Annual Interest Rate
c = parseFloat(contribution_amount.dataset.value), // Contribution Amount
n = parseInt(document.querySelector('[name="compound_period"]:checked').value), // Compound Period
n2 = parseInt(document.querySelector('[name="contribution_period"]:checked').value), // Contribution Period
t = parseInt(investment_timespan.value), // Investment Time Span
currentYear = (new Date()).getFullYear();
var labels = [];
for (var year = currentYear; year < currentYear + t; year++) {
labels.push(year);
}
var principal_dataset = {
label: 'Total Principal',
backgroundColor: 'rgb(0, 123, 255)',
data: []
};
var interest_dataset = {
label: "Total Interest",
backgroundColor: 'rgb(23, 162, 184)',
data: []
};
for (var i = 1; i <= t; i++) {
var principal = P + (c * n2 * i),
interest = 0,
balance = principal;
if (r) {
var x = Math.pow(1 + r / n, n * i),
compound_interest = P * x,
contribution_interest = c * (x - 1) / (r / n2);
interest = (compound_interest + contribution_interest - principal).toFixed(0)
balance = (compound_interest + contribution_interest).toFixed(0);
}
future_balance.innerHTML = '' + balance;
principal_dataset.data.push(principal);
interest_dataset.data.push(interest);
}
return {
labels: labels,
datasets: [principal_dataset, interest_dataset]
}
}
function updateChart() {
var data = getChartData();
chart.data.labels = data.labels;
chart.data.datasets[0].data = data.datasets[0].data;
chart.data.datasets[1].data = data.datasets[1].data;
chart.update();
}
initial_deposit.addEventListener('change', function() {
updateValue(this);
});
contribution_amount.addEventListener('change', function() {
updateValue(this);
});
estimated_return.addEventListener('change', function() {
updateValue(this);
});
investment_timespan.addEventListener('change', function() {
investment_timespan_text.innerHTML = this.value + ' years';
updateChart();
});
investment_timespan.addEventListener('input', function() {
investment_timespan_text.innerHTML = this.value + ' years';
});
var radios = document.querySelectorAll('[name="contribution_period"], [name="compound_period"]');
for (var j = 0; j < radios.length; j++) {
radios[j].addEventListener('change', updateChart);
}
var buttons = document.querySelectorAll('[data-counter]');
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
button.addEventListener('click', function() {
var field = document.querySelector('[name="' + this.dataset.field + '"]'),
action = this.dataset.counter;
if (field) {
updateValue(field, action);
}
});
}
var ctx = document.getElementById('myChart').getContext('2d'),
chart = new Chart(ctx, {
type: 'bar',
data: getChartData(),
options: {
legend: {
display: false
},
tooltips: {
mode: 'index',
intersect: false,
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ':' + tooltipItem.yLabel;
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: 'Year'
}
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value) {
return '' + value;
}
},
scaleLabel: {
display: true,
labelString: 'Balance'
}
}]
}
}
});
})();
body {
margin-top: 60px;
}
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="initial_deposit">Initial Deposit</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="initial_deposit">−</button>
</div>
<input class="form-control text-center" id="initial_deposit" type="text" name="initial_deposit" min="100" max="1000000" step="100" value="00" data-value="5000" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="initial_deposit">+</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="contribution_amount">Contributions</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="contribution_amount">−</button>
</div>
<input class="form-control text-center" id="contribution_amount" type="text" name="contribution_amount" min="0" max="10000" step="50" value="0" data-value="100" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="contribution_amount">+</button>
</div>
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_monthly" type="radio" name="contribution_period" value="12" checked>
<label class="form-check-label" for="contribution_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_annually" type="radio" name="contribution_period" value="1">
<label class="form-check-label" for="contribution_period_annually">annually</label>
</div>
</div>
<div class="form-group">
<label for="investment_timespan">Investment Time Span</label>
<div class="row">
<div class="col-md-6 col-sm-8">
<input class="form-control" id="investment_timespan" type="range" name="investment_timespan" min="2" max="50" step="1" value="5">
</div>
</div>
<span id="investment_timespan_text">5 years</span>
</div>
<div class="form-group">
<label for="estimated_return">Estimated Rate of Return</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="estimated_return">−</button>
</div>
<input class="form-control text-center" id="estimated_return" type="text" name="estimated_return" min="0" max="50" step="0.25" value="5.00%" data-value="5.00" data-append="%">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="estimated_return">+</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<div>Compound Frequency</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_daily" type="radio" name="compound_period" value="365">
<label class="form-check-label" for="compound_period_daily">daily</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_monthly" type="radio" name="compound_period" value="12" checked>
<label class="form-check-label" for="compound_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_annually" type="radio" name="compound_period" value="1">
<label class="form-check-label" for="compound_period_annually">annually</label>
</div>
</div>
</div>
</div>
<div class="col-md-6 text-center">
<div>Future Balance</div>
<div class="h3" id="future_balance">?</div>
<canvas id="myChart"></canvas>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"></script>
这些事情在你的尝试中是错误的
- Bootstrap 引用应该是
link
而不是script
。你的代码应该是
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css" rel="stylesheet"/>
而不是
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css"></script>
确保您的 HTML HIERARCHY 正常
<head> <link href="link to file" rel="stylesheet"> </head> <body> your code <script src=""> </body>
您的图表无法正常工作,因为您在 Javascript 代码中存在语法错误。 第 74,148,166
行有未关闭的''
future_balance.innerHTML = ' + balance; //74 return data.datasets[tooltipItem.datasetIndex].label + ': + tooltipItem.yLabel;//148 return ' + value;//166
将它们处理为
future_balance.innerHTML = '' + balance; //74 return data.datasets[tooltipItem.datasetIndex].label + ':' + tooltipItem.yLabel;//148 return '' + value;//166
这是您的工作代码
如果您想在此处复制粘贴 运行 代码
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.3/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="initial_deposit">Initial Deposit</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="initial_deposit">−</button>
</div>
<input class="form-control text-center" id="initial_deposit" type="text" name="initial_deposit" min="100" max="1000000" step="100" value="00" data-value="5000" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="initial_deposit">+</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="contribution_amount">Contributions</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="contribution_amount">−</button>
</div>
<input class="form-control text-center" id="contribution_amount" type="text" name="contribution_amount" min="0" max="10000" step="50" value="0" data-value="100" data-prepend="$">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="contribution_amount">+</button>
</div>
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_monthly" type="radio" name="contribution_period" value="12" checked>
<label class="form-check-label" for="contribution_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="contribution_period_annually" type="radio" name="contribution_period" value="1">
<label class="form-check-label" for="contribution_period_annually">annually</label>
</div>
</div>
<div class="form-group">
<label for="investment_timespan">Investment Time Span</label>
<div class="row">
<div class="col-md-6 col-sm-8">
<input class="form-control" id="investment_timespan" type="range" name="investment_timespan" min="2" max="50" step="1" value="5">
</div>
</div>
<span id="investment_timespan_text">5 years</span>
</div>
<div class="form-group">
<label for="estimated_return">Estimated Rate of Return</label>
<div class="row">
<div class="input-group col-md-6 col-sm-8">
<div class="input-group-prepend">
<button class="btn btn-primary" type="button" data-counter="sub" data-field="estimated_return">−</button>
</div>
<input class="form-control text-center" id="estimated_return" type="text" name="estimated_return" min="0" max="50" step="0.25" value="5.00%" data-value="5.00" data-append="%">
<div class="input-group-append">
<button class="btn btn-primary" type="button" data-counter="add" data-field="estimated_return">+</button>
</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<div>Compound Frequency</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_daily" type="radio" name="compound_period" value="365">
<label class="form-check-label" for="compound_period_daily">daily</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_monthly" type="radio" name="compound_period" value="12" checked>
<label class="form-check-label" for="compound_period_monthly">monthly</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" id="compound_period_annually" type="radio" name="compound_period" value="1">
<label class="form-check-label" for="compound_period_annually">annually</label>
</div>
</div>
</div>
</div>
<div class="col-md-6 text-center">
<div>Future Balance</div>
<div class="h3" id="future_balance">?</div>
<canvas id="myChart"></canvas>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"></script>
<script>
(function() {
var initial_deposit = document.querySelector('#initial_deposit'),
contribution_amount = document.querySelector('#contribution_amount'),
investment_timespan = document.querySelector('#investment_timespan'),
investment_timespan_text = document.querySelector('#investment_timespan_text'),
estimated_return = document.querySelector('#estimated_return'),
future_balance = document.querySelector('#future_balance');
function updateValue(element, action) {
var min = parseFloat(element.getAttribute('min')),
max = parseFloat(element.getAttribute('max')),
step = parseFloat(element.getAttribute('step')) || 1,
oldValue = element.dataset.value || element.defaultValue || 0,
newValue = parseFloat(element.value.replace(/$/, ''));
if (isNaN(parseFloat(newValue))) {
newValue = oldValue;
} else {
if (action == 'add') {
newValue += step;
} else if (action == 'sub') {
newValue -= step;
}
newValue = newValue < min ? min : newValue > max ? max : newValue;
}
element.dataset.value = newValue;
element.value = (element.dataset.prepend || '') + newValue + (element.dataset.append || '');
updateChart();
}
function getChartData() {
var P = parseFloat(initial_deposit.dataset.value), // Principal
r = parseFloat(estimated_return.dataset.value / 100), // Annual Interest Rate
c = parseFloat(contribution_amount.dataset.value), // Contribution Amount
n = parseInt(document.querySelector('[name="compound_period"]:checked').value), // Compound Period
n2 = parseInt(document.querySelector('[name="contribution_period"]:checked').value), // Contribution Period
t = parseInt(investment_timespan.value), // Investment Time Span
currentYear = (new Date()).getFullYear();
var labels = [];
for (var year = currentYear; year < currentYear + t; year++) {
labels.push(year);
}
var principal_dataset = {
label: 'Total Principal',
backgroundColor: 'rgb(0, 123, 255)',
data: []
};
var interest_dataset = {
label: "Total Interest",
backgroundColor: 'rgb(23, 162, 184)',
data: []
};
for (var i = 1; i <= t; i++) {
var principal = P + (c * n2 * i),
interest = 0,
balance = principal;
if (r) {
var x = Math.pow(1 + r / n, n * i),
compound_interest = P * x,
contribution_interest = c * (x - 1) / (r / n2);
interest = (compound_interest + contribution_interest - principal).toFixed(0)
balance = (compound_interest + contribution_interest).toFixed(0);
}
future_balance.innerHTML = '' +
balance;
principal_dataset.data.push(principal);
interest_dataset.data.push(interest);
}
return {
labels: labels,
datasets: [principal_dataset, interest_dataset]
}
}
function updateChart() {
var data = getChartData();
chart.data.labels = data.labels;
chart.data.datasets[0].data = data.datasets[0].data;
chart.data.datasets[1].data = data.datasets[1].data;
chart.update();
}
initial_deposit.addEventListener('change', function() {
updateValue(this);
});
contribution_amount.addEventListener('change', function() {
updateValue(this);
});
estimated_return.addEventListener('change', function() {
updateValue(this);
});
investment_timespan.addEventListener('change', function() {
investment_timespan_text.innerHTML = this.value + ' years';
updateChart();
});
investment_timespan.addEventListener('input', function() {
investment_timespan_text.innerHTML = this.value + ' years';
});
var radios = document.querySelectorAll('[name="contribution_period"], [name="compound_period"]');
for (var j = 0; j < radios.length; j++) {
radios[j].addEventListener('change', updateChart);
}
var buttons = document.querySelectorAll('[data-counter]');
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
button.addEventListener('click', function() {
var field = document.querySelector('[name="' + this.dataset.field + '"]'),
action = this.dataset.counter;
if (field) {
updateValue(field, action);
}
});
}
var ctx = document.getElementById('myChart').getContext('2d'),
chart = new Chart(ctx, {
type: 'bar',
data: getChartData(),
options: {
legend: {
display: false
},
tooltips: {
mode: 'index',
intersect: false,
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ':' +
tooltipItem.yLabel;
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: 'Year'
}
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value) {
return '' +
value;
}
},
scaleLabel: {
display: true,
labelString: 'Balance'
}
}]
}
}
});
})();
</script>
</body>
请使用 returns 上的符号和分隔符。评论错误并给出更正。
// return data.datasets[tooltipItem.datasetIndex].label + ':
// + tooltipItem.yLabel;
return data.datasets[tooltipItem.datasetIndex].label + ': ' + tooltipItem.yLabel;
// future_balance.innerHTML = '
// + balance;
future_balance.innerHTML = '$' + balance;
// return '
// + value;
return '$' + value;