Я создал таблицу HTML, в которой каждая строка извлекает данные из таблицы базы данных sql.
?>
<div class = "container">
<h2>Activities</h2>
<table class = "table table-striped">
<thead>
<tr>
<th scope = "col">#</th>
<th scope = "col">Date</th>
<th scope = "col">Position</th>
<th scope = "col">Activity Type</th>
<th scope = "col">Edit</th>
</tr>
</thead>
<tbody>
<?php
$incremental=0;
while($selRow=$res_selPostData->fetch_assoc()) {
$incremental +=1;
$filepath='.\outputs\\' . 'verbale' . $selRow['IDIntervento'] . '.pdf';
?>
<tr>
<td><?php echo $selRow['IDActivity']; ?></td>
<td><?php echo $selRow['DateActivity']; ?></td>
<td><?php echo $selRow['Position']; ?></td>
<td><div id=<?php echo "TypeAct" . $incremental; ?>><?php echo $selRow['Activity_type']; ?></div></td>
<td><div id=<?php echo "button" . $incremental; ?>><span id='edit'>EDIT</span></div></td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
Последний столбец таблицы HTML содержит для каждой строки «кнопку», которая связана со следующей функцией javascript.
<script>
window.onload = function() {
var maximum=parseInt(<?php echo $incremental; ?>);
for (let i = 1; i<maximum; i++) {
var makeMod = document.getElementById('TypeAct' + 'i');
var div = document.getElementById('button' + 'i');
div.onclick = function(e) {
makeMod.contentEditable = true;
makeMod.focus();
makeMod.style.backgroundColor = '#E0E0E0';
makeMod.style.border = '1px dotted black';
}
}
}
</script>
Я пытался использовать скрипт без цикла for с
<td><div id=<?php echo "button"; ?>><span id='edit'>EDIT</span></div></td>
и
var makeMod = document.getElementById('TypeAct')` and `var div = document.getElementById('button')
но в этом случае функция работает только для одной строки.
Изменение «i» на «i» решило проблему с «кнопкой», но когда я нажимаю кнопку в разных строках, редактируемым становится только тип активности в последней строке, а не тот, который находится в той же строке, что и кнопка; как если бы функция воздействовала только на последнюю сгенерированную строку в цикле while таблицы. Можете ли вы догадаться, почему?
Это решило проблему с «кнопкой», но когда я нажимаю кнопку в разных строках, редактируемым становится только тип активности в последней строке, а не тот, который находится в той же строке, что и кнопка; как если бы функция воздействовала только на последнюю сгенерированную строку в цикле while таблицы. Можете ли вы догадаться, почему?
еще одна проблема: идентификаторы уникальны, и эта часть вашего кода находится внутри цикла, у вас не может быть нескольких элементов с одним и тем же идентификатором, поэтому измените его, как вы сделали с другими идентификаторами <span id='edit'>EDIT</span>
Это действительно проблема PHP? Почему бы сначала не сгенерировать статическую разметку, запустить ее со всей этой логикой JS, а затем динамически построить разметку?
В этой строке:
var div = document.getElementById('button' + 'i');
«i» находится в кавычках, таким образом, получается не расчетное значение, а буквально буква «i». Вместо этого попробуйте:
var div = document.getElementById('button' + i);
и в идеале используйте дефис между кнопкой слова и переменной приращения, например:
id = "button-1" id = "button-2" etc.
Я использую образец HTML с образцами данных, которые я сделал только для проверки кода, так как здесь нельзя воспроизвести PHP.
Первым делом замените строку i
на переменную (что вы уже сделали)
makeMod = document.getElementById('TypeAct-' + i);
Эта строка кода находится внутри цикла. <span id='edit'>EDIT</span>
, что означает, что у вас будет несколько элементов с идентификатором edit
. Этого не может быть, поэтому измените его, как вы сделали с другими идентификаторами. Вы можете объединить свою переменную php $incremental
, как и с другими.
Измените свой цикл на этот for (let i = 1; i <= maximum; i++) {
, если вы оставите его на i < maximum
, тогда он не добавит событие к вашей последней кнопке.
Теперь гораздо лучше использовать let
и const
вместо var
. Подробнее здесь
Используйте addEventListener
вместо onclick
. Почему? подробнее об этом читайте здесь addEventListener-vs-onclick
window.onload = function() {
let maximum = 3;//sample value, leave this line like in your original code
let makeMod;
for (let i = 1; i <= maximum; i++) {
document.getElementById('button-' + i).addEventListener("click", function(e) {
makeMod = document.getElementById('TypeAct-' + i);
makeMod.contentEditable = true;
makeMod.focus();
makeMod.style.backgroundColor = '#E0E0E0';
makeMod.style.border = '1px dotted black';
});
}
}
<div class = "container">
<h2>Activities</h2>
<table class = "table table-striped">
<thead>
<tr>
<th scope = "col">#</th>
<th scope = "col">Date</th>
<th scope = "col">Position</th>
<th scope = "col">Activity Type</th>
<th scope = "col">Edit</th>
</tr>
</thead>
<tbody>
<tr>
<td>some data</td>
<td>some data</td>
<td>some data</td>
<td>
<div id = "TypeAct-1">act 1</div>
</td>
<td>
<div id = "button-1"><span id='edit-1'>EDIT</span></div>
</td>
</tr>
<tr>
<td>some data</td>
<td>some data</td>
<td>some data</td>
<td>
<div id = "TypeAct-2">act 2</div>
</td>
<td>
<div id = "button-2"><span id='edit-2'>EDIT</span></div>
</td>
</tr>
<tr>
<td>some data</td>
<td>some data</td>
<td>some data</td>
<td>
<div id = "TypeAct-3">act 3</div>
</td>
<td>
<div id = "button-3"><span id='edit-3'>EDIT</span></div>
</td>
</tr>
</tbody>
</table>
</div>
Это решило проблему полностью! Большое спасибо
рад, что это помогло, пожалуйста, примите ответ и проголосуйте за него, это также приветствуется :)
Было бы лучше, IMO, полностью удалить атрибуты ID, если вам нужно использовать числовой суффикс, чтобы помочь идентифицировать элементы, и полагаться на другие, более гибкие средства идентификации элементов DOM, такие как querySelector
, querySelectorAll
и другие родитель/потомок/брат. введите свойства и методы. В приведенном выше примере единственное использование, которое имеет переменная PHP $incremental
, — это числовой суффикс — он не будет играть никакой роли в какой-либо фактической операции edit
(отправка формы / ajax и т. д.), когда запись должна быть отредактирована, поэтому ее можно удалить. Таблица создается с содержимым из базы данных, поэтому у вас есть IDActivity
, который будет полезен в операции редактирования, поэтому назначьте его как значение идентификатора данных!
Идентификация событий click
может быть выполнена с помощью delegated event listener
вместо того, чтобы назначать прослушиватель событий каждому button
.
Я также добавил обработчик событий blur
к элементам DIV contentEditable, который возвращает их в нормальное состояние, когда они больше не используются. Этот обработчик blur
можно использовать для отправки ajax-запроса на редактирование записи в БД.
const d=document;
const CN='editable';
d.querySelector('.container table').addEventListener('click', e=>{
if ( e.target instanceof HTMLSpanElement && e.target.dataset.type == 'edit' ) {
let id=e.target.parentNode.dataset.id;
let content = e.target.parentNode.closest('tr').querySelector('div[data-type = "content"]');
content.contentEditable=true;
content.focus();
content.classList.add( CN );
console.info( ' -> Id=%s',id )
}
});
d.querySelectorAll('[data-type = "content"]').forEach(n=>n.addEventListener('blur',e=>{
if ( e.target.classList.contains( CN ) ){
e.target.classList.remove( CN );
e.target.contentEditable=false;
// update using ajax?
console.info(e.target.dataset.id,e.target.textContent);
}
}));
.editable{
background:#E0E0E0;
border:1px dotted black
}
<div class = "container">
<h2>Activities</h2>
<table class = "table table-striped">
<thead>
<tr>
<th scope = "col">#</th>
<th scope = "col">Date</th>
<th scope = "col">Position</th>
<th scope = "col">Activity Type</th>
<th scope = "col">Edit</th>
</tr>
</thead>
<tbody>
<!-- emulated content -->
<!--
The `IDActivity` value is what would be assigned
to the `data-id` attribute below. That `data-id`
is easily accessible in Javascript and can be used
for whatever EDIT operation you wish.
ie:
<td>
<div data-id = "<?=$selRow['IDActivity'];?>">
<?=$selRow['Activity_type'];?>
</div>
</td>
-->
<tr>
<td>1</td>
<td>2023/04/15</td>
<td>Midfield</td>
<td><div data-id=1 data-type='content'>Banana Bouncing</div></td>
<td><div data-id=1><span data-type='edit'>EDIT</span></div></td>
</tr>
<tr>
<td>2</td>
<td>2023/04/17</td>
<td>Ground-Level</td>
<td><div data-id=2 data-type='content'>Hedgehog Juggling</div></td>
<td><div data-id=2><span data-type='edit'>EDIT</span></div></td>
</tr>
<tr>
<td>3</td>
<td>2023/04/18</td>
<td>Upstairs</td>
<td><div data-id=3 data-type='content'>Dwarf Tossing</div></td>
<td><div data-id=3><span data-type='edit'>EDIT</span></div></td>
</tr>
<!-- end emulated content -->
</tbody>
</table>
</div>
как должно работать, когда вы получаете элемент и объединяете строку «i», а не значение вашей переменной
i
var makeMod = document.getElementById('TypeAct' + 'i');
, вы должны изменить ее на этоvar makeMod = document.getElementById('TypeAct' + i);