I have a form, and I want to be able to edit any part of that form by double clicking it. So going from this:
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
<tr>
<td>John Smith</td>
<td>johnsmith#gmail.com</td>
<td>+12345678</td>
</tr>
</table>
How can I by double-clicking an element, transform it to an input element?
For example: if I double click on John Smith, the HTML changes into this:
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
<tr>
<form action="index.php" method="post">
<td><input type="text" value="John Smith" name="name" /></td>
<td>johnsmith#gmail.com</td>
<td>+12345678</td>
</form>
</tr>
</table>
So now I can change John's name.
Does someone know how to do it?
Try this, fields from the second row are editable with dblclick
document.querySelectorAll("table tr:nth-child(2) td").forEach(function(node){
node.ondblclick=function(){
var val=this.innerHTML;
var input=document.createElement("input");
input.value=val;
input.onblur=function(){
var val=this.value;
this.parentNode.innerHTML=val;
}
this.innerHTML="";
this.appendChild(input);
input.focus();
}
});
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
<tr>
<td>John Smith</td>
<td>johnsmith#gmail.com</td>
<td>+12345678</td>
</tr>
</table>
How about that:
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
<tr>
<td id="name">John Smith</td>
<td>johnsmith#gmail.com</td>
<td>+12345678</td>
</tr>
</table>
<script>
$("#name").dblclick(function(e) {
if (e.target.parentElement.nodeName != 'form') {
var form = $('<form action="index.php" method="post">');
var parent = $(e.target.parentElement);
parent.children().each(function(i, elem){
form.append(elem);
})
parent.empty();
parent.append(form);
}
})
</script>
It handles double click event and wraps all <td> elements inside <tr> into <form> tag.
I believe this will do what you want:
$("document").ready(function () {
var haveForm = false;
$("td").dblclick(function () {
var thisVal = $(this).html();
if (!haveForm) {
$("td").wrapAll('<form action="index.php" method="post" />');
haveForm = true;
}
$(this).html('<input type="text" value="' + thisVal + '" name="name" />');
});
});
jsFiddle
This makes use of jQuery's wrapAll() and safe guards against multiple form elements being created.
Related
I have this html table and 2 textboxes:
<table id="myTbl">
<thead>
<tr>
<th>A</th>
<th>B</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
<input type="text" name="txt" id="txt" >
<input type="text" name="txt" id="txt2" >
I want when reload the page, the values 1 and 2 must display in each textbox. How can I do it?
I have tried this js code but wrong and I want it auto display, not to click it:
var cells = document.querySelectorAll('#myTbl tbody ');
Array.from(cells).forEach(function (elem) {
elem.addEventListener('click', function () {
document.getElementById('txt').value = this.textContent;
})
})
var tbody = document.getElementsByTagName('tbody')[0]
var input1 = document.getElementById('txt')
var input2 = document.getElementById('txt2')
input1.value = tbody.getElementsByTagName('td')[0].textContent
input2.value = tbody.getElementsByTagName('td')[1].textContent
Why is .append() creating 2 identical rows in this code when I click Add New button? I don't see why 2 appends happen. Am I misunderstanding something? This doesn't happen with vanilla javascript but happens with jquery.
I added the table which includes the tbody tag at the end of the table where I would like to append the template string in function onAddProduct(e).
(Note: I removed html since it was an assignment.)
here is the code snippet
$(function() {
var $formEl = $('form');
var $tbodyEl = $('tbody');
var $tableEl = $('table');
function onAddProduct(e) {
e.preventDefault();
var $pName = $('#pname').val();
var $pCat = $('#pcat').val();
var $pPrice = $('#pprice').val();
$tbodyEl.append(`
<tr>
<td>${$pName}</td>
<td>${$pCat}</td>
<td>${$pPrice}</td>
<td><button class="deleteBtn">Delete</button></td>
</tr>
`);
}
function onDeleteRow(e) {
if (!e.target.classList.contains("deleteBtn")) {
return;
}
const btn = e.target;
btn.closest("tr").remove();
}
//formEl.addEventListener("submit", onAddProduct);
$formEl.on({
submit: onAddProduct
});
//tableEl.addEventListener("click", onDeleteRow);
$tableEl.on({
click: onDeleteRow
});
});
Consider the following.
$(function() {
var $formEl = $('form');
var $tbodyEl = $('tbody');
var $tableEl = $('table');
function onAddProduct(e) {
e.preventDefault();
var row = $("<tr>").appendTo($("tbody", $tableEl));
$("<td>").html($('#pname').val()).appendTo(row);
$("<td>").html($('#pcat').val()).appendTo(row);
$("<td>").html($('#pprice').val()).appendTo(row);
$("<td>").html("<button class='deleteBtn'>Delete</button>").appendTo(row);
return;
}
function onDeleteRow(e) {
if (!e.target.classList.contains("deleteBtn")) {
return;
}
if (confirm("Are you sure you want to delete this Product?")) {
$(e.target).closest("tr").remove();
}
}
$formEl.on({
submit: onAddProduct
});
$tableEl.on({
click: onDeleteRow
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h4>Add Product</h4><br>
<form>
<label for="pname">Product Name:</label>
<input type="text" id="pname" name="pname">
<label for="pcat">Product Category:</label>
<input type="text" id="pcat" name="pcat">
<label for="pprice">Product price:</label>
<input type="text" id="pprice" name="pprice">
<button type="submit" class="addBtn">Add New</button>
</form>
<table>
<thead>
<tr>
<th>Product Name</th>
<th>Product Category</th>
<th>Product Price</th>
<td> </td>
</tr>
</thead>
<tbody>
</tbody>
</table>
I am not able to replicate the issue with this code. Only 1 Row is added.
Your table is missing the <tbody> around the rows you have added, so the browser is adding it in to create a valid table. This results in 2 <tbody> elements, and is why rows are being added twice:
It can be prevented by putting the header and body rows inside the <thead> and <tbody> elements that the browser wants, seen below in the snippet -
$(function() {
var $formEl = $('form');
var $tbodyEl = $('tbody');
function onAddProduct(e) {
e.preventDefault();
var $pName = $('#pname').val();
var $pCat = $('#pcat').val();
var $pPrice = $('#pprice').val();
$tbodyEl.append(`
<tr>
<td>${$pName}</td>
<td>${$pCat}</td>
<td>${$pPrice}</td>
</tr>
`);
}
$formEl.on({
submit: onAddProduct
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="productTable" border="1">
<thead>
<tr>
<th>Product Name</th>
<th>Product Category</th>
<th>Product Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>M&M</td>
<td>Snacks</td>
<td>$1.99</td>
</tr>
<tr>
<td>Table</td>
<td>Furniture</td>
<td>$1.99</td>
</tr>
<tr>
<td>Kale</td>
<td>Vegetables</td>
<td>$2.49</td>
</tr>
</tbody>
</table>
<h4>Add Product</h4><br>
<form>
<label for="pname">Product Name:</label>
<input type="text" id="pname" name="pname">
<label for="pcat">Product Category:</label>
<input type="text" id="pcat" name="pcat">
<label for="pprice">Product price:</label>
<input type="text" id="pprice" name="pprice">
<button type="submit" class="addBtn">Add New</button>
</form>
table:
<table id=tblList>
<thead>
<th>Firstname</th>
<th>Lastname</th>
<th>Status</th>
<th>Action</th>
</thead>
<tbody>
<tr>
<td>Jane</td>
<td>Doe</td>
<td>Pending</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>Cancelled</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
</tbody>
</table>
and script
var search = 'Cancelled';
$('#tblAppointment tr td').filter(function () {
return $(this).text() == search;
}).parent('tr').css('color', 'red');
with code above, i've managed to changed the color of the row that contains "Cancelled" to red
and with this:
$('#tblAppointment tr td').filter(function () {
return $(this).text() == search;
}).find(".cancelThis").prop("disabled", true);
is not working.
should be: for every row that contains string "Cancelled" cancel button will be disabled. rows that doesn't contain string "Cancelled" will remain unaffected.
TIA.
You can just add the same logic as the one that is working, Add .parent('tr') before .find(".cancelThis").prop("disabled", true);
$('#tblAppointment tr td').filter(function() {
return $(this).text() == search;
}).parent('tr').find(".cancelThis").prop("disabled", true);
You can cut down you code a bit,
var search = 'Cancelled';
var t = $('#tblAppointment tr td').filter(function() {
return $(this).text() == search;
}).parent('tr');
t.css('color', 'red');
t.find(".cancelThis").prop("disabled", true);
Demo
var search = 'Cancelled';
$('#tblAppointment tr td').filter(function() {
return $(this).text() == search;
}).parent('tr').css('color', 'red');
$('#tblAppointment tr td').filter(function() {
return $(this).text() == search;
}).parent('tr').find(".cancelThis").prop("disabled", true);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id=tblAppointment>
<thead>
<th>Firstname</th>
<th>Lastname</th>
<th>Status</th>
<th>Action</th>
</thead>
<tbody>
<tr>
<td>Jane</td>
<td>Doe</td>
<td>Pending</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>Cancelled</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
</tbody>
</table>
Your initial query is getting a list of <td> elements. So when you call find on that, you're only searching inside the <td> (which doesn't have a .cancelThis) element. You'd have to do something like this:
$('#tblAppointment tr td').filter(function () {
return $(this).text() == search;
}).parent('tr').find(".cancelThis").prop("disabled", true);
However, I can think of one issue you might want to resolve. What if First or Last named is "Cancelled"? Your query would match that too. If you add a class to the status <td>, you can search for it specifically:
<table id='tblAppointment'>
<thead>
<th>Firstname</th>
<th>Lastname</th>
<th>Status</th>
<th>Action</th>
</thead>
<tbody>
<tr>
<td>Jane</td>
<td>Doe</td>
<td class='status'>Pending</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td class='status'>Cancelled</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
</tbody>
</table>
$('#tblAppointment tr td.status').filter(function () {
return $(this).text() == search;
}).parent('tr').find(".cancelThis").prop("disabled", true);
This will only look at the text of the td.status elements, and not the other elements (like first and last name).
I have a html table that shows a list of users ID, Name and E-mail. When my user clicks in any row, I get the id number of that row and send to my backend. So, I did this:
//Making the table
var trs = document.getElementsByTagName('tr');
for (var i = 0; i < trs.length; i++) {
trs[i].onclick = clickHandler;
}
Function that handles the click:
function clickHandler(event) {
var numb = this.innerText.match(/\d/g);
numb = numb.join("");
window.location.replace("chooseParticipant.php?id="+numb);
}
Table Example:
<div id="table">
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
<td>7</td>
<td>Test User</td>
<td>testuser123#example.com</td>
</tbody>
</table>
</div>
What happens then? If an user have numbers in their e-mail, the "numb" variable gets these numbers too. I don't know how to filter only the id number. Did someone have any ideas?
You could assign a class to you tag.
Something like below:-
<td class="id">7</td>
And in the javascript code you could fetch all the elements with class "id".
And then perform your click handler on each one.
var trs = document.getElementsByClassName('id');
I hope this helps.
Try this code snippet which use data-* attribute
document.addEventListener('DOMContentLoaded', function(e) {
var trs = document.querySelectorAll('#table tbody tr');
var repeater = Array.prototype.slice;
repeater.call(trs).forEach(function(tr) {
tr.addEventListener('click', function(e) {
var data = tr.querySelector('td[data-id]').dataset;
console.log('id=', data.id);
});
});
});
tbody {
cursor: pointer;
}
<div id="table">
<table border="1" cellspacing="0" cellpadding="3">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
<tr>
<td data-id="7">7</td>
<td>Test User 1</td>
<td>testuser1231#gmail.com</td>
</tr>
<tr>
<td data-id="8">8</td>
<td>Test User 2</td>
<td>testuser1232#gmail.com</td>
</tr>
<tr>
<td data-id="9">9</td>
<td>Test User 3</td>
<td>testuser1233#gmail.com</td>
</tr>
</tbody>
</table>
</div>
I am having a few issues with something. I have the following two tables
<table id="customFields1" class="table table-bordered table-hover additionalMargin alignment">
<thead>
<tr>
<th colspan="2"></th>
<th>Some Title</th>
</tr>
</thead>
<tbody>
<tr>
<td><label class="subjectline" for="User1">User NOC M1</label></td>
<td id="slLabel">SL_A</td>
<td id="slInput"><input type="text" name="slOptions[User][NOC M1]" class="form-control" id="User1"></td>
<td><a class="addCF" href="javascript:void(0);">+ additional user</a></td>
</tr>
</tbody>
</table>
<table id="customFields2" class="table table-bordered table-hover additionalMargin alignment">
<thead>
<tr>
<th colspan="2"></th>
<th>Some Title</th>
</tr>
</thead>
<tbody>
<tr>
<td><label class="subjectline" for="User1">User NOC M1</label></td>
<td id="slLabel">SL_A</td>
<td id="slInput"><input type="text" name="slOptions[User][NOC M1]" class="form-control" id="User1"></td>
<td><a class="addCF" href="javascript:void(0);">+ additional user</a></td>
</tr>
</tbody>
</table>
Both of the have an addCF button. This is used to add a new row to the table. This is achieved through this
$(function() {
alp = "A";
regexp = /[_A]+$/;
$(".addCF").click(function(){
alp = (alp.substring(0,alp.length-1)+String.fromCharCode(alp.charCodeAt(alp.length-1)+1));
var clone = $(this).closest('tr').clone(true);
var inputOrgLabel = $("td:nth-child(2)", clone).html();
inputOrgLabel = inputOrgLabel.replace(regexp,'');
$("td:nth-child(2)", clone).html(inputOrgLabel+'_'+alp);
$("td:first-child", clone).empty();
$("td:last-child", clone).html('Remove');
clone.insertAfter($(this).closest('table').find('tr:last'));
});
$("table.table").on('click','.remCF',function(){
$(this).parent().parent().remove();
});
});
Everything appears to work besides one thing. If I add a new row, I change the label SL_A to SL_B. Every row added has the next letter of the alphabet added to the end of it. This is working, but if I add a row in table 1, making it SL_B, and then add a row in table 2, the row in table 2 has SL_C. Each of the incrementations of letters should be independent, so the second row in table two should also have SL_B.
Is this possible? I have set up a JSFiddle to demonstrate
Thanks
I have made an array for holding your data in alp and changed accordingly. Here i ma getting the index of the clicked button to use that index as the index of the apl array.
$(function() {
alp = [];
$.each($('.addCF'), function(i,v) {
alp[i] = "A";
})
regexp = /[_A]+$/;
$(".addCF").click(function(e){
index = $('.addCF').index($(this));
alp[index] = (alp[index].substring(0,alp[index].length-1)+String.fromCharCode(alp[index].charCodeAt(alp[index].length-1)+1));
var clone = $(this).closest('tr').clone(true);
var inputOrgLabel = $("td:nth-child(2)", clone).html();
inputOrgLabel = inputOrgLabel.replace(regexp,'');
$("td:nth-child(2)", clone).html(inputOrgLabel+'_'+alp[index]);
$("td:first-child", clone).empty();
$("td:last-child", clone).html('Remove');
clone.insertAfter($(this).closest('table').find('tr:last'));
});
$("table.table").on('click','.remCF',function(){
$(this).parent().parent().remove();
});
});
Note: You have to manage code for remove, as it is not resetting the value.