/* ... */
свои варианты не проверял - тестировать это мне не на чем. и самое главное, перечислены изменения в плане реализации, а не в плане подхода - кроме всего этого, вам надо менять подход и модель данных выделять./* эти три let вполне могут быть const */
let resa = document.querySelector('.todo_ul');
let addLi = document.querySelector('.todo_add');
let inputLi = document.querySelector('.todo_input');
// Событие на кнопку "Добавить"
addLi.addEventListener('click',function(e){
//Отключает перезагрузку страниц
e.preventDefault(); /* перезагрузки изначально не должно быть, вы наверное неподходящий тип кнопки выбрали? */
let ul = document.querySelector('.todo_ul'); /* ссылка на этот элемент уже получена выше под именем resa */
//В список при нажатии на кнопку "Добавить" добавляется новый элемент списка со значением из инпута
ul.appendChild(addNewLi(inputLi.value)) /* разумнее само заталкивание иметь внутри соответствующего метода, а не тут */
//Очищаем инпут
inputLi.value = '';
});
/*
в результате, ваш обработчик может выглядеть так:
addLi.addEventListener('click',function(e){
addNewLi(inputLi.value));
inputLi.value = '';
});
*/
//Функция для создания элемента списка
/* это всё я уже советовал заменить на шаблон с кусочком html */
function addNewLi(value){
if(value === ''){
return false
}; /* в таких местах точка с запятой не нужна */
let li = createElem('li',{class:'todo_li'}) /* а в таких наоборот нужна. много мест. все помечать не буду */
let divInLi = createElem('div',{class:'todo_check'})
let changeButton = createElem('input',{type:'button',value:'Изменить',class:'todo_li_change li_button'});
let deleteButton = createElem('input',{type:'button',value:'Удалить',class:'todo_li_delete li_button'});
let saveButton = createElem('input',{type:'button',value:'Сохранить',class:'save_change_item li_button'});
/* класс li_button почти наверняка лишний, вы спокойно можете в css привязаться к родительскому классу, особенно если тэг на button поменяете */
let saveInput = createElem('input',{type:'text',class:'change_item'});
let p = createElem('p',{class:'li_text'});
p.innerHTML = value; /* это у вас натуральная XSS уязвимость. что будет если пользователь введёт <script>вредоносный код</script> ?*/
li = appendChilds(li,p,divInLi,changeButton,deleteButton,saveButton,saveInput)
//Выполняить функцию, а качестве аргумента - нвоый созданый элемент списка
//doEvent(li);
return li
};
function createElem(tag,props){
let div = document.createElement(tag);
for( let key in props){
/* в таких местах должна быть проверка if(props.hasOwnProperty(key)), а то могут непонятно от кого унаследованные поля вылезти */
/* или for(const key of Object.keys(props)) */
div.setAttribute(key, props[key])
}
return div
};
function appendChilds(obj,...arg){ /* правильно children */
for(let i = 0; i < arg.length; i++){ /* тут был бы уместен какой-нить arg.forEach(x => obj.appendChild(x)) */
obj.appendChild(arg[i]);
}
return obj
};
/*
всё добавление тудушки может выглядеть так:
function addNewLi(value){
if(!value) return;
const li = document.createElement('li');
li.outerText = `
<li class="todo_li">
<p class="li_text"></p>
<div class="todo_check"></div>
<button class="todo_li_change">Изменить</button>
<button class="todo_li_delete">Удалить</button>
<button class="save_change_item">Сохранить</button>
<input type="text" class="change_item">
</li>`;
li.querySelector('.li_text').textContent = value;
resa.appendChild(li);
}
*/
resa.addEventListener('click', function(e){ /* когда кода много, обработчики надо разобрать на отдельные именованные по смыслу методы. но этот код почти весь лишний */
console.log(e.target.className)
if(e.target.tagName === 'P'){
let check = e.target.parentNode.querySelector('.todo_check');
check.classList.toggle('check'); /* дублирующиеся по смыслу классы у чекбокса и родителя, достаточно родительского, а в цсс использовать селектор .todo_li.checked .todo_check */
e.target.parentNode.classList.toggle('checked');
}else if(e.target.tagName === 'LI'){ /* простановка галки повторяется аж три раза, явно зря */
let check = e.target.querySelector('.todo_check');
check.classList.toggle('check');
e.target.classList.toggle('checked');
}else if(e.target.classList.contains("todo_li_change")){
let qSelector = e.target.parentNode;
let save = qSelector.querySelector('.save_change_item');
let saveInput = qSelector.querySelector('.change_item');
let deleteButton = qSelector.querySelector('.todo_li_delete');
let litext = qSelector.querySelector('.li_text');
saveInput.value = litext.innerHTML;
save.style.visibility = 'visible'; /* все переключения видимости должны быть сделаны в css. тут надо только добавлять и снимать тудушке класс .edited, а в цсс при наличии класса показываются инпут и кнопка сохранить, а при отсутсвии - кнопки редкатирования/удаления и параграф с текстом тудушки */
saveInput.style.visibility = 'visible';
e.target.className += ' disp_none';
deleteButton.className += ' disp_none';
}else if(e.target.classList.contains('save_change_item')){
let saveInput = e.target.parentNode.querySelector('.change_item');
let litext = e.target.parentNode.querySelector('.li_text');
let save = e.target.parentNode.querySelector('.save_change_item');
let deleteButton = e.target.parentNode.querySelector('.todo_li_delete');
let chandeButton = e.target.parentNode.querySelector('.todo_li_change');
litext.innerText = saveInput.value;
save.style.visibility = 'hidden';
saveInput.style.visibility = 'hidden';
deleteButton.classList.remove('disp_none')
chandeButton.classList.remove('disp_none')
}else if(e.target.classList.contains('todo_li_delete')){
e.target.parentNode.remove()
}else if(e.target.classList.contains('todo_check')){
e.target.classList.toggle('check');
e.target.parentNode.classList.toggle('checked')
}
})
/*
итого, делегированная обработка событий получается примерно такая:
resa.addEventListener('click', function(e){
const el = e.target;
const li = el.closest(".todo_li");
if(!li) return;
if(el.matches(".todo_li_change")) {
li.querySelector('.change_item').value = li.querySelector('.li_text').textContent;
li.classList.add('edited');
}
else if(el.matches(".save_change_item")) {
li.querySelector('.li_text').textContent = li.querySelector('.change_item').value;
li.classList.remove('edited');
}
else if(el.matches(".todo_li_delete")) {
li.remove();
}
else {
li.classList.toggle('checked');
}
});
*/
про ошибки в проектировании даже не упоминаю (это всё надо делать совсем по-другому), но чтобы от этого упражнения была какая-то польза, хотя бы добейтесь чтобы оно как есть заработало.