0

I'm trying to make this anchor element change its text when you click on it, but it just won't work.

The element in question is part of a set of other anchors inside a table, according to the following structure:

  • table
    • row
      • cell → anchor
      • cell → anchor
      • cell → anchor
    • row
      • cell → anchor
      • cell → anchor
      • cell → anchor
    • row
      • cell → anchor
      • cell → anchor
      • cell → anchor

And it's populated by the following script:

var initButtonAction = function() {
    var table = document.getElementById("Table");
    var number = document.getElementById("Number");
    var size = parseInt(number.value);

    clearChildren(table); // A function I improvised to clear an element's contents

    for (var i = 0; i < size; i++) {
        var row = document.createElement("tr");
        for (var j = 0; j < size; j++) {
            var cell = document.createElement("td");
            var anchor = document.createElement("a");
            var text = document.createTextNode("O");

            anchor.id = "Id_"+i+"_"+j;
            anchor.addEventListener("click", function(e) {
                    var newValue = document.createTextNode(parseInt(Math.random()*10)+1);

                    clearChildren(anchor); 
                    anchor.appendChild(newValue);

                    e.preventDefault();
                }, false);

            anchor.appendChild(text);
            cell.appendChild(anchor);
            row.appendChild(cell);
        }
        table.appendChild(row);
    }
}

The problem is that when I click on any anchor, only the last one gets changed, for example:

O   O   O   O   O
O   O   O   O   O
O   O   O   O   O
O   O   O   O   O
O   O   O   O   O

Changes to this:

O   O   O   O   O
O   O   O   O   O
O   O   O   O   O
O   O   O   O   O
O   O   O   O   8

No matter what "O" I press.

However, I did the same on another project (using the same symbol in the event listener function) and it worked pretty fine, the code is as follows:

var row = document.createElement('tr');

// Create and initialize other elements

row.id = 'Product'+globalProductsIdCounter+'Row';

// Some more irrelevant processing

opcAnchor.id = 'Product'+globalProductsIdCounter+'OpcAnchor';
opcAnchor.href = '#';
opcAnchor.addEventListener('click', function() {
        ProductsTableBody.removeChild(row);
    }, false
    );
opcAnchor.appendChild(document.createTextNode('(eliminar)'));

Why does the first example doesn't work?

arielnmz
  • 8,354
  • 9
  • 38
  • 66
  • possible duplicate of [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Amadan Nov 28 '14 at 04:38
  • 1
    In your first snippet, you need to make a closure: `(function(anchor) { anchor.addEventListener( ... ) })(anchor);` In your second snippet, you're not in a loop, `opcAnchor` does not change, and you're safe. – Amadan Nov 28 '14 at 04:40

1 Answers1

1

Just do a small change in your code. Replace anchor.appendChild(newValue); with this.appendChild(newValue);. Note that anchor variable will hold the last element after iteration.

anchor.addEventListener("click", function(e) {
       var newValue = document.createTextNode(parseInt(Math.random()*10)+1);
       clearChildren(anchor); 
       this.appendChild(newValue);
       e.preventDefault();
}, false);
Gilsha
  • 14,431
  • 3
  • 32
  • 47
  • 1
    While this is certainly the best solution to the problem (well, it would be if you didn't miss the `anchor` in `clearChildren(anchor)` :P ), OP asked "Why does the first example doesn't work?" :) I'd say teaching about joys and pitfalls of closures is more important than solving the immediate issue. – Amadan Nov 28 '14 at 04:45
  • Thank you, @Amadan, that's certainly what I like so much about this community: information. But I also appreciate Gilsha's approach to this issue. Thank you both. – arielnmz Nov 28 '14 at 04:47
  • Oh, no worries. I did upvote Gilsha's answer, because that's exactly what your code needs. What *you* need though is in the duplicate question link. – Amadan Nov 28 '14 at 04:48
  • That's right, also, I guess I wouldn't be able to find out what the issue was without asking first, or mayble I'd have spent many days looking into it. Thank you again! – arielnmz Nov 28 '14 at 04:50