Ad

Cannot Read Property "name" Of Undefined

- 1 answer

I have a bit of an odd "bug" (quotations because it's not breaking anything, it's just an error in the console).

I have a website that simulates a retail website. When you click on an item, a div pops up asking you if you want to add it to the cart. If you press confirm, it sends the products name and price to a function that adds it to a EasyUI datagrid, as seen here:

Checking if product has been clicked:

$(document).on('click', '.item', function() {
        if (ismobile) {
            price = $(this).find('p.title').attr("data");
            name = $(this).find('p.title').html();
            image = $(this).find('img').attr("src");            

            mobileproducts(price, name, image);
        }
    });

Checking if"Add to cart" has been clicked:

$(document).on('click', "#mob_add", function() {
        name = $(".mob_title").html();
        //price = $(".mob_price").html();

        addProduct(name, parseFloat(price));
        console.log(name + parseFloat(price));
        $("#popup").hide();
    });

And the function where it adds it to a Datagrid (the cart).

function addProduct(name, price) {
    function add(){
        for (var i=0; i<data.total; i++) {
            var row = data.rows[i];
            if(row.name == name) {             ** ERROR HAPPENS ON THIS LINE **
                row.quantity++;
                return;
            }
        }
        data.total++;
        data.rows.push({
            name:name,
            quantity:1,
            price:price
        });
    }
    add();
    ...
}

Now as I've mentioned, this works perfectly fine, no problems. The item gets added to the cart, and if there's more than one of that item, the item quantity gets increased. This also works fine if you drag the product to the cart instead of clicking on it, printing no errors.

A demo can be seen here: (note, to click on a product, window must be < 900px width, drag and drop needs window to be > 900px)

What I want to know is, why this error is happening.

EDIT: I've also found that, when you first load the page and add a product, no error is printed, but adding a product after that, causes an error. Also happens if you reload the page, open a product dialog, close it without adding to the cart, and then adding any product to the cart.

Ad

Answer

After helpful comments and necessary downvotes I looked at the debugger again. It seems that using the dialog causes one extra iteration over the products ( and the last row is undefined).

There may be a chance that you are calling the add() function two times.

Update:

Using firefox I saved the webpage (using complete) temporarily on my local drive.

I noticed that the function handling the click event for add (in the dialog) shows my alert test two times instead of one.

$(document).on('click', "#mob_add", function() {
        name = $(".mob_title").html();
        //price = $(".mob_price").html();

    alert("TEST"); // Should run only once
    addProduct(name, parseFloat(price));
    console.log(name + parseFloat(price));
    $("#popup").hide();
});

Update: You are re-using the same dialog and are re-adding continuously new click handlers to the document object using a selector.

If mobileproducts is called every time the dialog appears, an additional click handler is binded every time.

    function mobileproducts(price, name, image) {
        $("#popup").show();
        $(".mob_title").html(name);
        $("#popup > img").attr("src", image);
        $(".mob_price").html("£" + price);


        $(document).on('click', "#mob_close", function() {
                $("#popup").hide();


    });
     alert('binding again');
        $(document).on('click', "#mob_add", function() {
            name = $(".mob_title").html();
        //price = $(".mob_price").html();

        alert("TEST");
        addProduct(name, parseFloat(price));
        console.log(na

me + parseFloat(price));
            $("#popup").hide();
        });

        console.log("CLICKED: " + name + " WITH PRICE: " + price + " AND IMAGE URL: " + image);
    }

Fix

The quickest fix would be to stop binding first on document, and switch to using the popup (or even the button). Additionally, before finding a new function, you should unbind the previous.

Working example below:

function mobileproducts(price, name, image) {
    $("#popup").show();
    $(".mob_title").html(name);
    $("#popup > img").attr("src", image);
    $(".mob_price").html("£" + price);
    //alert("TEST2");

    $("#popup").unbind('click');

    $("#popup").on('click', "#mob_close", function() {
        $("#popup").hide();
    });
    $("#popup").on('click', "#mob_add", function() {
        name = $(".mob_title").html();
        //price = $(".mob_price").html();


        addProduct(name, parseFloat(price));
        console.log(name + parseFloat(price));
        $("#popup").hide();
    });

    console.log("CLICKED: " + name + " WITH PRICE: " + price + " AND IMAGE URL: " + image);
}

A better fix would be to even BIND only once using on, and refactor your code to use singleton parameters that are available to that function.

Ad
source: stackoverflow.com
Ad