简体   繁体   中英

JavaScript adding and removing <tr> with EventListener and jQuery

Apologies for the very messy code. I'm confused by where my $().ready(function() and individual functions should be placed.

What works: 1) $(".calc").change(function() - this updates a span and divs with data selected from a table populated from a database 2) When the page is loaded, before the $(".calc").change(function() is called the function addRow(e) manages to write "hey" to the console log, but fails with ReferenceError: Can't find variable: tbody addRow (furniture-product.php, line 396) . Once the $(".calc").change(function() is run, the console log no longer works

What does not work: 1) function addRow(e) 2) function removeRow(e)

I'm certain it's a case of having something small in the wrong place, but I have tried moving parts of the script around but with no success.

$().ready(function () {

    "use strict";
    var tbody = document.getElementById("the-tbody");

    document.getElementById("btn-add").addEventListener("click", addRow, false);

    tbody.addEventListener("click", removeRow, false);


    var radios = $('input[type=radio]');
    radios.on('change', function () {
        radios.each(function () {
            var radio = $(this);
            radio.closest('.article-option')[radio.is(':checked') ? 'addClass' : 'removeClass']('highlight');
        });
    });


    $(".calc").change(function () {
        calctotal()

    });

});



function addRow(e) {
    console.log("hey");
    var product_id = $('input[name="product_name"]').val();
    var product_price = $('input[name="product_price"]').val();
    var row = document.createElement('tr');
    row.innerHTML = '<td><input type="hidden" name="item_id[]" value="' + product_id + '"><p>' + name + '</p><input type="hidden" name="price[]" value="' + product_price + '" class="price">&pound;<span id="amount" class="amount">0</span> <span class="remove">[x]</span></td>';
    tbody.appendChild(row);
    update_amounts();
}



function removeRow(e) {
    var elm;
    for (elm = e.target; elm !== this; elm = elm.parentNode) {
        if (/\bremove\b/.test(elm.className)) {
            removeElement(elm.parentNode);
            e.stopPropagation();
            return;
            update_amounts();
        }
    }
}

function calctotal() {
    var total = 0;

    var radios = $('input[type=radio]');

    radios.each(function () {
        var radio = $(this);
        radio.closest('.article-option')[radio.is(':checked') ? 'addClass' : 'removeClass']('highlight');

    });



    $(".calc:checked").each(function () {
        var a = this.value.split(",");
        total += parseFloat(a[0]);
        name = (a[1]);
        image = (a[2]);
        curtainid = (a[3]);
        curtaindesc = (a[4]);


        $("span.img").html('<div class="row curtain-img"><img src="images/furniture/' + image + '" class="img-responsive img-rounded" style="border: 5px solid #5f4865"></div>');


        $("div#product_name").html('<input type="hidden" name="product_name" value="' + curtainid + '">' + name + '');
        $("div#product_desc").html('' + curtaindesc + '');
        $("div#product_add").html('<input type="button" id="btn-add" value="Add">');
        $("div#product_price").html('<input type="hidden" name="product_price" value="' + total.toFixed(2) + '"><strong>&pound;' + total.toFixed(2) + '</strong>');

    });


}

Quite simply the HTML is

<table id="myTable">

<tbody id="the-tbody"></tbody>

</table>

<input type="button" id="btn-add" value="Add">

JS Fiddle: http://jsfiddle.net/pw25p3qt/

Ahhh.. You all doing correct. Just define your variable just on top, ie. before document.ready().

  var tbody=null;
  $().ready(function () {

"use strict";
tbody = document.getElementById("the-tbody");
 document.getElementById("btn-add").addEventListener("click", addRow, false);

tbody.addEventListener("click", removeRow, false);


var radios = $('input[type=radio]');
radios.on('change', function () {
    radios.each(function () {
        var radio = $(this);
        radio.closest('.article-option')[radio.is(':checked') ? 'addClass' : 'removeClass']('highlight');
    });
   });


  $(".calc").change(function () {
    calctotal()

  });

  });

There's a number of issues with the code - too many to list.

Here's a working version, with some of the original code stripped out, leaving just the raw add/remove functionality.

HTML

<table id="myTable" border>
    <thead>
        <tr><th>Product</th><th>Unit Price</th><th>Quantity</th><th>Total Price</th><th>Remove</th></tr>
    </thead>
    <tbody id="the-tbody"></tbody>
    <tr><td id="totalCell" colspan="5">Total: &pound;<span id="total"></span></td></tr>
</table>
<input type="button" id="btn-add" value="Add" />

Javascript

$(function() {
    "use strict";
    $("#btn-add").on('click', addRow);
    var tbody = $("#the-tbody").on('click', '.remove', removeRow);//delegate click handling to the tbody element.
    calc();

    function calc() {
        var sum = 0;
        $('tr.product').each(function() {
            var qty = Number($(this).find('.qty').text()),
                price = Number($(this).find('.price').text()),
                amount = (qty * price).toFixed(2);
            $(this).find('.amount').text(amount);
            sum += Number(amount);
        });
        $('#total').text(sum.toFixed(2));
    }
    function addRow(e) {
        $('<tr class="product"><td>Sample Product</td><td>&pound;<span class="price">1.00</span></td><td><span class="qty">1</span></td><td>&pound;<span class="amount"></span></td><td><span class="remove">[x]</span></td></tr>').appendTo(tbody);
        calc();
    }
    function removeRow(e) {
        $(this).closest("tr").remove();
        calc();
    }
});

DEMO

Note how the Remove buttons' click action is delegated to the tbody element. This is necessary to ensure that every remove button that is added later (as part of a product row) has the required action without the need to attach the click handler individually.

Note also that all the worker functions, addRow() , removeRow() and calc() are now defined inside the $(function() {}) structure. This ensures that vars such as tbody remain in scope (without resorting to the global scope).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM