<style>
td[contenteditable=true] {
background: aqua;
}
</style>
<table border="1" align="center" cellpadding="4" cellspacing="0">
<tr>
<th>#</th>
<th>Имя</th>
<th>Фамилия</th>
<th>Опции</th>
</tr>
<tbody>
<tr>
<td data-field="id">1</td>
<td class="data" data-field="name">Иван</td>
<td class="data" data-field="family">Петров</td>
<td class="options">
<a class="edit" href="#">Edit</a>
<a class="save" href="#" style="display: none">Save</a>
<a class="cancel" href="#" style="display: none">Cancel</a>
</td>
</tr>
<tr>
<td data-field="id">2</td>
<td class="data" data-field="name">Александр</td>
<td class="data" data-field="family">Сидоров</td>
<td class="options">
<a class="edit" href="#">Edit</a>
<a class="save" href="#" style="display: none">Save</a>
<a class="cancel" href="#" style="display: none">Cancel</a>
</td>
</tr>
</tbody>
</table>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script>
jQuery(document).ready(function ($) {
$('.options').on('click', 'a', function (e) {
e.preventDefault();
var $tr = $(this).parents('tr');
var $edit = $tr.find('.data');
function showEdit() {
$tr.find('a').hide();
$tr.find('a.edit').show();
$edit.attr('contenteditable', 'false');
}
switch (e.target.className) {
case 'edit':
$edit.attr('contenteditable', 'true');
$(this).hide().siblings().show();
break;
case 'save':
var data = {};
$tr.find('[data-field]').each(function (_, v) {
data[$(v).data('field')] = $(v).text();
});
console.log(data);
/*$.post('index.php', data, function (res) {
if (res) {
$edit.attr('contenteditable', 'false');
}
}, 'json').fail(function (error) {
alert(error.statusText)
});*/
showEdit();;
break;
case 'cancel':
showEdit();
break;
}
});
});
</script>
Вариант с contenteditable