GORAGOD.com

การคำนวณราคาสินค้าอัตโนมัติขณะกรอก

การคำนวณราคาสินค้าโดยที่ไม่ต้อง Sumit นั้น มีเทคนิคง่ายๆ โดยที่ไม่ต้องพึ่งพา Ajax แต่อย่างใด (หลายๆคนคิดว่ามันต้องใช้ Ajax) เพราะหลักการของมันจริงๆแล้ว มันไม่จำเป็นต้องมีอะไรติดต่อกับ Server เลย เพียงแค่เราเตรียมข้อมูลที่จำเป็นเท่านั้น ซึ่งข้อมูลที่จำเป็นที่เราต้องเตรียมก็คือ ข้อมูลราคาสินค้าต่อหน่วย ส่วน จำนวนนั้นเราจะให้ User เป็นผู้กรอก

ในตัวอย่างนี้ผมจะนำเสนอแค่การเขียนโค้ดเพื่อคำนวณเท่านั้นนะครับ.. 

อย่างแรกเลยเรามาดูโค้ดฟอร์มกันก่อน
<form method="get" action="calc.php" id="calc_frm">
    <p>
        <input type="text" name="amount[]" value="1"> *
        <input type="text" name="price[]" value="10"> =
    <input type="text" name="sum[]"> </p>
    <p>
        <input type="text" name="amount[]" value="10"> *
        <input type="text" name="price[]" value="1"> =
        <input type="text" name="sum[]"> </p>
    <p>
        <input type="text" name="amount[]" value="10"> *
        <input type="text" name="price[]" value="1"> =
        <input type="text" name="sum[]"> </p>
</form>

ในตัวอย่างนี้ผมแบ่งช่องกรอกออกเป็น 3 แถว เพื่อแสดงให้เห็นว่าเราสามารถเขียนคำสั่งเพื่อจัดการข้อมูลทั้ง 3 แถวได้ในคราวเดียว ไม่ต้องมานั่งจัดการกับ input ทีละตัวหรือข้อมูลทีละชุด ซึ่งจะทำให้การเพิ่มหรือลดจำนวนแถวของข้อมูลสามารถทำได้สะดวก
/* ตัวเลขเท่านั้น */
var numberOnly = function (event) {
    var key = event.which || event.keyCode;
    if (!((key > 47 && key < 58) || key == 8 || key == 9 || key == 37 || key == 39)) {
        event.preventDefault();
    }
};
/* ตัวเลขและจุดเท่านั้น */
var currencyOnly = function (event) {
    var key = event.which || event.keyCode;
    if (!((key > 47 && key < 58) || key == 8 || key == 9 || key == 37 || key == 39 || key == 46)) {
        event.preventDefault();
    }
};

โค้ดด้านบนจะเป็นโค้ด Javascript สำหรับทำให้ input รับค่าเป็น ตัวเลขเท่านั้น (สำหรับจำนวนสินค้า) หรือ สามารถรับจุดทศนิยมได้ด้วย (สำหรับจำนวนเงิน)
/* หาผลคูณ */
function calc(inps) {
    var amount = parseFloat(inps[0].value);
    amount = isNaN(amount) ? 0 : amount;
    var price = parseFloat(inps[1].value);
    price = isNaN(price) ? 0 : price;
    inps[2].value = amount * price;
};

โค้ดด้านบน เป็นโค้ดส่วนคำนวณราคารวมในแต่ละแถว โดย input ในแต่ละแถว จะอยู่ในตัวแปรแอเรย์ inps โดยที่ inps[0] คือจำนวนสินค้า inps[1] คือราคาสินค้า และ inps[2] คือช่องเก็บผลรวมราคาสินค้าที่ได้จากการคำนวณ inps0]*inps[1]
// form, p
var frm = document.getElementById('calc_frm'),
    ps = frm.getElementsByTagName('p');
for (var i = 0; i < ps.length; i++) {
    // อ่าน input ทีละแถว
    var inps = ps[i].getElementsByTagName('input');
    (function (inps) {
        // จำนวน ตัวเลขเท่านั้น
        inps[0].addEventListener('keypress', numberOnly);
        // ราคา ตัวเลขและจุด
        inps[1].addEventListener('keypress', currencyOnly);
        // จำนวน คำนวนราคา
        inps[0].addEventListener('keyup', function () {
            calc(inps);
        });
        // ราคา คำนวนราคา
        inps[1].addEventListener('keyup', function () {
            calc(inps);
        });
        // สั่งคำนวณในครั้งแรก
        calc(inps);
    })(inps);
}

หัวใจของโค้ดอยู่ที่คำสั่งด้านบน หลักการก็คือ เราจะทำการอ่าน input ออกมาทีละแถว โดยอาศัย tag p เสร็จแล้วในแต่ละ tag p ค่อยไปอ่านเอา input ต่างๆ ออกมาอีกที ซึ่งจะทำให้เราได้ input ที่เกี่ยวข้องกันเท่านั้นออกมาในแต่ละรอบ
  • inps[0] หรือ input ตัวแรกที่อ่านเจอ ก็จะเป็นจำนวนสินค้า เราก็ส่งไปตรวจจับ event keypress เพื่อให้รับค่าการกดเฉพาะตัวเลขเท่านั้น ด้วยฟังก์ชั่น numberOnly
  • inps[1] หรือ input ตัวที่สอง ก็จะเป็นราคาสินค้า เราก็ส่งไปตรวจจับ event keypress เพื่อให้รับค่าการกดเฉพาะตัวเลขและจุดทศนิยม ด้วยฟังก์ชั่น currencyOnly
เมื่อมีการพิมพ์ตัวเลขลงในช่อง inps[0] และ inps[1] ก็จะมีการดักจับ event keyup เพื่อนำไปคำนวณราคารวม ที่ฟังก์ชั่น calc (ใช้ event keyup เนื่องจาก event นี้จะเกิดหลังจาก input ยอมรับค่าที่กรอกแล้ว หรือหลังจาก event keypress นั่นเอง)

ถ้าสังเกตุดีๆ โค้ดนี้จะมีจุดพิศดารอยู่หน่อยหนึ่งคือมีการใช้คำสั่งนี้ครอบอยู่
(function (inps) {
......
 })(inps);

การใช้คำสั่งนี้ เพื่อจำกัดโสคปของตัวแปร ซึ่งหากไม่มีการใช้คำสั่งนี้ ตัวแปร inps ที่ใช้ส่งค่าให้กับฟังก์ชั่น calc จะเป็นตัวแปรสุดท้ายเสมอ เพราะตัวแปรทั้งหมดอยู่ในสโคปเดียวกัน (ใน for) จึงมีการสร้างฟังก์ชั่นที่ไม่มีชื่อขึ้น

ตัวอย่าง