zoukankan      html  css  js  c++  java
  • 从<<JavaScript权威指南>>抄下来的一个例子

    11111111

    <!DOCTYPE html>
    <html>
    <head>
    <title>JavaScript Loan Calculator</title>
    <style> /* 这是一个CSS样式:定义了程序输出的样式 */
    .output    {font-weight: bold;} /* 计算结果,定义为粗体 */
    #payment {text-decoration:    underline;} /* 定义id="payment"的元素样式 */
    #graph {border: solid black 1px;} /* 定义id="graph"的图表边框为1px */
    th,td {vertical-align: left;} /* 定义表格单元格对其方式,为左对齐 */
    </style>
    </head>
    <body>
    <!--  PDF的文档在29页
    这是一个HTML表格,其中包含的<input>元素,可以用来输入数据
    程序将在<span>元素中显示计算结果,这些元素都具有类似"interset"和"years"的id
    这些id将在表格下面的JavaScript代码中用到。我们也应注意到,有一些input元素
    定义了“onchange”或“onclick”的事件处理程序,以便用户在输入数据或点击input时
    执行指定的JavaScript代码段
    -->
        <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="450" height="250"></canvas>
                </td>
            </tr>
            <tr>
                <td>Annual interset (%):</td>
                <td><input id="apr" onchange="calculate();"></td>
            </tr>
            <tr>
                <td>Repayment period (years):</td>
                <td><input id="years" onchange="calculate();"></td>
            </tr>
            <tr>
                <td>Zipcode (to find lenders):</td>
                <td><input id="zipcode" onchange="calculate();"></td>
            </tr>
            <tr>
                <td>Approximate Payments:</td>
                <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>
                <td>Sponsors:</td>
                <td colspan=2>
                    Apply for your loan with one of these fine lenders:
                    <div id="lenders">
                </td>
            </tr>
        </table>
        <!-- 随后是JavaScript代码, 这些代码内嵌在了一个<script>标签里面  page30 -->
        <!-- 通常情况下,这些脚本代码应当放在<head>标签中 -->
        <!-- 将JavaScript代码放HTML代码之后仅仅为了便于理解 -->
        <script>
        "use strict"; //如果浏览器支持的话,则开户ECMAScript 5的严格模式
        /*
        * 这里的脚本定义了caculate()函数, 在HTML代码中绑定事件处理程序时会调用它
        * 这个函数从<input>元素中读取数据,计算代款赔付信息,并将结果信息显示在<span>元素中
        * 同样,这里还保存了用户数据、展示了放贷人链接并绘制出了图表
        */
        function calculate(){
            // 查找文档中用于输入输出的元素
            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");
            
            // 假设所有的输入都是合法的, 将从input元素中获取输入数据
            // 将百分比格式转换为小数格式, 并从年利率转换为月利率
            // 将年度赔付转换为月度赔付
            var principal = parseFloat(amount.value);
            var interest = parseFloat(apr.value) / 100 / 12;
            var payments = parseFloat(years.value) * 12;
            
            // 现在计算月度赔付的数据
            var x = Math.pow(1 + interest, payments);  // Math.pow() 进行幂次运算
            var monthly = (principal * x * interest) / (x - 1);
            
            // 如果结果没有超过JavaScript能表示的数字范围,且用户的输入也正确
            // 这里所展示的结果就是合法的
            if (isFinite(monthly)){
                // 将数据填充至输出字段的位置,四舍五入到小数点后两位数字
                payment.innerHTML = monthly.toFixed(2);
                total.innerHTML = (monthly * payments).toFixed(2);
                totalinterest.innerHTML =((monthly * payments) - principal).toFixed(2);
    
                // 将用户的输入数据保存下来, 这样下次访问时也能取到数据
                save(amount.value, apr.value, years.value, zipcode.value);
    
                // 找到并展示本地放贷人, 但忽略网络错误
                try{
                    getLenders(amount.value, apr.value, years.value, zipcode.value);
                }
                catch(e){
                    // 忽略这些异常
                }
                
                // 最后, 用图表展示贷款余额、利息和资产收益
                chart(principal, interest, monthly, payments);
            }
            else {
                // 计算结果不是数字或者无穷大, 意味着输入数据是非法或不完整的
                // 清空之前的输出数据
                payment.innerHTML = "";        // 清空元素的文本内容
                total.innerHTML = "";
                totalinterest.innerHTML = "";        // 不传参数的话就是清除图表
                chart();
            }
        }
    
        // 将用户的输入保存至localStorage对象的属性中   page31
        // 这些属性在再次访问时还会继续保持在原位置
        // 如果你在浏览器中,按照file://URL的方式直接打开本地文件
        // 则无法在某些浏览器中使用存储功能(比如FireFox)
        // 而通过HTTP打开文件是可行的
        function save(amount, apr, years, zipcode){
            if(window.localStorage){    // 只有在浏览器支持的时候才运行这里的代码
                localStorage.loan_amount = amount;
                localStorage.loan_apr = apr;
                localStorage.loan_years = years;
                localStorage.loan_zipcode = zipcode;
            }
        }
    
        // 在文档首次加载时,将会尝试还原输入字段
        window.onload = function(){
            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;
            }
        };
    
        // 将用户的输入发送至服务器端脚本,(理论上)将返回一个本地放贷人的链接列表,
        // 在这个例子并没有实现这种查找放贷人的服务
        // 但如果该服务存在, 该函数会使用它
        function getLenders(amount, apr, years, zipcode){
            // 如果浏览器不支持XMLHttpRequest对象, 则退出
            if (!window.XMLHttpRequest) return;
    
            // 找到要显示放贷人列表的元素
            var ad = document.getElementById("lenders");
            if (!ad) return;    // 如果返回为空, 则退出
    
            // 将用户的输入数据进行URL编码, 并作为查询参数附加在URL里
            var url = "getLenders.php" +                // 处理数据的URL地址
            "?amt=" + encodeURIComponent(amount) +        // 使用查询串中的数据
            "&apr=" + encodeURIComponent(apr) +
            "&yrs=" + encodeURIComponent(years) +
            "&zip=" + encodeURIComponent(zipcode) ;
    
            // 通过XMLHttpRequest对象来提取返回数据
            var req = new XMLHttpRequest();        // 发起一个新的请求
            req.open("GET", url);    // 通过URL发起一个HTTP GET请求
            req.send(null);        //不带任何正文发送这个请求
    
            // 在返回数据之前, 注册了一个事件处理函数, 这个处理函数
            // 将会在服务器的响应返回至客户端的时候调用
            // 这种异步编程框在客户端JavaScript中是非常常见的
            req.onreadystatechange = function(){
                if (req.readyState == 4 && req.status == 200){
                    // 如果代码运行到这里,说明我们得到了一个合法且完整的HTTP响应
                    var response = req.responseText;    // HTTP响应是以字符串的形式呈现的
                    var lenders = JSON.parse(response);    // 将其解析为JS数组  -- page32
    
                    // 将数组中的放贷人对象转换为HTML字符串形式
                    var list = "";
                    for (var i=0; i<lenders.length; i++){
                        list += "<li><a href='" + lenders[i].url + "'>" + 
                        lenders[i].name + "</a>"; 
                    }
    
                    // 将数据在HTML元素中呈现出来
                    ad.innerHTML = "<ul>" + list + "</ul>"
                }
            }
        }
    
        // 在HTML<cannas>元素中用图表展示月度贷款余额、利息和资产收益
        // 如果不传入参数的话,则清空之前的图表数据    
        function chart(principal, interest, monthly, Payments){
            var graph = document.getElementById("graph");    // 得到<canvas>标签
            graph.width = graph.width;    // 用一种巧妙的方法清除并重置画布
    
            // 如果不传入参数,或者浏览器不支持画布,则直接返回
            if (arguments.length == 0 || graph.getContext) return;
    
            // 获得画布元素的"context"对象,这个对象定义了一组绘画API
            var g = graph.getContext("2d");    // 所有的绘画操作都将基于这个对象
            var width = graph.width;
            height = graph.height;
    
            // 这里的函数作用是将付款数字和美元转换为像素
            function paymentToX(n){
                return n * width / payments;
            }
            function amountToY(a){
                return height - (a * height / (monthly * payments * 1.05));
            }
    
            // 付款数据是一条从(0,0)到(payments, monthly*payments) 的直线
            g.moveTo(paymentToX(0), amountToY(0));    // 从左下方开始
            g.lineTo(paymentToX(payments), amountToY(monthly * payments)); // 绘至右上方
            g.lineTo(paymentToX(payments), amountToY(0));    // 再至右下方
            g.closePath();    // 将结尾连接至开头
            g.fillStyle = "#f88";    // 亮红色
            g.fill();
            g.font = "bold 12px sans-serif";    // 定义一种字体
            g.fillText("Total Interest Payments", 20, 20);    // 将文字绘制到图例中
    
            // 很多资产数据并不是线性的, 很难将其反映至图表中
            var equity = 0;
            g.beginPath();        // 开始绘制新图形
            g.moveTo(paymentToX(0), amountToY(0));    // 从左下方开始
            for (var p=1; p<=payments; p++){
                // 计算出每一笔赔付的利息
                var thisMonthsInterest = (principal - equity) * interest;
                equity += (monthly - thisMonthsInterest);    // 得到资产额
                g.lineTo(paymentToX(p), amountToY(equity));    // 将数据绘制画布上
            }
            g.lineTo(paymentToX(payments), amountToY(0));    // 将数据线绘制至X轴 page33
            g.closePath();    // 将线条结尾连接至线条开头
            g.fillStyle = "green";    // 使用绿色绘制图形
            g.fill();    // 曲线之下的部分均填充
            g.fillText("Total Equity", 20, 35);
    
            // 再次循环, 余额数据显示为黑色粗线条
            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);    // 得到资产额
                g.lineTo(paymentToX(p), amountToY(bal));    // 数据连接至某点
            }
            g.lineWidth = 3;    // 将直线宽度加粗
            g.stroke();        // 绘制余额的曲线
            g.fillStyle = "black";    // 使用黑色字体
            g.fillText("Loan Balance", 20, 50);        //图例文字
    
            // 将年度数据在X轴做标记
            g.textAlign = "center";     // 文字居中对齐
            var y = amountToY(0);        // Y坐标设为0
            for (var year=1; year*12 <= payments; year++){    // 遍历每年
                var x = paymentToX(year * 12);    // 计算标记位置
                g.fillRect(x-0.5, y-3, 1, 3);    // 开始绘制标记
                if (year==1) {
                    g.fillText("Year", x, y-5);    // 在坐标轴标记
                }
                if (year%5 == 0 && year*12 !== payments){    // 每5年的数据
                    g.fillText(String(year), x, y-5);
                }
            }
    
            // 将赔付数额标记在右边界
            g.textAlign = "right";        // 文字右对齐
            g.textBaseline = "middle";    // 文字垂直居中
            var ticks = [monthly * payments, principal];    // 我们将要用的两个点
            var rightEdge = paymentToX(payments);        // 设置X坐标
            for (var i=0; i<ticks.length; i++){            // 对每两个点做循环
                var y = amountToY(ticks[i]);            // 计算每个标记的Y坐标
                g.fillRect(rightEdge-3, y-0.5, 3, 1);    // 绘制标记
                g.fillText(String(ticks[i].toFixed(0)), rightEdge-5, y);    // 绘制文本
            }
        }
        </script>
    </body>
    </html>

    222222

  • 相关阅读:
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
    Construct Binary Tree from Preorder and Inorder Traversal
    Construct Binary Tree from Inorder and Postorder Traversal
    Path Sum
    Symmetric Tree
    Solve Tree Problems Recursively
    632. Smallest Range(priority_queue)
    609. Find Duplicate File in System
    poj3159最短路spfa+邻接表
  • 原文地址:https://www.cnblogs.com/yimai-series/p/12216914.html
Copyright © 2011-2022 走看看