ThanksInAdvance
ThanksInAdvance

Reputation: 547

Input in HTML Table

I used a form and some JavaScript to take data from an uploaded CSV file and created an HTML table based on that data. In addition, I added an extra column for user input. My issues is that I cannot figure out a manageable way to take the user input at each input tag and replace the input tag with the text they entered.

Code

This is the code behind the table. When I implement it, there will not be a finite number of rows though. Instead the amount of rows will be based on the data from the CSV file.

var table = document.createElement('table');
table.classList.add('table');

var thead = document.createElement('thead');
var headRow = document.createElement('tr');
var columnNames = ["Col1", "Col2", "Col3", "Col4"];

for (var i = 0; i < 4; i++) {
  var th = document.createElement('th');
  th.appendChild(document.createTextNode(columnNames[i]));
  headRow.appendChild(th);
}

thead.appendChild(headRow);

var tbody = document.createElement('tbody');

for (var i = 0; i < 10; i++) {
  var tr = document.createElement('tr');

  for (var j = 0; j < 4; j++) {
    var td = document.createElement('td');

    if (j == 3) {
      td.classList.add("input");
      var input = document.createElement('input');
      input.type = "text";
      td.appendChild(input);
      tr.appendChild(td);
      continue;
    }
    td.appendChild(document.createTextNode("x"));
    tr.appendChild(td);
  }

  tbody.appendChild(tr);
}

table.appendChild(thead);
table.appendChild(tbody);
document.body.appendChild(table);
td { width: 25vw; }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>

Table Example

Table Example

Upvotes: 1

Views: 26903

Answers (2)

If you consider the user is done entering the text when they switch to another input, you can attach a blur listener to each input.

<input type="text" onblur="z(this)">

z = function(input){
  var newEl = document.createElement('span');
  newEl.innerHTML = input.value;
  input.parentNode.replaceChild(newEl, input);
}

here is fiddle https://jsfiddle.net/nqmhpp88/

Upvotes: 0

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48600

You can toggle the cells between input and text cells by doing the following.

function toggleInputCells(button) {
  var cells = document.getElementsByClassName('input');
  
  for (var i = 0; i < cells.length; i++) {
    var cell = cells[i];
    var input = cell.getElementsByTagName('input')[0];

    if (input != null) {
      var text = input.value;
      cell.innerHTML = text;
    } else {
      var text = cell.innerHTML;
      cell.innerHTML = '';
      var input = document.createElement('input');
      input.type = "text";
      input.value = text;
      cell.appendChild(input);
    }
  }
}


var rows = 10;
var cols = 4;

var table = document.createElement('table');
table.classList.add('table');

var thead = document.createElement('thead');
var headRow = document.createElement('tr');
var columnNames = ["Col1", "Col2", "Col3", "Col4"];

for (var i = 0; i < 4; i++) {
  var th = document.createElement('th');
  th.appendChild(document.createTextNode(columnNames[i]));
  headRow.appendChild(th);
}

thead.appendChild(headRow);

var tbody = document.createElement('tbody');

for (var i = 0; i < rows; i++) {
  var tr = document.createElement('tr');

  for (var j = 0; j < cols; j++) {
    var td = document.createElement('td');

    if (j == 3) {
      td.classList.add("input");
      var input = document.createElement('input');
      input.type = "text";
      input.value = 'Row #' + (i + 1); // Add a value?
      td.appendChild(input);
      tr.appendChild(td);
      continue;
    }
    td.appendChild(document.createTextNode("x"));
    tr.appendChild(td);
  }

  tbody.appendChild(tr);
}

table.appendChild(thead);
table.appendChild(tbody);
document.body.appendChild(table);
td { width: 25vw; }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>

<input type="button" value="Toggle Input" onClick="toggleInputCells(this)" />

You could also listen to when the user clicks down on the cell and convert it to an input. After they leave focus, you can convert it back into a regular text cell.

function makeEditable(e) {
  var cell = e.target;
  if (cell.dataset.editing !== 'true') {
    cell.dataset.editing = true;
    var text = cell.innerHTML;
    cell.innerHTML = '';
    var input = document.createElement('input');
    input.addEventListener('blur', makeNonEditable);
    input.type = "text";
    input.value = text;
    cell.appendChild(input);
  }
}

function makeNonEditable(e) {
  var input = e.target;
  var text = input.value;
  var cell = input.parentElement;
  if (cell.dataset.editing === 'true') {
    cell.dataset.editing = false;
    cell.innerHTML = text;
  }
}

var rows = 10;
var cols = 4;

var table = document.createElement('table');
table.classList.add('table');

var thead = document.createElement('thead');
var headRow = document.createElement('tr');
var columnNames = ["Col1", "Col2", "Col3", "Col4"];

for (var i = 0; i < 4; i++) {
  var th = document.createElement('th');
  th.appendChild(document.createTextNode(columnNames[i]));
  headRow.appendChild(th);
}

thead.appendChild(headRow);

var tbody = document.createElement('tbody');

for (var i = 0; i < rows; i++) {
  var tr = document.createElement('tr');

  for (var j = 0; j < cols; j++) {
    var td = document.createElement('td');

    if (j == 3) {
      td.addEventListener('mousedown', makeEditable); // Add mousedown listener.
      td.innerHTML = 'Row #' + (i + 1);               // Add a value?
      tr.appendChild(td);
      continue;
    }
    td.appendChild(document.createTextNode("x"));
    tr.appendChild(td);
  }

  tbody.appendChild(tr);
}

table.appendChild(thead);
table.appendChild(tbody);
document.body.appendChild(table);
td { width: 25vw; }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>

Upvotes: 2

Related Questions