JavaScript贷款计算器问题

时间:2014-10-07 00:33:19

标签: javascript html css3 canvas

我正在使用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);
    }
}

1 个答案:

答案 0 :(得分:0)

这是一个常见的问题。见Inline event handler not working in JSFiddle

在您的情况下,JS错误控制台会打印一条消息,按下按钮时,calculate未定义。

如果您更改JSFIDDLE的Javascript部分以显式定义window.calculate,它将起作用。

像这样:

window.calculate = function(){

而不是function calculate(){...

http://jsfiddle.net/nqb4wpnr/3/