v k
v k

Reputation: 15

Add multiple divs inside the td on keypress jQuery

I have a input text box inside a div which is in a td, now when the user enters some text and press enter it should add an additional div with input box to the same td. The goal is to have multiple values in subsequent rows.

I'm able to add the div on keypress but the problem here is I'm not able to make the keypress fire only once. I have used flag to make it fire only once but it didn't work in my case.

Before the keypress event

<div id="grid">
<table>
<tr>
<td class="first-row">
<div><input class ="td-input"></input></div>
</td>
</tr></table>

After adding the div on key press dom will be like below

<div id="grid">
<table>
<tr>
<td class="first-row">
<div><input class ="td-input"></input></div>
<div><input class="td-input"></input></div>
</td>
</tr></table>

JQuery

$('#grid').on('keypress','td.first-row > div input.td-input', 
function(event){
var key = (event.keyCode ? event.keyCode : event.which);
var currentTD,addDiv;
if(key == '13'){
currentTD = $(this).closest('td');
addDiv = '<div><input class="td-input"></input></div>';
currentTD.append(addDiv);
}
});

I want 'div' to be added only once for each keypress on the input text box. With my code, 2 divs will be added if press enter twice.

Please refer the below image for output.

$('#grid').on('keypress', 'td.first-row > div input.td-input', function(event){
				var key = (event.keyCode ? event.keyCode : event.which);
				var currentTD,addDiv;
				if(key == '13'){
					currentTD = $(this).closest('td');
					addDiv = '<div class="additional-row"><input class="td-input"></input></div>';
					currentTD.append(addDiv);
			}
		});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="grid">
<table>
<tr>
<td>
<div><input class ="td-input" placeholder="Enter here column 1"></input></div>
</td>
<td class="first-row">
<div><input class ="td-input" placeholder="Enter here column 2"></input></div>
</td>
</tr>
</table>

Upvotes: 1

Views: 949

Answers (3)

Kamil Kiełczewski
Kamil Kiełczewski

Reputation: 92617

try to use <template> tag

let data = [''];

function setValue(inp, i) {
  data[i] = inp.value;
}

function add(e,i) {
  if (e.key != 'Enter' || i+1<data.length) return;
  data.splice(i+1,0,'');
  show(data);
  cell.children[i+1].children[0].focus();
}

function show(data) {
  let t= item.innerHTML;
  let inj = (s,o)=>s.replace(/\${(.*?)}/g,(x,g)=>o[g]);
  cell.innerHTML=data.map((v,i)=>inj(t,{val:v.replace(/"/g,"&quot;"),i})).join('')
}


show(data);
td { border: 1px solid black; }
<div id="grid">
  <table>
    <tr>
      <td class="first-row" id="cell"></td>
    </tr>
  </table>
</div>

<template id="item">
  <div>
    <input 
      class="td-input" 
      onkeypress="add(event,${i})" 
      oninput="setValue(this,${i})" 
      value="${val}" />
  </div>
</template>

Upvotes: 0

Taplar
Taplar

Reputation: 24965

If you want to only allow a single enter on an input to insert a new input, since you are already using a delegate, you can change it to test that the input does not have a class. Once the event handler is processed for an input, by adding the class to it, you ensure that it will not be repeated for future enters.

$('#grid').on('keypress', 'td.first-row > div input.td-input:not(.processed)', function(event) {
  var key = (event.keyCode ? event.keyCode : event.which);

  if (key == 13) {
    var $this = $(this);
    var $td = $this.closest('td');
    
    $td.append('<div class="additional-row"><input class="td-input"></input></div>');
    $this.addClass('processed');
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="grid">
  <table>
    <tr>
      <td>
        <div><input class="td-input" placeholder="Enter here column 1"></input>
        </div>
      </td>
      <td class="first-row">
        <div><input class="td-input" placeholder="Enter here column 2"></input>
        </div>
      </td>
    </tr>
  </table>

Upvotes: 1

Scott Marcus
Scott Marcus

Reputation: 65845

You just use a named event handler and then the .off() JQuery method to de-register the previously registered handler just before it completes.

Also, keypress is the wrong event for testing the ENTER key (is doesn't fire for non-printable characters). For that, use keydown.

Lastly, the input element doesn't have a closing tag (</input>). That's invalid HTML.

$('td.first-row > div input.td-input').on('keydown', makeInput);

function makeInput(event){
  var key = event.keyCode || event.which;  // Just need to check which one exists
  if(key == '13'){
    // Doesn't make sense to set up variables for values you'll only use once
    $(this).closest('td').append('<div><input class="td-input"></div>');
    
    // Just de-register the currently registered callback
    $('td.first-row > div input.td-input').off('keydown', makeInput);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="grid">
  <table>
    <tr>
      <td class="first-row">
        <div><input class ="td-input"></div>
      </td>
    </tr>
  </table>
</div>

Upvotes: 0

Related Questions