Why can't I get my images to appear in table c

2019-08-31 05:35发布

问题:

I want to add a new image in each cell of the new table and give it the same source as the old table, and then make it clickable. Firstly, I did this:

function showData() {
  if (localStorage.getItem(name) !== null) {
    var showme = localStorage.getItem(name);
    alert("I got the table");
    var newTable = document.createElement('table');
    newTable.innerHTML = showme;
    newTable.id = "newTable";

    newNumRows = newTable.getElementsByTagName('tr').length;
    newNumCells = newTable.getElementsByTagName('td').length;
    newNumCols = newNumCells / newNumRows;
    alert(newNumRows);
    alert(newNumCells);
    alert(newNumCols);

    var newImages = newTable.getElementsByTagName('img');
    for (var i = 0; i < newImages.length; i += 1) {
      var picSource = newImages[i]['src'];
      console.log(picSource);
    }

    function addNewImage(newNumCols) {
      var newImg = new Image();
      newImg.src = picSource;
      col.appendChild(newImg);
      newImg.onclick = function() {
        alert("WOW");
      };
    }

    for (r = 0; r < newNumRows; r++) {
      row = newTable.insertRow(-1);

      for (c = 0; c < newNumCols; c++) {
        col = row.insertCell(-1);
        addNewImage(newNumCols);
      }
    }

    var showIt = document.getElementById('holdTable');
    showIt.appendChild(newTable);
  }
}

This works to a certain extent, but, unfortunately, only the last image was displaying. So, I did a bit of looking around and I think it has to do with closure (apologies for any duplication), but it's a concept I am really struggling to understand. So then I tried this:

function showData() {
  if (localStorage.getItem(name) !== null) {
    hideTaskForm();
    var showme = localStorage.getItem(name);
    var oldTable = document.createElement('table');
    oldTable.innerHTML = showme;
    newTable = document.createElement('table');
    newTable.id = "newTable";
    var i, r, c, j;

    newNumRows = oldTable.getElementsByTagName('tr').length;
    newNumCells = oldTable.getElementsByTagName('td').length;
    newNumCols = newNumCells / newNumRows;
    var newTableCells = newTable.getElementsByTagName('td');
    var getImages = oldTable.getElementsByTagName('img');

    for (r = 0; r < newNumRows; r++) {
      row = newTable.insertRow(-1);

      for (c = 0; c < newNumCols; c++) {
        makeNodes = row.insertCell(-1);
      }
    }

    for (var j = 0; j < newTableCells.length; j++) {
      var theNodeImage = document.createElement("img");
      newTableCells[j].appendChild(theNodeImage);
      alert(newTableCells[j].innerHTML); //This gives me img tags
    }

    for (i = 0; i < getImages.length; i += 1) {
      var oldSource = getImages[i]['src']; //gets the src of the images from the saved table
      console.log(oldSource);
      //alert(oldSource);//successfully alerts the image paths
      var newPic = new Image(); //creates a new image

      (function(newPic, oldSource) {
        newPic.src = oldSource;
        alert(newPic.src); //gives the same image paths
        newTable.getElementsByTagName('img').src = newPic.src; //This doesn't work - table is blank???
      })(newPic, oldSource);
    }

    var showIt = document.getElementById('holdTable');
    showIt.appendChild(newTable);
  }
}

Now, this doesn't throw any errors. However, nor does it fill the table. It does give me the source and I think I have created the new image objects to attach to the img tags in the newTableCells, but the table is showing up blank. I don't know where I am going wrong. All help really welcome.

Note: Even as a hobbyist, even I know there are probably tons of more efficient ways to do this, but I purposely did it this way to try and help me understand the logic of each step I was taking.

回答1:

In your code you have:

var newImages = newTable.getElementsByTagName('img');

for (var i = 0; i < newImages.length; i += 1) {
  var picSource = newImages[i]['src'];
  console.log(picSource);
}

At the end of this, picSource has the value of the last image's src attribute. Then there is:

function addNewImage(newNumCols) {
  var newImg = new Image();
  newImg.src = picSource;
  col.appendChild(newImg);
  newImg.onclick = function() {
    alert("WOW");
  };
}

A value is passed to newNumCols but not used in the function. The value of picSource comes from the outer execution context and is not changed, so it's still the last image src from the previous for loop.

for (r = 0; r < newNumRows; r++) {
  row = newTable.insertRow(-1);

  for (c = 0; c < newNumCols; c++) {
    col = row.insertCell(-1);
    addNewImage(newNumCols);
  }
}

This loop just keeps calling addNewImage with a single parameter that isn't used in the function, so you get the same image over and over.

For the record, the addNewImage function does have a closure to picSource, but it also has a closure to all the variables of the outer execution contexts. This isn't the issue, though it perhaps masks the fact that you aren't setting a value for picSource on each call, so you get the left over value from the previous section of code.

You haven't provided any indication of the content of showme, so it's impossible to determine if this approach will work at all.

Note

Where you have:

var showme = localStorage.getItem(name);
alert("I got the table");
var newTable = document.createElement('table');
newTable.innerHTML = showme;
newTable.id = "newTable";

IE does not support setting the innerHTML property of table elements, though you can create an entire table as the innerHTML of some other element and set the innerHTML of a cell (tr, th). If you want to use this approach, consider:

var div = document.createElement('div');
div.innerHTML = '<table id="newTable">' + showme + '<\/table>';
var newTable = div.firstChild;