I want to create a to do list that will add elements typed in <input type="text"> and delete when clicked on button with class .delete. When ever I push elements in an array. And innerHTML it in html page, the delete button stops working. The delete button works for elements that are written into Html code. If someone can help me I will be very thankful.
`
const itemsLIst = document.querySelector('.item-list'); // where we want to add our list
const addText = document.querySelector('.submit'); // add button
let deleteText = document.querySelectorAll('.delete'); // delete button
// const list = JSON.parse(localStorage.getItem('items')) || [];
let list = [];
function addItem(e) {
let text = document.querySelector('.input_bar').value; //text typed in input bar
if (text.length != 0) {
list.push(`<div>
<p>${text}</p>
<button class="delete" onclick='deleteItem'>🗴</button>
<button class="edit">Edit</button>
</div><hr>`);
itemsLIst.innerHTML = list.join('');
text = '0';
document.getElementById("myText").value = "";
} else {
return;
}
}
function deleteItem(e) {
this.parentElement.style.display = 'none';
}
for (var i = 0 ; i < deleteText.length; i++) {
deleteText[i].addEventListener('click', deleteItem);
}
addText.addEventListener('click', addItem);
<style>
body {
width: 100%;
height: 100vh;
background-color: rgb(115, 115, 197);
margin: 0;
padding: 0;
position: relative;
}
.container {
width:50%;
height:70%;
position: absolute;
background-color: rgb(241, 241, 241);
font-family: Arial, Helvetica, sans-serif;
border-bottom-left-radius: 25px;
border-bottom-right-radius: 25px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
overflow-y: scroll;
}
.heading {
width: 100%;
height: 122px;
background-color: #5B45B9;
display: flex;
align-items: center;
justify-content: center;
}
.heading h1 {
color: white;
font-size: 40px;
}
.item-list {
width: 100%;
padding: 0 0 30px 0;
}
.item-list div {
width: auto;
height: 60px;
}
p {
width: 60%;
float: left;
font-size: 25px;
padding-left: 30px;
margin-top: 12px ;
}
.item-list button {
width: 60px;
height: 60px;
font-size: 18px;
float: right;
}
.delete {
font-size: 30px;
color: red;
}
.input_form {
width: 100%;
padding: 30px 0 30px 0;
position: absolute;
bottom: 0;
text-align: center;
}
.input_form .input_bar {
width: 80%;
height: 50px;
font-size: 18px;
border: none;
}
.input_form button {
width: 10%;
height: 50px;
float: right;
margin-right: 30px;
}
</style>
<html>
<head>
</head>
<body>
<div class="container">
<div class="heading">
<h1>TO-DO LIST</h1>
</div>
<div class="item-list">
<div>
<p>TEEXT2</p>
<button class="delete">🗴</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT1</p>
<button class="delete">🗴</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT3</p>
<button class="delete">🗴</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT4</p>
<button class="delete">🗴</button>
<button class="edit">Edit</button>
</div>
</div>
<div class="input_form">
<input type="text" class="input_bar" id="myText" placeholder="Add ITEM">
<button class="submit">+ADD ITEM</button>
</div>
</div>
</body>
</html>
<button class="delete">🗴</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT1</p>
<button class="delete">🗴</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT3</p>
<button class="delete">🗴</button>
<button class="edit">Edit</button>
</div>
<div>
<p>TEEXT4</p>
<button class="delete">🗴</button>
<button class="edit">Edit</button>
</div>
</div>
<div class="input_form">
<input type="text" class="input_bar" id="myText" placeholder="Add ITEM">
<button class="submit">+ADD ITEM</button>
</div>
<script src="script.js"></script>
</div>
</body>
</html>`
You actually only trigger DOM "original" delete button (button loaded with your HTML code) with the line :
let deleteText = document.querySelectorAll('.delete'); // delete button
Your others .delete are loaded after the first DOM loading and are not even listed in "deleteText" array !
You have to refresh deleteText every time you add a new item. Something like :
const itemsLIst = document.querySelector('.item-list'); // where we want to add our list
const addText = document.querySelector('.submit'); // add button
let deleteText = document.querySelectorAll('.delete'); // delete button
// const list = JSON.parse(localStorage.getItem('items')) || [];
let list = [];
function addItem(e) {
let text = document.querySelector('.input_bar').value; //text typed in input bar
if (text.length != 0) {
list.push(`<div>
<p>${text}</p>
<button class="delete" onclick='deleteItem'>🗴</button>
<button class="edit">Edit</button>
</div><hr>`);
itemsLIst.innerHTML = list.join('');
text = '0';
document.getElementById("myText").value = "";
} else {
return;
}
}
function deleteItem(e) {
this.parentElement.style.display = 'none';
}
function triggerDeleteButton(){
deleteText = document.querySelectorAll('.delete'); // delete button
for (var i = 0 ; i < deleteText.length; i++) {
deleteText[i].addEventListener('click', deleteItem);
}
}
addText.addEventListener('click', function(){
addItem() ;
triggerDeleteButton() ;
}
);
Without refreshing, you can add and edit data by using local storage
For example, like below, you can try once!
<script>
let customerData = [];
// Inserting new customer record into local storage
function insert() {
let company = document.getElementById("company").value;
let obj = {company};
customerData.push(obj);
synData(customerData);
let customerDetails = JSON.parse(localStorage.getItem("customerString"));
clearFileds();
displayelements(customerDetails);
}
function displayelements(customerDetails) {
let html = "<table id='customer_data' border='1'><tr><th>Sl No</th><th>Company</th><th>Delete</th></tr>";
if(customerDetails == '') {
html+="<tr>No record found!</tr>";
} else {
customerDetails.map((values, index) => {
html+="<tr id='row_data'>";
html+="<td>"+index+"</td>";
html+="<td>"+values.company+"</td>";
html+="<td onclick='deleteRow(" + index + ")'>Delete</td>";
html+="</tr>";
} )
}
html+="</table>";
document.getElementById("display").innerHTML = html;
clearFileds();
}
// Delete the specific customer record from local storage
function deleteRow(deleteKey) {
let customerDetails = JSON.parse(localStorage.getItem("customerString"));
customerDetails.map((values, index) => {
if (index == deleteKey) {
customerDetails.splice(index, 1);
}
})
customerData = customerDetails;
synData(customerDetails);
displayelements(customerDetails);
}
// Clearing the form input field data
function clearFileds() {
document.getElementById("company").value = '';
}
// Updating local storage data
function synData(customerDetails) {
localStorage.setItem('customerString', JSON.stringify(customerDetails));
}
</script>
<html>
<head>
<title>Save</title>
</head>
<script ></script>
<body id="format_background">
<div id="customerAction" >
<h1>Customer data</h1>
<label>Company Name </label>
<input id="company" type="text" />
<button type="button" value="Save&Show" onclick="insert()" id="insert">Save</button>
</div>
<div id="display"></div>
</body>
</html>
Related
I have currently figured out a way to store value of 6am plan in a content editable box in my local storage key
item 2
How do I make this happen for all the other hours like 1
work plan for every hour of the day 6 am - 11pm
storing input in one key
using this code snippet below
javascript -
var content = document.getElementById('content'),
address = document.getElementById('address'),
saveButton = document.getElementById('save'),
loadButton = document.getElementById('load'),
clearButton = document.getElementById('clear'),
resetButton = document.getElementById('reset');
var localStore = {
saveLocalStorage: function() {
localStorage.setItem('item', content.innerHTML);
},
loadLocalStorage: function() {
var contentStored = localStorage.getItem('item');
if ( contentStored ) {
content.innerHTML = contentStored;
}
},
clearLocalStorage: function() {
localStorage.removeItem('item');
}
};
saveButton.addEventListener('click', function() {
localStore.saveLocalStorage();
}, false);
<r class="notion-table-row">
<td
style="color: inherit; fill: inherit; border: 1px solid gb(233, 233, 231); position: relative; vertical-align: top; min-width: 122px; max-width: 122px; min-height: 32px;">
<div class="notion-table-cell">
<div class="notion-table-cell-text"
spellcheck="true" placeholder=" "
data-content-editable-leaf="true"
style="max-width: 100%; width: 100%; white-space: pre-wrap; word-break: break-word; caret-colour: gb(55, 53, 47); padding: 7px 9px; background-colour: transparent; font-size: 14px; line-height: 20px;"
content editable="false">11 PM</div>
</div>
</td>
<td
style="color: inherit; fill: inherit; border: 1px solid gb(233, 233, 231); position: relative; vertical-align: top; min-width: 200px; max-width: 200px; min-height: 32px;">
<div class="notion-table-cell">
<div class="notion-table-cell-text"
spellcheck="true" placeholder=" "
data-content-editable-leaf="true"
style="max-width: 100%; width: 100%; white-space: pre-wrap; word-break: break-word; caret-colour: gb (55, 53, 47); padding: 7px 9px; background - colour: transparent; font-size: 14px; line-height: 20px;"
<section id="11pm_input" content editable="true"></div>
Store all of the data in an array. Keep in mind, localStorage stores only strings so anything not a string (ex. array, object, number, etc.), must be converted into a string when saved to localStorage:
localStorage.setItem("String", JSON.stringify([...Array]))
and when it is retrieved from localStorge it needs to be parsed into it's original type:
const data = JSON.parse(localStorage.getItem("String"));
In the example below, the data is gathered from all .cell which comprise of the following HTML elements from the table head and body (in ex. 4 x time, 6 x data):
<time class='cell' datetime="23:00">11 PM</time>
<data class='cell' value="0ne Zer0">Zer0 0ne</data>
time.datetime = "23:00";
time.textContent = "11 PM";
data.value = "0ne Zer0";
data.textContent = "Zer0 0ne";
lStorage = [
["23:00", "11 PM"],
["0ne Zer0", "Zer0 0ne"],
["00:00", "12 AM"],
...[N, N]
];
The event handler manageData(event) delegated all click events triggered on the table head, body, and foot.
Variables:
key is whatever the user typed in .input, the value will be assigned to data being saved to localStorage.
data is declared for data coming from and to localStorage.
cells is an array of all time.cell and data.cell tags within the table head and body.
node is determined by event.target property which always refers to the tag the user actually clicked. This reference will be delegated to react according to the .matches() method and a series of flow control statements (if, if else, and else).
The process for loading data from localStorage involves loadData(key) and iteration of the array of arrays saved in localStorage and the array of .cells:
if (node.matches('.load')) {...
...
data = loadData(key);
cells.forEach((n, i) => {
n.textContent = data[i][1];
if (n.matches('time')) {
n.datetime = data[i][0];
} else {
n.value = data[i][0];
}
});
The rest of the code is of simular fashion -- here's a brief description of what it can do:
Load data from key in localStorage and popualte a <table> with it.
Save data from a <table> to a key in localStorage.
Reset data the user typed in the fields (if given a selector, it can reset it as well).
Clear data by key and all data in <table> (including static data).
All .cells are editable (including headers). Double click any .cell within the table head or body to toggle it in/out of edit mode.
Due to SO security policy, WebStorage API will not function, go to: Plunker
The link doesn't work for me when clicked but
I managed to use the url by copy & paste
to the address bar:
https://run.plnkr.co/preview/ckz3pfkfe0007386nlancnzqk/
If the links above don't work, you can copy & paste the code in the Snippet with a text editor and save the file with a *.html extension.
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
:root {
font: 1ch/1.5 'Segoe UI';
}
body {
font-size: 2ch;
}
table {
table-layout: fixed;
width: 70vw;
margin: 20px auto;
}
th {
width: 50%;
font-size: 2.25rem;
}
td {
vertical-align: center;
}
.box {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
min-height: 32px;
padding: 8px 8px 5px;
}
.cell {
display: block;
max-width: 100%;
width: 100%;
min-height: 25px;
white-space: pre-wrap;
word-break: break-word;
font-size: 2rem;
border: 2px solid #000;
background: transparent;
text-align: center;
}
.head {
width: 97.5%;
border-color: transparent;
}
.edit {
border-color: blue;
}
button {
display: block;
font: inherit;
font-size: 2rem;
background: transparent;
border-radius: 6px;
cursor: pointer;
}
button:hover {
border-color: blue;
color: blue;
background: #ddd;
}
.ctrl {
position: relative;
flex-flow: row nowrap;
justify-content: space-between;
min-width: 92%;
height: 30px;
margin-top: 40px;
}
.input {
position: absolute;
top: -40px;
left: -0.5vw;
width: 99%;
height: 25px;
}
.noKey {
color: tomato;
font-weight: 900;
border-color: tomato;
}
.noKey::before {
content: 'Enter the key to data';
}
.done {
color: blue;
border-color: blue;
}
.done::before {
content: 'Data is saved under key: "';
}
.done::after {
content: '"';
}
</style>
</head>
<body>
<main>
<section>
<table>
<thead>
<tr>
<th>
<data class="cell head" value="Hour">Hour</data>
</th>
<th>
<data class="cell head" value="Employee">Employee</data>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<fieldset class="box">
<time class="cell">8 PM</time>
</fieldset>
</td>
<td>
<fieldset class="box">
<data class="cell edit" contenteditable></data>
</fieldset>
</td>
</tr>
<tr>
<td>
<fieldset class="box">
<time class="cell">9 PM</time>
</fieldset>
</td>
<td>
<fieldset class="box">
<data class="cell edit" contenteditable></data>
</fieldset>
</td>
</tr>
<tr>
<td>
<fieldset class="box">
<time class="cell">10 PM</time>
</fieldset>
</td>
<td>
<fieldset class="box">
<data class="cell edit" contenteditable></data>
</fieldset>
</td>
</tr>
<tr>
<td>
<fieldset class="box">
<time class="cell">11 PM</time>
</fieldset>
</td>
<td>
<fieldset class="box">
<data class="cell edit" contenteditable></data>
</fieldset>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<fieldset class="ctrl box">
<data class="cell input edit" contenteditable></data>
<button class="load" title="Load data">
Load</button>
<button class="save" title="Save data">
Save</button>
<button class="reset" title="Reset fields">
Reset</button>
<button class="clear" title="Clear saved data and Reset fields">
Clear</button>
</fieldset>
</td>
</tr>
</tfoot>
</table>
</section>
</main>
<script>
const tab = document.querySelector('table');
const hdr = tab.tHead;
const mid = tab.tBodies[0];
const ftr = tab.tFoot;
const cls = ['noKey', 'done'];
const inp = document.querySelector('.input');
const formatTime = time => {
const T = time.split(' ');
return T[1] === 'PM' ? `${+T[0]+12}:00` : `${T[0]}:00`;
};
const lastFirst = name => name.split(' ').reverse().join(', ');
const loadData = key => JSON.parse(localStorage.getItem(key));
const saveData = (key, data) => localStorage.setItem(key, JSON.stringify(data));
const resetData = selector => {
let nodes = selector === undefined ? '.edit' : selector;
[...document.querySelectorAll(nodes)].forEach(n => {
n.textContent = '';
if (n.matches('time')) {
n.datetime = '';
} else {
n.value = '';
}
});
inp.classList.remove(...cls);
};
const clearData = key => {
resetData('.cell');
inp.classList.remove(...cls);
localStorage.removeItem(key);
};
const manageData = e => {
let key = inp.textContent;
let data;
const cells = [...document.querySelectorAll('.cell')];
const node = e.target;
if (node.matches('.load')) {
if (key.length < 1) {
inp.classList.add('noKey');
} else {
data = loadData(key);
cells.forEach((n, i) => {
n.textContent = data[i][1];
if (n.matches('time')) {
n.datetime = data[i][0];
} else {
n.value = data[i][0];
}
});
}
} else if (node.matches('.save')) {
if (key.length < 1) {
inp.classList.add('noKey');
} else {
data = cells.flatMap(n => {
if (n.matches('time')) {
n.datetime = formatTime(n.textContent);
return [
[n.datetime, n.textContent]
];
} else {
n.value = lastFirst(n.textContent);
return [
[n.value, n.textContent]
];
}
});
inp.classList.add('done');
saveData(key, data);
}
} else if (node.matches('.reset')) {
resetData();
} else if (node.matches('.clear')) {
if (key.length < 1) {
inp.classList.add('noKey');
} else {
clearData(key);
}
} else if (node.matches('.input')) {
node.textContent = '';
node.classList.remove(...cls);
} else {
return;
}
};
ftr.onclick = manageData;
const toggleEdit = e => {
const node = e.target;
if (node.matches('.cell')) {
node.classList.toggle('edit');
node.toggleAttribute('contenteditable');
}
};
hdr.ondblclick = toggleEdit;
mid.ondblclick = toggleEdit;
</script>
</body>
</html>
I am working on an assignment, that constructs a small library. The project requires, that the user can input the title of a book, its author, number of pages and if the user has already read it. Then the content gets displayed on the page.
Here's the code (work in progress):
let myLibrary = [];
let submitBtn = document.querySelector("#submitBtn");
let textInput = document.querySelectorAll("input");
let addNew = document.getElementById("addNew");
let fieldSet = document.getElementById("fieldset");
let cancelBtn = document.querySelector("#cancelBtn");
let bookDisplay = document.getElementById("bookDisplay");
let flexItems = document.getElementsByClassName("flexItems");
// object Constructor for new books
class Book {
constructor(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
}
Book.prototype.addToDisplay = function() {
let newDiv = document.createElement("div");
bookDisplay.appendChild(newDiv).className = "flexItems";
let newSpan = document.createElement("span");
flexItems[myLibrary.length-1].appendChild(newSpan).className = "spanItem";
newSpan.innerText = this.title;
this.read === true ? flexItems[myLibrary.length-1].style.backgroundColor = "green" :
flexItems[myLibrary.length-1].style.backgroundColor = "red";
newDiv.addEventListener("mouseenter", moreInfo => {
newSpan.childNodes[0].nodeValue = this.author + "\n" + this.title + "\n" + this.pages + " pages";
})
newDiv.addEventListener("mouseleave", defaultInfo => {
newSpan.childNodes[0].nodeValue = this.title;
})
}
// creates a new instance of Book and pushes the object into the array
let addToLibrary = function addToLibrary() {
newBook = new Book(textInput[0].value, textInput[1].value, textInput[2].value, textInput[3].checked)
myLibrary.push(newBook);
newBook.addToDisplay();
};
// eventlistener, to submit a new Book to the library
submitBtn.addEventListener("click", addToLibrary);
// sets the form's display from block to non-visible
let cancel = function cancel() {
fieldSet.style.display = "none";
}
// cancels the form and returns back
cancelBtn.addEventListener("click", cancel);
// sets the form's display from non-visible to visible
let openForm = function openForm() {
fieldSet.style.display = "block";
}
// opens form to add new book
addNew.addEventListener("click", openForm);
body {
margin-left: 20px;
}
h1 {
text-align: center;
}
#fieldset {
position: fixed;
z-index: 2;
border: none;
display: none;
background: #3CBC8D;
border-radius: 10px;
right: 1%;
top: 2%;
width: 400px;
height: auto;
overflow: auto;
}
button {
cursor: pointer;
}
.display {
display: flex;
flex-direction: row;
flex-wrap: wrap;
position: relative;
}
.flexItems {
position: relative;
display: flex;
margin: 5px;
color: black;
font: Georgia;
font-size: 20px;
height: 200px;
width: 200px;
align-items: center;
border: 2px solid gray;
transition: 500ms;
border-radius: 5px;
}
.spanItem {
width: 100%;
text-align: center;
white-space: wrap;
overflow: hidden;
text-overflow: ellipsis;
}
.display .flexItems:focus,
.display .flexItems:hover {
transform: scale(1.2);
z-index: 1;
}
#addNew {
position: fixed;
z-index: 2;
border: none;
background: #3CBC8D;
color: white;
border-radius: 10px;
right: 2%;
top: 2%;
width: 100px;
height: 50px;
overflow: auto;
cursor: pointer;
}
/*. Could be additionally used for the hover-effect, but doesnt look that nice for more than one row
flexItems:hover ~.flexItems {
transform: translateX(25%);
}
.display:focus-within .flexItems,
.display:hover .flexItems {
transform: translateX(-25%);
}
.flexItems:focus ~.flexItems,
.flexItems:hover ~.flexItems {
transform: translateX(25%);
} */
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<link href="style.css" rel="stylesheet" type="text/css" />
<script src="script.js" defer></script>
<title>Library</title>
</head>
<body>
<div><h1>My book library</h1></div>
<div id="bookDisplay" class="display">
</div>
<div>
<button id="addNew">Test</button>
</div>
<fieldset id="fieldset">
<form id="form">
<div>
<label for="title">Title: </label>
<input type="text" name="title" id="title" class="usrInput">
</div>
<div>
<label for="author">Author: </label>
<input type="text" name="author" id="author" class="usrInput">
</div>
<div>
<label for="number">Number of pages: </label>
<input type="number" name="number" id="number" class="usrInput">
</div>
<div>
<label for="read">Already read?: </label><br>
Y <input type="radio" name="read" id="read" value="Y" class="read">
N <input type="radio" name="read" id="read" value="N" class="read">
</div>
<button id="submitBtn" type="button">Submit</button>
<button id="cancelBtn" type="button">Cancel</button>
</fieldset>
</div>
</body>
</html>
**My question: ** The code is working until here. But I have my concerns with the mouseenter-Eventlistener. On mouseenter, I want to add a <button>, to edit the book's value. And maybe there is moreto be added in the future. That would mean the à ddToDisplay() function eventually will get clunky. So I was wondering, if I could enter the Object.prototype of the addToDisplay() function and store all eventListeners in its prototype. Is this possible in Javascript?
The only way I could solve it right now is, to write an extra function for the eventlisteners. But it seems, that this way, I'm just going back to normal function expressions with dozens of values to pass by:
Book.prototype.addToDisplay = function() {
// (...)
mousehover(this, newDiv, newSpan)
}
let mousehover = function mousehover(test, newDiv, newSpan) {
newDiv.addEventListener("mouseenter", moreInfo => {
newSpan.childNodes[0].nodeValue = test.author + "\n" + test.title + "\n" + test.pages + " pages";
})
newDiv.addEventListener("mouseleave", defaultInfo => {
newSpan.childNodes[0].nodeValue = test.title;
})
}
Hope I got the problem across. It's the first assignment to Objects I'm working on.
Thanks for any answers and links to informative sources.
I am trying to create a simple post adder in Javascript. For some reason, it won't push my input. What am I doing wrong? Is there a better alternative to doing this?
let posts = [];
function sendPost () {
let post = document.getElementById("post").value;
document.getElementById("postSender").innerHTML=(post);
}
input {
background: lightgrey;
border: none;
padding: 10px;
border-radius: 15px;
outline-width: 0;
}
::placeholder {
color: grey;
}
<div id="app">
<div>
<input type="text" placeholder="hi" id="post">
<button value="submit" #click="sendPost();"> Hi
</div>
<div id="postSender">
<p>
</p>
</div>
</div>
Change your #click to onClick and change innerHTML value equal to your let post
const posts = [];
function sendPost () {
let HTML = '';
let post = document.getElementById("post").value;
posts.push(post);
posts.forEach(function(item) {
HTML += '<div>' + item + '</div>';
});
document.getElementById("postSender").innerHTML = HTML;
}
input {
background: lightgrey;
border: none;
padding: 10px;
border-radius: 15px;
outline-width: 0;
}
::placeholder {
color: grey;
}
<div id="app">
<div>
<input type="text" placeholder="hi" id="post">
<button value="submit" onClick="sendPost()"> Hi</button>
</div>
<div id="postSender"></div>
</div>
Edit: post added to posts array and displayed in separate divs
Update the #click to onclick and y create functions to grab the HTML elements.
Here is one way to do it:
//function that grab te input value
function getInputValue(){
return document.getElementById("post").value
}
//function that grab the div with id "postSender"
function getDivPostSender(){
return document.getElementById("postSender")
}
function sendPost () {
//create a ne p tag element
let pEl = document.createElement('p')
//Appends the p Tag to the div with id "postSender"
getDivPostSender().appendChild(pEl)
//Update the text on the p tag element.
pEl.innerText = getInputValue()
}
input {
background: lightgrey;
border: none;
padding: 10px;
border-radius: 15px;
outline-width: 0;
}
::placeholder {
color: grey;
}
<div id="app">
<div>
<input type="text" placeholder="hi" id="post">
<button onclick="sendPost()">Submit</button>
</div>
<div id="postSender">
</div>
</div>
this line is wrong
let post = document.getElementById("post").value
it should be
let post = document.getElementById("postSender").value
I am trying to create a text font colour drop down button where it gives you an option of multiple colour to pick from and then it would change the colour of the text. I am not sure on how to approach this and I am not meant to use jQuery. Any help would be appreciated. In the code below it shows other examples of other button where they change the user input entered into the contenteditable. I want the font colour button to do the same but just change the colour of the text
const TAB_KEY = 9;
const ENTER_KEY = 13;
const SHIFT_KEY = 16
const editor = document.querySelector('.editor');
editor.appendChild(document.createElement('li'));
editor.addEventListener('keydown', (e) => {
let code = e.keyCode || e.which;
if (code == TAB_KEY) {
e.preventDefault();
let parent = e.target;
let ul = document.createElement('ul');
let li = document.createElement('li');
ul.appendChild(li);
parent.appendChild(ul);
moveCursorToEnd(li);
} else if (code == ENTER_KEY) {
e.preventDefault();
let parent = e.target;
let li = document.createElement('li');
parent.appendChild(li);
moveCursorToEnd(li);
} else if (code == TAB_KEY * TAB_KEY){
e.preventDefault();
let parent = e.target;
let ol = document.createElement('ol');
let li = document.createElement('li');
ol.appendChild(li);
parent.appendChild(ol);
moveCursorToEnd(li);
}
});
function moveCursorToEnd(el) {
el.focus();
document.execCommand('selectAll', false, null);
document.getSelection().collapseToEnd();
}
/*editor.addEventListener('click', (x) => {
x = document.getElementById("b");
if(x.style.fontWeight == "bolder"){
x.style.fontWeight = "normal";
} else {
x.style.fontWeight = "bolder";
}
});*/
function bold(){
if(document.execCommand("bold")){
document.execCommand("normal");
}else{
document.execCommand("bold");
}
}
/*function underline(){
let x = document.getElementById("text");
if(x.style.textDecoration == "underline"){
x.style.textDecoration = "none";
}else{
x.style.textDecoration = "underline";
}
}*/
function underline(){
if(document.execCommand("underline")){
document.execCommand("none");
}else{
document.execCommand("underline");
}
}
/*Turns the font of the text to Italic*/
function italic(){
if(document.execCommand("italic")){
document.execCommand("normal");
}else{
document.execCommand("italic");
}
}
function highlighSelectedText(){
let sel = window.getSelection().getRangeAt(0);
let selText = sel.extractContents();
let span = document.createElement("span");
span.style.backgroundColor = "yellow";
span.appendChild(selText);
sel.insertNode(span);
}
/*function printPage(){
let printButton = document.getElementById("ul");
printButton.style.visibility = 'hidden';
window.print();
printButton.style.visibility = 'visible';
}*/
body{
margin-top:1em;
margin-bottom: 10em;
margin-right: 1em;
margin-left: 1em;
border: solid;
border-color: #0033cc;
background-color: #f6f6f6;
}
div button{
padding: 1em 2em;
color: white;
background-color: #0000cc;
}
div input{
padding: 1em 2em;
color: white;
background-color: #0000cc;
}
div{
list-style-type:square;
list-style-position: inside;
margin-left: 0.25em;
margin-bottom: 5em;
}
section {
padding: 1em 2em;
color: white;
background-color: #0000cc;
}
.editor {
font-weight: normal;
}
div contenteditable{
margin-bottom: 10em;
}
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<head>
<title>Outliner</title>
<link href="style.css" rel="stylesheet" title="Style">
<div>
<button id="b" onclick="bold()"> B </button>
<button onclick="underline()"> U </button>
<button onclick="italic()"> I </button>
<input type="button" onclick="highlighSelectedText()" value="Highlight"/>
<div id="text" class="editor" contenteditable="true" draggable="true"></div>
</div>
<section>
<input id="saveAs"></input>
<button onclick="saveTextFile()">Download</button>
<input type="file" id="load"/>
<button onclick="loadFile()">Load</button>
</section>
<section>
<button class="btn btn-primary" onclick="saveChanges()">Save Text</button>
<button class="btn btn-warning" onclick="clearStorage()">Reset</button>
</section>
</head>
<script type= "text/javascript" src='setting.js'></script>
</body>
First off we will use a CSS variable. Lets declare a value at :root
:root {
--font-color: #000;
}
Now we will use that value to style the font color of our P tags.
p {
color: var(--font-color);
}
Now when somebody clicks one of the color names, we want to change the value of --font-color. (Notice we are using the data- attribute model to store the color we want to change too).
document.documentElement.style.setProperty('--font-color', target.dataset.color);
And presto we can now change color easily. This works for other values also.
Here is a great article
document.addEventListener('click', ({ target }) => {
if(target.matches('p')) {
document.documentElement.style.setProperty('--font-color', target.dataset.color);
}
});
:root {
--font-color: #000;
}
p {
width: 30%;
border: 2px solid #00000030;
border-radius: 7px;
margin: 0.25rem;
padding: 0.25rem;
color: var(--font-color);
}
<h2>Click a color</h2>
<p data-color="#f00">Red</p>
<p data-color="#0f0">Green</p>
<p data-color="#00f">Blue</p>
<p data-color="#000">Reset</p>
You can manipulate the style variable:
<div id="text">
Choose a color
</div>
<input id="color" type="color">
<button onclick="document.getElementById('text').style.color = document.getElementById('color').value;">Change Color</button>
strong text
I have a box in a few boxes and placed inside each box for an hour.
I want to sort by using the box clock named item.
This sorting has three modes, the first ascending, the second descending, the third without sorting.
strong text
<body>
<style>
body{margin: 0 auto;padding: 0 auto;background: skyblue;}
.full-item{width: 800px;height: 600px;margin: 50px auto;background: grey;}
.full-item .button-item{width: 100%;height: 80px;background: #B33771;}
.full-item .button-item button{margin: 30px 45%;}
.full-item .item-sort{width: 100%;height: 500px;background: white;margin-top: 10px;}
.full-item .item-sort:first-child{margin-top: 10px;}
.full-item .item-sort .item{width: 90%;height: 140px;background: red;margin: 10px auto;}
.item-sort .item .pic{width: 30%;height: 100%;background: #3B3B98;float: left;}
.item-sort .item .time{width: 70%;height: 100%;background: #1B9CFC;float: right;}
.item-sort .item .time span{color: white;text-align: center;display: block;line-height: 100px;}
</style>
<div class="full-item">
<div class="button-item">
<button id="Sort-item">Sort by</button>
</div>
<div class="item-sort">
<div class="item">
<div class="pic"></div>
<div class="time"><span>15:20</span></div>
</div>
<div class="item">
<div class="pic"></div>
<div class="time"><span>13:10</span></div>
</div>
<div class="item">
<div class="pic"></div>
<div class="time"><span>18:40</span></div>
</div>
</div>
</div>
</body>
If the data is coming from JSON or other source, as with akbansa's recommendation, you should perform the sorting on the data first; otherwise, see below for an example of how you could reorder your elements:
const button = document.querySelector('#Sort-item')
// add handler
button.addEventListener('click', clickHandler)
// handler definition
function clickHandler(){
let container = document.querySelector('.item-sort')
let items = Array.from(container.querySelectorAll('.item-sort .item'))
// sort based on time
items = items.sort((a,b)=>{
let a_time = a.querySelector('.time span').textContent
let b_time = b.querySelector('.time span').textContent
return a_time > b_time ? 1 : -1
})
// apply the order
for(let item of items)
container.appendChild(item)
}
body {
margin: 0 auto;
padding: 0 auto;
background: skyblue;
}
.full-item {
width: 800px;
height: 600px;
margin: 50px auto;
background: grey;
}
.full-item .button-item {
width: 100%;
height: 80px;
background: #B33771;
}
.full-item .button-item button {
margin: 30px 45%;
}
.full-item .item-sort {
width: 100%;
height: 500px;
background: white;
margin-top: 10px;
}
.full-item .item-sort:first-child {
margin-top: 10px;
}
.full-item .item-sort .item {
width: 90%;
height: 140px;
background: red;
margin: 10px auto;
}
.item-sort .item .pic {
width: 30%;
height: 100%;
background: #3B3B98;
float: left;
}
.item-sort .item .time {
width: 70%;
height: 100%;
background: #1B9CFC;
float: right;
}
.item-sort .item .time span {
color: white;
text-align: center;
display: block;
line-height: 100px;
}
<div class="full-item">
<div class="button-item">
<button id="Sort-item">Sort by</button>
</div>
<div class="item-sort">
<div class="item">
<div class="pic"></div>
<div class="time"><span>15:20</span></div>
</div>
<div class="item">
<div class="pic"></div>
<div class="time"><span>13:10</span></div>
</div>
<div class="item">
<div class="pic"></div>
<div class="time"><span>18:40</span></div>
</div>
</div>
</div>
Update your html inside "button-item" class
<div class="button-item">
<p>Sort By </p>
<button id="sort-asc" onclick="app.sortAsc()">Asc</button>
<button id="sort-desc" onclick="app.sortDesc()">Desc</button>
<button id="reset" onclick="app.reset()">Reset</button>
</div>
Add to your scripts
var app = (function (){
var originalArr = []
var timeArr = []
var sortedArr = []
var objArr = []
var timeElements = document.querySelectorAll('.time')
var itemSortElement = document.querySelector('.item-sort')
for ( let timeEl of timeElements) {
// retrieving text from individual span element
let timeText = timeEl.children[0].innerText;
// retrieving parent node of div with class "time"
let timeParent = timeEl.parentNode
let obj = { text: timeText, parent: timeParent }
objArr.push(obj)
timeArr.push(timeText)
}
// copying all elements/ texts from "timeArr" array to "originalArr" array
// to keep track of original order of texts
originalArr = timeArr.slice()
function sortAsc () {
// sorting the retrieved texts in ascending order
sortedArr = timeArr.sort();
while (itemSortElement.hasChildNodes()) {
// removing all child elements of class "item-sort"
itemSortElement.removeChild(itemSortElement.firstChild);
}
for ( let i = 0; i < sortedArr.length; i++) {
let filteredObj = objArr.filter((obj) => sortedArr[i] == obj.text)[0]
let node = filteredObj.parent
itemSortElement.appendChild(node)
}
}
function sortDesc () {
sortedArr = timeArr.sort().reverse();
while (itemSortElement.hasChildNodes()) {
itemSortElement.removeChild(itemSortElement.firstChild);
}
for ( let i = 0; i < sortedArr.length; i++) {
var filteredObj = objArr.filter((obj) => sortedArr[i] == obj.text)[0]
let node = filteredObj.parent
itemSortElement.appendChild(node)
}
}
function reset () {
while (itemSortElement.hasChildNodes()) {
itemSortElement.removeChild(itemSortElement.firstChild);
}
for ( let i = 0; i < originalArr.length; i++) {
var filteredObj = objArr.filter((obj) => originalArr[i] == obj.text)[0]
let node = filteredObj.parent
itemSortElement.appendChild(node)
}
}
return {
sortDesc,
sortAsc,
reset
}
})()
you can check it Demo