我正在使用HTML,CSS,Javascript以及Javascript:The Definitive Guide(第6版)中的元素来处理贷款计算器示例。
这是JSfiddle:http://goo.gl/PWTtLi
我的问题:
1)图表未显示。为什么? 2)当我在JSFiddle版本中输入数字时,单击“计算”按钮时没有任何反应。但是,当我在计算机上打开HTML页面时,该页面将起作用。为什么呢?
我已经阅读了这本书的勘误表。不可否认,画布代码超出了我目前的技能水平,但我对HTML / CSS / JavaScript感到满意。我手工编写了书中的例子。 JsHint / console.log没有错误。有什么想法吗?
HTML
<table>
<tr>
<th>Enter Loan Data:</th>
<td></td>
<th>Loan Balance, Cumulative Equity, and Interest Payments</th>
</tr>
<tr>
<td>Amount of the loan ($):</td>
<td>
<input id="amount" onchange="calculate();">
</td>
<td rowspan=8>
<canvas id="graph" width="400" height="250"></canvas>
</td>
</tr>
<tr>
<td>Annual interest (%):</td>
<td>
<input id="apr" onchange="calculate();">
</td>
</tr>
<tr>
<td>Repayment period (years):</td>
<td>
<input id="years" onchange="calculate();">
</td>
<tr>
<td>Zipcode (to find lenders):</td>
<td>
<input id="zipcode" onchange="calculate();">
</td>
<tr>
<th>Approximate Payments:</th>
<td>
<button onclick="calculate();">Calculate</button>
</td>
</tr>
<tr>
<td>Monthly payment:</td>
<td>$<span class="output" id="payment"></span>
</td>
</tr>
<tr>
<td>Total payment:</td>
<td>$<span class="output" id="total"></span>
</td>
</tr>
<tr>
<td>Total interest:</td>
<td>$<span class="output" id="totalinterest"></span>
</td>
</tr>
<tr>
<th>Sponsors:</th>
<td colspan=2>Apply for your loan with one of these fine lenders:
<div id="lenders"></div>
</td>
</tr>
</table>
JS
function calculate() {
// Look up the input and output elements in the
// document
var amount = document.getElementById("amount");
var apr = document.getElementById("apr");
var years = document.getElementById("years");
var zipcode = document.getElementById("zipcode");
var payment = document.getElementById("payment");
var total = document.getElementById("total");
var totalinterest = document.getElementById("totalinterest");
// Get the user's input from the input elements.
// Assume it is all valid. Convert interest from
// a percentage to a decimal, and convert from an
// annual rate to a monthly rate. Convert payment
// period in years to the number of monthly
// payments.
var principal = parseFloat(amount.value);
var interest = parseFloat(apr.value) / 100 / 12;
var payments = parseFloat(years.value) * 12;
// Now compute the monthly payment figure.
var x = Math.pow(1 + interest, payments); // Math.pow() computes powers
var monthly = (principal * x * interest) / (x - 1);
// If the result is a finite umber, the user's input was good and
// we have meaningful results to display
if (isFinite(monthly)) {
// Fill in the output fields, rounding to 2 decimal places
payment.innerHTML = monthly.toFixed(2);
total.innerHTML = (monthly * payments).toFixed(2);
totalinterest.innerHTML = ((monthly * payments) - principal).toFixed(2);
// Save the user's input so we can restore it the next they visit
save(amount.value, apr.value, years.value, zipcode.value);
// Advertise: find and display local lenders, but ignore network errors
try { // Catch any errors that occur within the curly braces
// getLenders(amount.value, apr.value, years.value, zipcode.value);
} catch (e) { /* And ignore those errors */
}
// Chat loan balance, and interest, and equity payments
chart(principal, interest, monthly, payments);
} else {
// Reslt was Not-a-Number or infinite, which means the input was
// incomplete or invalid. Clear any peviously displayed output.
payment.innterHTML = ""; // Erase the content of these elemts
total.innerHTML = "";
totalinterest.innerHTML = "";
chart(); // With no arguments, clears the chart
}
}
// Save the user's input as properties of the localStorage object. Those
// properties will still be there when the user visits in the future
// This storage feature will not work in some browsers (Firefox, e.g.) if you
// run the example from a local file:// URL. It does work over HTTP, however.
function save(amount, apr, years, zipcode) {
if (window.localStorage) { // Only do this if the browser supports it
localStorage.loan_amount = amount;
localStorage.loan_amount = apr;
localStorage.loan_amount = years;
localStorage.loan_amount = zipcode;
}
}
// Automatically attempt to restore input fields when the document first loads.
window.onload = function () {
//If the browser supports localStorage and we have some stored data
if (window.localStorage && localStorage.loan_amount) {
document.getElementbyId("amount").value = localStorage.loan_amount;
document.getElementbyId("apr").value = localStorage.loan_apr;
document.getElementbyId("years").value = localStorage.loan_years;
document.getElementbyId("zipcode").value = localStorage.loan_zipcode;
}
};
//Chart montly loan balance, interest and equity in an HTML <canvas> element.
// If called with no arguments then just erase any previously drawn chart.
function chart(principal, interest, monthly, payments) {
var graph = document.getElementById("graph"); // Get the <canvas> tag
graph.width = graph.width; // Magic to clear and reset the canvas elemtn
// If we're called with no arguments, or ig this browser does not support
// graphics in a <canvas> elemtn, then just return now.
if (arguments.length === 0 || !graph.getContect) return;
// Get the "context" object for the <canvas> that defines the drawing API
var g = graph.getContext("2d"); // All drawing is done with this object
var width = graph.width,
height = graph.height; //Get canvas size
// These functions convert payment numbers and dollar amounts to pixels
function paymentToX(n) {
return n * width / payments;
}
function amountToY(a) {
return height - (a * height / (monthly * payments * 1.05));
}
// Payments are a straight line from (0,0) to (payments, monthly*payments)
g.moveTo(paymentToX(0), amountToY(0)); // Start at lower left
g.lineTo(paymentToX(payments), // Draw to upper right
amountToY(monthly * payments));
g.lineTo(paymentToX(payments), amountToY(0)); // Down to lower right
g.closePath(); // And back to start
g.fillStyle = "#f88"; // Light red
g.fill(); // Fill the triangle
g.font = "bold 12px sans-serif"; // Define a font
g.fillText("Total Interest Payments", 20, 20); // Draw text in legend
// Vumulative equity is non-linear and trickier to chart
var equity = 0;
g.beginPath(); // Begin a new shape
g.moveTo(paymentToX(0), amountToY()); // starting at lower-left
for (var p = 1; p <= payments; p++) {
// For each payment, figure out how much is interest
var thisMonthsInterest = (principal - equity) * interest;
equity += (monthly - thisMonthsInterest); // The rest goes to equity
g.lineTo(paymentToX(p), amountToY(equity)); //Line to this point
}
g.lineTo(paymentToX(payments), amountToY(0)); // Line back to X axis
g.closePath(); // And back to start point
g.fillStyle = "green"; // Now use green paint
g.fill(); // And fill area under curve
g.fillText("Total Equity", 20, 35); // Label it in green
// Loop again, as above, but chart loan balance as a thick black line
var bal = principal;
g.beginPath();
g.moveTo(paymentToX(0), amountToY(bal));
for (var p = 1; p <= payments; p++) {
var thisMonthsInterest = bal * interest;
bal += (monthly - thisMonthsInterest); // The rest goes to equity
g.lineTo(paymentToX(p), amountToY(bal)); // Draw line to this point
}
g.lineWidth = 3; // Use a thick line
g.stroke(); // Deaw the balance curve
g.fillStyle = "black"; // Switch to black text
g.fillText("Loan Balance", 20, 50); // Legend entry
// Now make a yearly tick marks and year numbers on X acis
g.textAlign = "center"; // Center text over ticks
var y = amountToY(0); // Y coordinate of X axis
for (var year = 1; year * 12 <= payments; year++) { // For each year
var x = paymentToX(year * 12); // Compute tick position
g.fillRect(x - 0.5, y - 3, 1, 3); // Draw the tick
if (year == 1) g.fillText("Year", x, y - 5); // Label the axis
if (year % 5 === 0 && year * 12 !== payments) // Number every 5 years
g.fillText(String(year), x, y - 5);
}
// Mark payment amounts along the right edge
g.textAlign = "right"; //Right=justify text
g.textBaseline = "middle"; // Center it vertically
var ticks = [monthly * payments, principal]; // The two points we'll mark
var rightEdge = paymentToX(payments); //X coordinate of Y axis
for (var i = 0; i < ticks.length; i++) { // for each of the 2 points
var y = amountToY(ticks[i]); // Compute Y position of tick
g.fillRect(rightEdge - 3, y - 0.5, 3, 1); //Draw the tick mark
g.fillText(String(ticks[i].toFixed(0)), //And label it.
rightEdge - 5, y);
}
}
答案 0 :(得分:0)
这是一个常见的问题。见Inline event handler not working in JSFiddle
在您的情况下,JS错误控制台会打印一条消息,按下按钮时,calculate
未定义。
如果您更改JSFIDDLE的Javascript部分以显式定义window.calculate,它将起作用。
像这样:
window.calculate = function(){
而不是function calculate(){...