cancel btn for a contenteditable html option - javascript

I'm really new to the contenteditable variable for html and so I want to dig your brains a bit :).
I want to allow users to edit content if they wish to but I'm stuck in the cancel btn option.
How can I retain the previous content if a user clicks the cancel btn? I've been looking at the documentation but struggle to find something. Please see the code below:
const cancelBtn = document.getElementById('cancel-btn');
console.log(editBtn);
function editable() {
const h3 = document.querySelector('h3');
const h4 = document.querySelector('h4');
const p = document.querySelector('p');
h3.className = 'edit';
h4.className = 'edit';
p.className = 'edit';
h3.contentEditable = true;
h4.contentEditable = true;
p.contentEditable = true;
addSaveBtn();
}
function cancelEdit() {
const h3 = document.querySelector('h3');
const h4 = document.querySelector('h4');
const p = document.querySelector('p');
h3.classList.remove('edit');
h4.classList.remove('edit');
p.classList.remove('edit');
h3.contentEditable = false;
h4.contentEditable = false;
p.contentEditable = false;
removeSaveBtn();
}
function addSaveBtn() {
const cardAccess = document.querySelector('.card');
const saveBtn = document.createElement('button');
saveBtn.id = 'edit-save-btn';
saveBtn.textContent = 'Save';
if (document.getElementById('edit-save-btn')) {
return;
} else {
cardAccess.insertAdjacentElement('beforeend', saveBtn);
}
saveBtn.addEventListener('click', () => {
const h3 = document.querySelector('h3');
const h4 = document.querySelector('h4');
const p = document.querySelector('p');
h3.classList.remove('edit');
h4.classList.remove('edit');
p.classList.remove('edit');
h3.contentEditable = false;
h4.contentEditable = false;
p.contentEditable = false;
removeSaveBtn();
});
}
function removeSaveBtn() {
if (!document.getElementById('edit-save-btn')) {
return;
} else {
document.getElementById('edit-save-btn').remove();
}
}
editBtn.addEventListener('click', editable);
cancelBtn.addEventListener('click', cancelEdit);```

Edit:
To add a cancel button:
Create a variable that stores the innerHTML when save was pressed.
Set the innerHTML of the contenteditable element to this variable when the cancel button is pressed.
Full Example:
// Set up the variable
var savedText = content.innerHTML;
save.onclick = ()=>{
// store the current content in savedText
savedText = content.innerHTML;
}
cancel.onclick = ()=>{
// set the new html content to what was stored
content.innerHTML = savedText;
}
<div id="content" contenteditable="true"><h1>Edit Me!</h1></div>
<button id="save">Save</button>
<button id="cancel">Cancel</button>
The contentEditable property takes a string, so you probably want something like this:
function cancelEdit() {
const h3 = document.querySelector('h3');
const h4 = document.querySelector('h4');
const p = document.querySelector('p');
h3.classList.remove('edit');
h4.classList.remove('edit');
p.classList.remove('edit');
h3.contentEditable = "false";
h4.contentEditable = "false";
p.contentEditable = "false";
removeSaveBtn();
}
function editable() {
const h3 = document.querySelector('h3');
const h4 = document.querySelector('h4');
const p = document.querySelector('p');
h3.className = 'edit';
h4.className = 'edit';
p.className = 'edit';
h3.contentEditable = "true";
h4.contentEditable = "true";
p.contentEditable = "true";
addSaveBtn();
}
Example with toggling:
toggle.onclick = ()=>{
content.contentEditable = (!content.isContentEditable).toString();
toggle.textContent = content.isContentEditable ? "Turn Editability Off" : "Turn editability On"
}
<div id="content" contenteditable="true"><h1>Edit Me!</h1></div>
<button id="toggle">Turn Editability Off</button>

Related

create a Edit Button while manipulating DOM in javascript

I am creating a simple TODO APP, which adds and deletes and edits a task when it's added, I am trying to figure out how to do edit a task. should I create a new P tag and equal it to par.value?
h1.innerText = 'TODO LIST';
document.body.appendChild(h1);
const input = document.createElement('input');
document.body.appendChild(input);
const addBtn = document.createElement('button');
addBtn.innerText = 'Add';
document.body.appendChild(addBtn);
const container = document.createElement('div');
container.innerText = 'Output';
document.body.appendChild(container);
addBtn.addEventListener('click', function(){
const par = document.createElement('p');
par.innerText = input.value;
container.appendChild(par);
const deleteBtn =document.createElement('button');
deleteBtn.innerText = 'Delete';
par.appendChild(deleteBtn);
const editBtn = document.createElement('button');
editBtn.innerText = 'Edit';
par.appendChild(editBtn);
deleteBtn.addEventListener('click', function(){
this.parentElement.remove();
editBtn.addEventListener('click', function(){
})
})
})
There are many ways how you can do this. One way is to use the attribute contenteditable for your paragraph. See this example:
const h1 = document.createElement('h1');
h1.innerText = 'TODO LIST';
document.body.appendChild(h1);
const input = document.createElement('input');
document.body.appendChild(input);
const addBtn = document.createElement('button');
addBtn.innerText = 'Add';
document.body.appendChild(addBtn);
const container = document.createElement('div');
container.innerText = 'Output';
document.body.appendChild(container);
addBtn.addEventListener('click', function() {
const par = document.createElement('p');
par.innerText = input.value;
container.appendChild(par);
const deleteBtn = document.createElement('button');
deleteBtn.innerText = 'Delete';
container.appendChild(deleteBtn);
const editBtn = document.createElement('button');
editBtn.classList.add('edit');
editBtn.innerText = 'Edit';
container.appendChild(editBtn);
deleteBtn.addEventListener('click', function() {
this.parentElement.remove();
editBtn.addEventListener('click', function() {
})
})
})
// Since the selector ".edit" is dynamic, listen to all elements
document.querySelector('*').addEventListener('click', (e) => {
// Return, if the element has not the class "edit"
if (e.target.className !== 'edit') return
// Set attribute to the paragraph
e.target.previousSibling.previousSibling.setAttribute('contenteditable', 'true');
// focus the paragraph
e.target.previousSibling.previousSibling.focus();
});

how to subtract a number on the second button click?

function createElement(){
const input = document.getElementById("input");
const ul = document.getElementById("ul");
const li = document.createElement("li");
const div = document.createElement("div");
div.innerText = input.value;
const btn = document.createElement("button");
btn.innerText = "add 2";
li.appendChild(div);
li.appendChild(btn);
ul.appendChild(li);
btn.onclick = () => {
let num = parseInt(div.innerText);
num = num + 2;
const roundednum = num.toFixed(2);
div.innerText = roundednum;
btnCLicked = true;
}
}
document.getElementById("btn").addEventListener("click", createElement);
<input type="number" id="input">
<ul id="ul"></ul>
<button id="btn">click me</button>
i have this simple code above that creates some elements, and it will add 2 to the number in the div when button inside the <li> is clicked, which works perfectly
now i want to subtract 2 from the number when button is clicked the second time, so first click will add 2, second click will subtract 2
so i come up with this code which uses a boolean to add and subtract the number which works
let btnCLicked = false;
function createElement(){
const input = document.getElementById("input");
const ul = document.getElementById("ul");
const li = document.createElement("li");
const div = document.createElement("div");
div.innerText = input.value;
const btn = document.createElement("button");
btn.innerText = "add 2";
li.appendChild(div);
li.appendChild(btn);
ul.appendChild(li);
btn.onclick = () => {
if (btnCLicked === false) {
let num = parseInt(div.innerText);
num = num + 2;
const roundednum = num.toFixed(2);
div.innerText = roundednum;
btnCLicked = true;
}else if (btnCLicked === true) {
let num = parseInt(div.innerText);
num = num - 2;
const roundednum = num.toFixed(2);
div.innerText = roundednum;
btnCLicked = false;
}
}
}
document.getElementById("btn").addEventListener("click", createElement);
<input type="number" id="input">
<ul id="ul"></ul>
<button id="btn">click me</button>
but now the problem is that when i create an <li>, and click the button inside to add 2 to the number, btnClicked is now set to true.
so when i create another element and click the button for the first time it will subtract the number because btnClicked is true, which is what i dont want, i want the first click to add and subtract on the second click
how do i solve that problem? im thinking about something like making the boolean only inside each li so each li has an own boolean and it will not effect other elements but idk lol i have no other idea
Move the let btnCLicked = false; into the function. Each invocation of createElement() will create a [closure`]1 since it's child function (click handler) is using variables from parents scope:
const input = document.getElementById("input");
const ul = document.getElementById("ul");
function createElement() {
let btnCLicked = false;
const li = document.createElement("li");
const div = document.createElement("div");
const btn = document.createElement("button");
div.innerText = input.value || 0;
btn.innerText = "add 2";
li.appendChild(div);
li.appendChild(btn);
ul.appendChild(li);
btn.onclick = () => {
let num = Number(div.innerText);
if (btnCLicked === false) {
num += 2;
} else {
num -= 2;
}
div.innerText = num;
btnCLicked = !btnCLicked;
}
}
document.getElementById("btn").addEventListener("click", createElement);
<input type="number" id="input">
<ul id="ul"></ul>
<button id="btn">click me</button>
Another solution: use event delegation and use a data-attribute to track the last action (add or subtract):
document.addEventListener("click", handle);
function createElement() {
document.querySelector("#ul").insertAdjacentHTML("beforeend", `
<li>
<div>${(+document.querySelector("#input").value).toFixed(2)}</div>
<button data-action="add">2</button>
</li>`);
}
function handle(evt) {
const origin = evt.target;
if (origin.id === "btn") {
return createElement();
}
if (origin.dataset.action) {
return addOrSubtract2(origin);
}
}
function addOrSubtract2(fromBttn) {
const parentLi = fromBttn.closest("li");
const add = fromBttn.dataset.action === "add";
const num = +(parentLi.querySelector("div").textContent) + (add ? 2 : -2);
fromBttn.dataset.action = add ? "subtract" : "add";
parentLi.querySelector("div").textContent = num.toFixed(2);
}
[data-action]:before {
content: attr(data-action)' ';
}
<input type="number" id="input" value=0 step="0.1">
<button id="btn">create new</button>
<ul id="ul"></ul>

Uncaught TypeError: Cannot read property 'remove' of null error console

I am trying to use media query JS, but when the device is minimized or enlarged an error appears.
My code:
<script type="text/javascript">
// media query event handler
if (matchMedia) {
const mq = window.matchMedia("(max-width: 1100px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
const h = document.querySelector(".right-bar");
h.insertAdjacentHTML(
"afterend",
"<div class='header-mobile'><label class='show-menu-btn' for='chk'><i class='fas fa-align-justify'/></label><label class='hide-menu-btn' for='chk'><i class='fas fa-times'/></label><label class='search-menu-btn' for='check'><i class='fas fa-search'/></label><label class='tutup-menu-btn' for='check'><i class='fas fa-times'/></label></div>"
);
// ambil semua element icon
const ambil = document.querySelector(".hide-menu-btn");
const ambil1 = document.querySelector(".show-menu-btn");
const ambil2 = document.querySelector(".search-menu-btn");
const ambil3 = document.querySelector(".tutup-menu-btn");
// hilangkan icon tutup
ambil.style.display = "none";
ambil3.style.display = "none";
// menambahkan element p HTML header
ambil1.addEventListener("click", function () {
const l = document.querySelector("#search-box");
l.insertAdjacentHTML(
"afterend",
"<p id='cons'>TERHUBUNG KE ADMIN</p>"
);
const divbaru = document.createElement("p");
const tulisanbaru = document.createTextNode(
"2020#admin.com All right reserved"
);
divbaru.appendChild(tulisanbaru);
const d1 = document.querySelector(".right-bar");
d1.appendChild(divbaru);
d1.style.left = "0";
ambil1.style.display = "none";
ambil.style.display = "block";
});
ambil.addEventListener("click", function () {
const k = document.querySelector("#cons");
k.remove();
const e = document.querySelector(".right-bar p");
e.remove();
ambil.style.display = "none";
ambil1.style.display = "block";
const f = document.querySelector(".right-bar");
f.style.left = "-101%";
});
} else {
const g = document.querySelector(".header-mobile");
g.remove();
const a = document.querySelector(".right-bar");
a.style.left = '-101%';
const m = document.querySelector("#cons");
m.remove();
const z = document.querySelector(".right-bar p");
z.remove();
}
}
</script>
I have a code like the one below, but the error on Google Chrome states the following:
It comes from here:

Javascript Shift-Click checkboxes To Do App

I'm currently building off Wes Bos Javascript 30 project.
Turned the project into a to-do app. And I can't figure out how to use the shift-clicking on newly created checkboxes using vanilla javascript.
Any insight on how to do this?
const addBtn = document.querySelector('.addBtn');
const myInput = document.getElementById('myInput');
const toDo = document.querySelector('.toDo-container');
const checkbox = document.querySelectorAll('.toDo-container input[type=checkbox]');
addBtn.addEventListener('click', newElement);
myInput.addEventListener("keyup", function(e){
if(e.keyCode === 13){
e.preventDefault()
newElement() }
});
// Create a new item when clicking on the "Add" button
function newElement(){
let div = document.createElement('div');
let input = document.createElement('input');
let inputValue = document.getElementById('myInput').value;
let textNode = document.createTextNode(inputValue);
let p = document.createElement('p');
div.className = "item";
input.type = "checkbox";
p.appendChild(textNode);
div.appendChild(input);
div.appendChild(p);
toDo.appendChild(div);
if(inputValue !== ""){
document.getElementById("myInput").value = "";
}
}
// Shift Clicking Checkboxes.
let lastChecked;
function shiftClick(e){
let inBetween = false;
if(e.shiftKey && this.checked){
checkbox.forEach(box => {
if(box === this || box === lastChecked){
inBetween = !inBetween
}
if(inBetween){
box.checked = true;
}
});
}
lastChecked = this;
}
checkbox.forEach(box => box.addEventListener('click', shiftClick));
https://codepen.io/iameddieyayaya/pen/XGWaQN?editors=1011
Thanks a ton!
Eddie G.
You can set a flag when the shift key is pressed and reset it when the key is released. Then your click listener can just act conditionally based on the state of the flag. (I don't know if focusing the whole container as I've done here is the best way to ensure that you don't fail to notice any keystrokes, but it works.)
const container = document.getElementById("container");
const box = document.getElementById("box");
let shiftIsDown = false;
container.addEventListener("keydown", setShiftFlag);
container.addEventListener("keyup", setShiftFlag);
box.addEventListener("click", handleBoxClick);
container.focus();
function setShiftFlag(event){
if(event.code == "ShiftLeft" || event.code == "ShiftRight"){
if(event.type == "keydown"){
shiftIsDown = true;
}
else if(event.type == "keyup"){
shiftIsDown = false;
}
}
}
function handleBoxClick(){
if(shiftIsDown){
console.log("shift-click");
}
else{
console.log("click");
}
}
body{ height: 100px; }
#container{ width: 100%; height: 100%; }
<body>
<div id="container" tabindex="0">
<input type="checkbox" id="box" />
</div>
</body>

input.value is destroyed after swapping <li> items in places

I have a simple ul with list items that contain few buttons. Two buttons are navigational they suppose to move list items either forward or backward.
The problem is: whenever I click Previous or Next button, the text in the list item disappears. Moreover, additional edit button adds up after each click.
Is there a way to preserve the text in list items after they get swapped in places?
const form = document.querySelector('form');
const ul = document.querySelector('ul');
const listItem = document.querySelector('li');
const addItemInput = document.querySelector('input.add-item-input');
const addItemButton = document.querySelector('button.add-item-button');
const removeItemButton = document.querySelector('button.remove-item-button');
function attach_span(li) {
const span = document.createElement('span');
span.textContent = addItemInput.value;
li.appendChild(span);
}
function attach_br(li) {
const br = document.createElement('br');
li.appendChild(br);
}
function attachButton_previous(li) {
const prev = document.createElement('button');
prev.className = 'previous';
prev.textContent = 'Previous';
if(li.previousElementSibling) li.appendChild(prev);
}
function attachButton_remove(li) {
const remove = document.createElement('button');
remove.className = 'remove';
remove.textContent = 'Remove';
li.appendChild(remove);
}
function attachButton_edit(li) {
const edit = document.createElement('button');
edit.className = 'edit';
edit.textContent = 'Edit';
li.appendChild(edit);
}
function attachButton_next(li) {
const next = document.createElement('button');
next.className = 'next';
next.textContent = 'Next';
li.appendChild(next);
}
function attachListItems(li) {
attach_span(li);
attach_br(li);
attachButton_previous(li);
attachButton_remove(li);
attachButton_edit(li);
attachButton_next(li);
}
addItemButton.addEventListener('click', () => {
const li = document.createElement('li');
ul.appendChild(li);
attachListItems(li);
addItemInput.value = '';
});
removeItemButton.addEventListener('click', () => {
const ul = document.getElementsByTagName('ul')[0];
const li = document.querySelector('li:last-child');
ul.removeChild(li);
});
ul.addEventListener('click', (e) => {
if(e.target.tagName === 'BUTTON' ) {
const button = e.target;
const li = button.parentNode;
const ul = li.parentNode;
const prevEl = li.previousElementSibling;
const nextEl = li.nextElementSibling;
if(button.className === 'remove') {
ul.removeChild(li);
}
if(button.className === 'previous') {
if(prevEl) {
ul.insertBefore(li, prevEl);
}
}
if(button.className === 'next') {
if(nextEl) {
ul.insertBefore(nextEl, li);
}
}
if(button.className === '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.className = 'save';
button.textContent = 'Save';
} else {
const input = li.firstElementChild;
const span = document.createElement('span');
span.textContent = input.value;
li.insertBefore(span, input);
li.removeChild(input);
button.className = 'edit';
button.textContent = 'Edit';
}
}
});
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<header></header>
<article>
<nav id="main-nav">
<ul>
</ul>
</nav>
<form class="form">
<input class="add-item-input" name="itemInput" type="text" title="Input for menu items">
<button class="add-item-button" type="button">Add item</button>
<button class="remove-item-button" type="button">Remove last item</button>
</form>
</article>
<p id="spitResult"></p>
<!-- <script src="js/functions.js"></script> -->
<script src="js/app.js"></script>

Categories

Resources