I'm creating something like GMAIL functionality with JavaScript ES5 ( I use only const and let, that's it, rest ES5).
So I manage to create the list functionality, all works except that when I select the items and move them to a different list, they lose any functionality, and I can't do anything with them.
I believe I need to use querySelectorAll to get all the lists, but that doesn't work. Not sure what should I do here.
I think I need to select all the lists, and then loop them to add interactivity.
CodePen: https://codepen.io/Aurelian/pen/dJryrX?editors=1010
JS:
window.onload = function() {
//////////////////////////////////
// VARIABLES
//////////////////////////////////
// Form
const form = document.querySelector('#registrar');
const input = form.querySelector('input');
// Lists
const partyList = document.querySelector('.party-lists');
const partyInvitedList = document.querySelector('#list-invited')
const partyGoingList = document.querySelector('#list-going');
const partyNotSure = document.querySelector('#list-not-sure');
const partyNotGoing = document.querySelector('#list-not-going');
// List Options
const listOptions = document.querySelector('.list-options');
const btnMoveToGoing = document.querySelector('.btnMoveGoing');
const btnMoveToNotSure = document.querySelector('.btnMoveNotSure');
const btnMoveToNotGoing = document.querySelector('.btnMoveNotGoing');
const btnDeleteSelected = document.querySelector('.btnDeleteSelected');
//////////////////////////////////
// FUNCTIONS
//////////////////////////////////
function createLI(text) {
const li = document.createElement('li');
const span = document.createElement('span');
span.textContent = text;
li.appendChild(span);
const label = document.createElement('label');
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
label.appendChild(checkbox);
li.appendChild(label);
const editButton = document.createElement('button');
editButton.textContent = 'edit';
li.appendChild(editButton);
const removeButton = document.createElement('button');
removeButton.textContent = 'remove';
li.appendChild(removeButton);
return li;
}
//////////////////////////////////
// EVENT HANDLERS
//////////////////////////////////
form.addEventListener('submit', function(e) {
e.preventDefault();
const text = input.value;
input.value = '';
const li = createLI(text);
partyInvitedList.appendChild(li);
});
partyList.addEventListener('click', function(e) {
if (e.target.tagName === 'BUTTON') {
const button = e.target;
const li = button.parentNode;
const ul = li.parentNode;
if (button.textContent === 'remove') {
ul.removeChild(li);
} else if (button.textContent === 'edit') {
const span = li.firstElementChild;
const input = document.createElement('input');
input.type = 'text';
input.value = span.textContent;
li.insertBefore(input, span);
li.removeChild(span);
button.textContent = 'save';
} else if (button.textContent === 'save') {
const input = li.firstElementChild;
const span = document.createElement('span');
span.textContent = input.value;
li.insertBefore(span, input);
li.removeChild(input);
button.textContent = 'edit';
}
}
});
listOptions.addEventListener('click', function(e) {
partyList.querySelectorAll('*:checked').forEach(function (listItems) {
const button = e.target;
var items = listItems.parentNode.parentNode;
if(button.className === 'btnMoveGoing') {
partyGoingList.appendChild(items);
items.checked = false;
var item = listItems;
item.checked = false;
} else if(button.className === 'btnMoveNotSure'){
partyNotSure.appendChild(items);
var item = listItems;
item.checked = false;
} else if(button.className === 'btnMoveNotGoing'){
partyNotGoing.appendChild(items);
var item = listItems;
item.checked = false;
} else if(button.className === 'btnDeleteSelected'){
listItems.parentNode.parentNode.remove();
var item = listItems;
item.checked = false;
}
});
});
}
HTML:
<div class="top">
<form id="registrar">
<input type="text" name="name" placeholder="Invite Someone">
<button type="submit" name="submit" value="submit">Submit</button>
</form>
<div class="list-options">
<button class="btnMoveGoing">Move to Going</button>
<button class="btnMoveNotSure">Move to Not Sure</button>
<button class="btnMoveNotGoing">Move to Not Going</button>
<button class="btnDeleteSelected">Delete Selected</button>
</div>
</div><!-- /top -->
<div class="col">
<h3>Invited</h3>
<ul id="list-invited" class="party-lists">
</ul>
</div>
<div class="col">
<h3>Going</h3>
<ul id="list-going" class="party-lists">
</ul>
</div>
<div class="col">
<h3>Not Sure</h3>
<ul id="list-not-sure" class="party-lists">
</ul>
</div>
<div class="col">
<h3>Not Going</h3>
<ul id="list-not-going" class="party-lists">
</ul>
</div>
Related
I am looking for a way to add text from my span tag into the input value field when you click on a checkbox.
I do not want to use jQuery for this, only JavaScript.
I have done it so it adds the text into the input field but when you actually click on the input it doesn't recognise that my text is there. Does anyone know how I go about this so it recognises I have added text to the input field? Any help would be appreciated.
Code here:
const inputContainer = document.querySelector('.input-container');
const spanText = document.querySelector('.span-t');
const checkbox = document.querySelector('#checkbox');
const check = document.getElementById('check');
const btn = document.querySelector('.btn');
/* Add Input Field */
const applyInput = function(){
const inputDiv = document.createElement("div");
const inputContent = `<div class="input-container">
<div>
<input class="input" type="text" name="input-code" value=""></input>
</div>
<button type="submit" class="btn" disabled="">
<span>Submit</span>
</button>
</div>`;
inputDiv.id = "input-container";
inputDiv.innerHTML = inputContent;
};
applyInput();
/* Add Span Text */
const span = document.createElement('div');
if(document.getElementById('p-text') !== null) document.getElementById('p-text').parentNode.removeChild(document.getElementById('p-text'));
span.id = "p-text";
span.innerHTML += '<p class="p-text">P Text<span class="span-t">Span Text</span></p>';
inputContainer.after(span);
/* Add Checkbox */
const addingCheckbox = () => {
if(document.getElementById('checkbox') !== null) document.getElementById('checkbox').parentNode.removeChild(document.getElementById('checkbox'));
const addCheckboxHtml = document.createElement('div');
addCheckboxHtml.id = 'checkbox';
addCheckboxHtml.className = 'checkboxEl';
addCheckboxHtml.innerHTML = `<label class="checkbox"><input type="checkbox" id="check"><span></span></label>`;
if(document.getElementById('checkbox') === null) {
spanText.after(addCheckboxHtml);
}
};
addingCheckbox();
/* Add if Checked */
checkbox.addEventListener('click', () => {
document.querySelector('.input').value = spanText.innerHTML;
});
check.onchange = function() {
btn.disabled = !this.checked;
};
SIMPLIFIED CHECK
You can see that this behavior is totally possible - the little snippet below shows a simplified case.
const span = document.querySelector("#from")
const input = document.querySelector("#to")
const cb = document.querySelector("#cb")
const btReset = document.querySelector("#reset")
const btLog = document.querySelector("#log")
cb.addEventListener("change", function(e) {
input.value = span.innerHTML
})
btReset.addEventListener("click", function() {
cb.checked = false
input.value = ''
})
btLog.addEventListener("click", function() {
console.log("input value:", input.value)
})
.container {
margin-bottom: 16px;
}
<div class="container">
<span id="from">This is the text.</span>
</div>
<div class="container">
<input type="text" id="to" /><input type="checkbox" id="cb" />
</div>
<div class="container">
<button id="reset">RESET</button><button id="log">LOG INPUT VALUE</button>
</div>
CODE UPDATE
Now the snippet you gave works without an error.
/* Add Input Field */
const applyInput = function() {
const inputDiv = document.createElement("div");
const inputContent = `
<div class="input-container">
<div>
<input class="input" type="text" name="input-code" value="" />
</div>
<button type="submit" class="btn" disabled="">
<span>Submit</span>
</button>
</div>
`;
inputDiv.id = "input-container";
inputDiv.innerHTML = inputContent;
// you need to add the created element to the DOM,
// e.g. append it to the body
document.body.append(inputDiv)
};
applyInput();
// only elements that are created can be queried, so
// these variables must be initialized AFTER the element(s)
// they are supposed to get exist in the document (DOM)
const inputContainer = document.querySelector('.input-container');
const btn = document.querySelector('.btn');
/* Add Span Text */
// the creation of the span has to be also encapsulated in
// a function - this way it's easier to handle
const addingSpan = () => {
const span = document.createElement('div');
if (document.getElementById('p-text') !== null) document.getElementById('p-text').parentNode.removeChild(document.getElementById('p-text'));
span.id = "p-text";
span.innerHTML += '<p class="p-text">P Text<span class="span-t">Span Text</span></p>';
inputContainer.after(span);
}
addingSpan()
// element after it is actually created
const spanText = document.querySelector('.span-t');
/* Add Checkbox */
const addingCheckbox = () => {
if (document.getElementById('checkbox') !== null) document.getElementById('checkbox').parentNode.removeChild(document.getElementById('checkbox'));
const addCheckboxHtml = document.createElement('div');
addCheckboxHtml.id = 'checkbox';
addCheckboxHtml.className = 'checkboxEl';
addCheckboxHtml.innerHTML = `<label class="checkbox"><input type="checkbox" id="check"><span></span></label>`;
if (document.getElementById('checkbox') === null) {
spanText.after(addCheckboxHtml);
}
};
addingCheckbox();
// element after it is actually created
const checkbox = document.querySelector('#checkbox');
const check = document.getElementById('check');
/* Add if Checked */
checkbox.addEventListener('click', () => {
document.querySelector('.input').value = spanText.innerHTML;
});
check.onchange = function() {
btn.disabled = !this.checked;
};
UPGRADED CODE
I think the following snippet does what your original code does, but the structure is cleaner, simpler.
const getInputHtml = () => `
<div class="input-container">
<div>
<input class="input" type="text" name="input-code" value=""></input>
</div>
<button type="submit" class="btn" disabled="">
<span>Submit</span>
</button>
</div>
`;
const getSpanHtml = () => `<p class="p-text">P Text<span class="span-t">Span Text</span></p>`;
const getCheckboxHtml = () => `<label class="checkbox-label"><input class="checkbox" type="checkbox" id="check" /></label>`;
// only execute function, if selector cannot be found in DOM
const ifNotExistsInDomFn = (selector) => (fn) => {
if (!document.querySelector(selector)) {
return fn()
}
}
const appendHtmlStrTo = (el) => (str) => {
el.insertAdjacentHTML('beforeend', str)
};
const appendHtmlStrToBody = appendHtmlStrTo(document.body);
// IIFE: Immediately Invoked Function Expression
(function() {
// creating UI
const inputHtml = getInputHtml()
appendHtmlStrToBody(inputHtml)
const spanHtml = getSpanHtml()
ifNotExistsInDomFn(".p-text")(() => appendHtmlStrToBody(spanHtml))
const checkboxHtml = getCheckboxHtml()
ifNotExistsInDomFn(".checkbox")(() => appendHtmlStrToBody(checkboxHtml))
// setting event handlers
const cb = document.querySelector(".checkbox")
cb.addEventListener("click", function() {
document.querySelector(".input").value = document.querySelector(".span-t").innerHTML
})
cb.addEventListener("change", function() {
document.querySelector(".btn").disabled = !cb.checked
})
})();
I am creting a todo list having a default list and then adding new todos to it. It is possible do drag and drop the elements to rearrenge them. That swapping function works perfectly with the default list but does not work with the new ones added. I am not sure why it is not working as it gets undefined
This is the code:
const draggableElement = document.getElementById('draggable-list');
const TodoList = [
'Complete online Javascript course',
'Jog around the park 3x',
'10 minutes meditation',
'Read for 2hr',
'Pick up the groceries',
'Complete todo list',
];
//store items
const listItems = [];
let dragStartIndex;
createList();
//insert items into dom
function createList() {
[...TodoList] //copies array
.forEach((todo, index) => {
const listItem = document.createElement('li');
// listItem.setAttribute('id','draggable');
listItem.setAttribute('data-index', index + 1);
listItem.setAttribute('className', 'draggable');
listItem.innerHTML = `
<label for="showRatings${index + 1}" class="circle${index + 1} check">
<input type="checkbox" class="checkbox input" name="showRatings${index + 1}" id="showRatings${index + 1}">
</label>
<span class="number">${index + 1+"-"}</span>
<div class="draggable" draggable="true">
<p class="todo-name" >${todo}</p>
</div>`;
listItems.push(listItem);
draggableElement.appendChild(listItem);
});
}
addEventListeners();
function dragStart() {
dragStartIndex = +this.closest('li').getAttribute('data-index');
// console.log('index',dragStartIndex)
}
function dragEnter() {
this.classList.add('over');
}
function dragLeave() {
this.classList.remove('over');
}
function dragOver(e) {
e.preventDefault();
// console.log('over')
}
///////////////////////////////////////////////////////
function dragDrop() {
const dragEndIndex = +this.getAttribute('data-index');
swapItems(dragStartIndex - 1, dragEndIndex - 1);
this.classList.remove('over');
}
function swapItems(fromIndex, toIndex) {
const itemOne = listItems[fromIndex].querySelector('.draggable');
const itemTwo = listItems[toIndex].querySelector('.draggable');
// console.log(itemOne,itemTwo);
// console.log(listItems[fromIndex])
listItems[fromIndex].appendChild(itemTwo);
listItems[toIndex].appendChild(itemOne);
}
function addEventListeners() {
const draggables = document.querySelectorAll('.draggable');
const dragListItems = document.querySelectorAll('.draggable-list li');
draggables.forEach(draggable => {
draggable.addEventListener('dragstart', dragStart);
});
dragListItems.forEach(item => {
item.addEventListener('dragover', dragOver);
item.addEventListener('drop', dragDrop);
item.addEventListener('dragenter', dragEnter);
item.addEventListener('dragleave', dragLeave);
});
}
const todoInput = document.querySelector('#todo-input');
const todos = [];
var index2 = 6;
todoInput.addEventListener('keyup', function(e) {
if (e.key == 'Enter' || e.keyCode == 13) {
// index2++;
// todos.push(e.target.value);
newTodo(e.target.value);
todoInput.value = '';
}
})
function newTodo(value) {
const todo = document.createElement('div');
const todoText = document.createElement('p');
todoText.classList.add('todo-name')
const todoCheckbox = document.createElement('input');
const todoCheckBoxLabel = document.createElement('label');
todo.setAttribute('draggable', true);
todo.classList.add('draggable')
const numberSpan = document.createElement('span');
numberSpan.classList.add('number')
const todoLi = document.createElement('li');
todoLi.setAttribute('className', 'draggable');
todoLi.classList.add('list-item', 'not-crossed')
const toDosContainer = document.querySelector('.draggable-list')
const Container = document.querySelector('.container-todo')
todoCross = document.createElement('span');
todoCross.classList.add('cross')
todoLi.setAttribute('data-index', index2);
// let content =[index2+ "-" + ' ' + value ];
// var arrayValue = content.toString().replace(/,/g, "")
numberSpan.textContent = "-";
todoText.textContent = value;
todoCheckbox.type = "checkbox";
todoCheckbox.name = "checkbox";
todoCheckBoxLabel.htmlFor = "checkbox";
todoCheckBoxLabel.addEventListener('click', function(e) {
if (todoCheckbox.checked) {
todoCheckbox.checked = false;
todoText.style.textDecoration = 'none';
todoCheckBoxLabel.classList.remove('active');
todoLi.classList.add('not-crossed')
todoLi.classList.remove('thick-crossed')
} else {
todoCheckbox.checked = true;
todoText.style.textDecoration = "line-through";
todoCheckBoxLabel.classList.add('active');
todoLi.classList.remove('not-crossed')
todoLi.classList.add('thick-crossed')
}
});
TodoList.push(todoText.textContent);
listItems.push(todoText.textContent);
console.log('lista', listItems);
todoCross.textContent = 'X';
todoCross.addEventListener('click', function(e) {
e.target.parentElement.remove();
});
Container.classList.add('todos-container');
todo.classList.add('todo');
todoCheckbox.classList.add('checkbox')
todoCheckBoxLabel.classList.add('circle', 'chk');
// todoCross.classList.add('cross');
todo.appendChild(todoCheckbox);
todo.appendChild(todoCheckBoxLabel);
todo.appendChild(numberSpan)
todo.appendChild(todoText);
todo.appendChild(todoCross);
todoLi.appendChild(todo);
toDosContainer.appendChild(todoLi)
}
<body>
<main>
<div class="header">
<h1 class="title">TODO</h1>
<div onclick="changeTheme()" class="tgl-btn"></div>
</div>
<div class="type-todo">
<div class="circle"></div>
<input type="text" value="" id="todo-input">
</div>
<div class="container-todo">
<ul class="draggable-list" id="draggable-list">
</ul>
<div class="footer-div" id="footer-div"></div>
</div>
<p class="note">Drag and drop to reorder list</p>
</main>
<script src="./index.js"></script>
</body>
Thank you in advance and I hope you can help me
I'm working on a to-do list project and stuck at this part where when a trash button is clicked all the list items will be deleted and it won't add any new to-do items.
I've checked other posts but couldn't really find the answer for my project, please help!
let input = document.querySelector('#todo')
let btn = document.querySelector('#btn');
let list = document.querySelector('#list');
btn.addEventListener('click', () => {
let txt = input.value;
if (txt === "") {
alert('Please write something to do!');
} else {
let li = document.createElement('li');
li.innerHTML = txt;
list.insertBefore(li, list.childNodes[0]);
input.value = '';
const delBtn = document.createElement("i");
delBtn.classList.add("fas", "fa-trash-alt");
li.appendChild(delBtn);
delBtn.addEventListener('click', e => {
list.parentNode.removeChild(list);
})
}
})
list.addEventListener('click', e => {
if(e.target.tagName == 'LI') {
e.target.classList.toggle('checked');
}
})
<div class="todoList">
<h1>To-do List</h1>
<div class="add-element">
<input type="text" id="todo" placeholder="Add new to-do">
<button id="btn">Add</button>
</div>
<div class="element-list">
<ul id="list"></ul>
</div>
</div>
list.parentNode.removeChild(list); deletes all the list, if you want to delete only one element from the list, add a button to every li and change this line to li.parentNode.removeChild(li); like this:
let input = document.querySelector('#todo')
let btn = document.querySelector('#btn');
let list = document.querySelector('#list');
btn.addEventListener('click', () => {
let txt = input.value;
if (txt === "") {
alert('Please write something to do!');
} else {
let li = document.createElement('li');
li.innerHTML = txt;
list.insertBefore(li, list.childNodes[0]);
input.value = '';
const delBtn = document.createElement("i");
li.appendChild(delBtn);
delBtn.addEventListener('click', e => {
li.parentNode.removeChild(li);
})
}
})
list.addEventListener('click', e => {
if(e.target.tagName == 'LI') {
e.target.classList.toggle('checked');
}
})
<div class="todoList">
<h1>To-do List</h1>
<div class="add-element">
<input type="text" id="todo" placeholder="Add new to-do">
<button id="btn">Add</button>
</div>
<div class="element-list">
<ul id="list"></ul>
</div>
</div>
I cannot add new Note after editing. How can I exit from the cycle?
This is a part where I create a new note
const createNote = () => {
if (button.className === "button") {
const div = document.createElement("div");
div.setAttribute("class", "note");
div.textContent = input.value;
field.appendChild(div);
const btn = document.createElement("button");
btn.setAttribute("class", "edit");
btn.textContent = "Edit";
div.appendChild(btn);
const del = document.createElement("button");
del.setAttribute("class", "del");
del.textContent = "Delete";
div.appendChild(del);
console.log("Note has been created");
input.value = "";
}
Here is a part where I want to edit created Note but also I want to create a new one (this part is inside function createNote)
const edit = document.querySelectorAll(".edit");
for (let i of edit) {
i.onclick = () => {
input.value = i.previousSibling.nodeValue;
button.innerText = "Edit";
button.classList.add("editable");
/*button.classList.remove("button");*/
if (button.className === "button editable") {
button.onclick = () => {
i.previousSibling.nodeValue = input.value;
input.value = "";
button.classList.remove("editable");
button.classList.add("button");
button.innerText = "Add";
};
}
};
}
};
button.onclick = createNote;
Here is HTML that I am using
<body>
<div class="container">
<div class="insert">
<input type="text" name="Note" id="noteId" placeholder="add note">
<button class="button">Add</button>
</div>
<div class="field">
<div class="note">Test note
<button class="edit">Edit</button>
<button class="del">Delete</button>
</div>
</div>
</div>
<script src="js/index.js"></script>
</body>
I'm trying to add some validation on something I'm working on. Basically if no input is processed, it would return a red paragraph telling you to enter something and return false. The problem I'm having is how to remove it when a valid value is processed.
var input = document.getElementById('input'),
button = document.getElementById('add')
function removeItem() {
var item = this.parentNode
var parent = item.parentNode
parent.removeChild(item)
}
button.addEventListener('click', function (e) {
if (input.value === '') {
var p = document.querySelector('p')
p.style.display = 'block'
return false
} else if (!input.value === '') {
p.style.display = ''
return true
}
var userInput = document.createTextNode(input.value)
var li = document.createElement('li')
var ul = document.getElementById('todo')
var remove = document.createElement('button')
remove.innerHTML = 'Remove'
remove.addEventListener('click', removeItem);
ul.insertBefore(li, ul.childNodes[0])
li.appendChild(userInput)
li.appendChild(remove)
})
<input type="text" id="input"/>
<button id="add">Add</button>
<p>plz add</p>
<div class="container">
<ul id="todo"></ul>
</div>
p {
display: none;
color: #f00;
}
Some issues:
You return in both if ... else cases, which (if it would work) makes the rest of the code unreachable.
The else if condition is unnecessary (since the if condition was already false), but is also wrong: ! has precedence over ===, so better use !==. Anyway, it is not needed at all.
Here is the corrected code:
var input = document.getElementById('input'),
button = document.getElementById('add');
function removeItem() {
var item = this.parentNode;
var parent = item.parentNode;
parent.removeChild(item);
}
button.addEventListener('click', function(e) {
var p = document.querySelector('p');
if (input.value.trim() === '') {
p.style.display = 'block';
return false;
}
p.style.display = '';
var remove = document.createElement('button');
remove.textContent = 'Remove';
remove.addEventListener('click', removeItem);
var li = document.createElement('li');
li.appendChild(document.createTextNode(input.value));
li.appendChild(remove);
todo.insertBefore(li, todo.childNodes[0]);
});
p {
display: none;
color: #f00;
}
<input type="text" id="input"/>
<button id="add">Add</button>
<p>plz add</p>
<div class="container">
<ul id="todo"></ul>
</div>
add an id to the error element. Then :
var el = document.getElementById('theidyouset')
el.parentNode.removeChild( el );
or you could hide it
el.className += " classhiddenwithcss";
Use CSS classes and simply add or remove the class from the class list as needed.
Also, because you are using return in both of your if/else cases, the code will stop processing and not continue on to do the rest of the work. Move the if/else to the end of the code so that return is the last thing you do.
And, use semi-colons at the end of your statements.
var input = document.getElementById('input'),
button = document.getElementById('add')
function removeItem() {
var item = this.parentNode;
var parent = item.parentNode;
parent.removeChild(item);
}
button.addEventListener('click', function(e) {
var p = document.querySelector('p')
var userInput = document.createTextNode(input.value)
var li = document.createElement('li')
var ul = document.getElementById('todo')
var remove = document.createElement('button')
remove.innerHTML = 'Remove'
remove.addEventListener('click', removeItem);
ul.insertBefore(li, ul.childNodes[0])
li.appendChild(userInput)
li.appendChild(remove)
if (input.value === '') {
p.classList.remove("hidden");
return false;
} else {
p.classList.add("hidden");
return true;
}
})
p {
color: #f00;
}
.hidden {
display:none;
}
<input type="text" id="input"/>
<button id="add">Add</button>
<p class="hidden">plz add</p>
<div class="container">
<ul id="todo"></ul>
</div>