Javascript: Editing a list item - javascript

I have made a to do list using vanilla JS , each list item has a delete and an edit option , delete works fine, but when I am editing a list item it is not editing the line item on which i use the edit option rather it updates the last added list item
HTML:
<div id="wrapper">
<div id="inputWrapper">
<input type="text" name="" id="listDetail"
placeholder="What's the task about" autofocus>
<button id="addBtn">Add</button>
</div>
<ul id="ul"></ul>
JS:
var listDetail = document.getElementById("listDetail");
var addBtn = document.getElementById("addBtn");
var ul = document.getElementById("ul");
addBtn.onclick = function () {
if (listDetail.value !== "") {
var li = document.createElement("LI");
ul.appendChild(li);
}
else {
alert("List item cannot be empty");
}
var entry = document.createElement("SPAN");
var entryText = document.createTextNode(listDetail.value);
entry.className = "userEntry";
entry.appendChild(entryText);
li.appendChild(entry);
var span = document.createElement("SPAN");
var spanText = document.createTextNode("\u00D7");
span.className = "close";
span.appendChild(spanText);
li.appendChild(span);
var close = document.getElementsByClassName("close");
for (var i = 0; i < close.length; i++) {
close[i].onclick = function () {
this.parentElement.style.display = "none";
}
}
var edit = document.createElement("SPAN");
var eText = document.createTextNode("\u270E");
edit.className = "edit";
edit.appendChild(eText);
li.appendChild(edit);
var editC = document.getElementsByClassName("edit");
for (var e = 0; e < editC.length; e++) {
editC[e].onclick = function () {
var p = prompt("Edit your entry");
entry.innerText = p;
}
}
var liTag = document.getElementsByTagName("LI");
for (var j = 0; j < liTag.length; j++) {
liTag[j].onclick = function () {
this.classList.toggle("checked");
}
}
listDetail.value = "";
}
How do I ensure it updates the right line item?

Here lies your problem:
var entry = document.createElement("SPAN"); // <<<
...
for (var e = 0; e < editC.length; e++) {
editC[e].onclick = function () {
var p = prompt("Edit your entry");
entry.innerText = p; // <<< you are modifying the entry that you've just created
}
}
I don't see a need for a for loop.
var listDetail = document.getElementById("listDetail");
var addBtn = document.getElementById("addBtn");
var ul = document.getElementById("ul");
addBtn.onclick = function () {
if (listDetail.value !== "") {
var li = document.createElement("LI");
ul.appendChild(li);
}
else {
alert("List item cannot be empty");
}
var entry = document.createElement("SPAN");
var entryText = document.createTextNode(listDetail.value);
entry.className = "userEntry";
entry.appendChild(entryText);
li.appendChild(entry);
var close = document.createElement("SPAN");
var cText = document.createTextNode("\u00D7");
close.className = "close";
close.appendChild(cText);
li.appendChild(close);
close.onclick = function () {
this.parentElement.style.display = "none";
}
var edit = document.createElement("SPAN");
var eText = document.createTextNode("\u270E");
edit.className = "edit";
edit.appendChild(eText);
li.appendChild(edit);
edit.onclick = function () {
var p = prompt("Edit your entry");
var entry = this.parentElement.getElementsByClassName("userEntry")[0]; // get sibling userEntry element
entry.innerText = p;
}
li.onclick = function () {
this.classList.toggle("checked");
}
listDetail.value = "";
}
<body>
<div id="wrapper">
<div id="inputWrapper">
<input type="text" name="" id="listDetail" placeholder="What's the task about" autofocus>
<button id="addBtn">Add</button>
</div>
<ul id="ul"></ul>

You have to create an ID for each specific tag, and when the user edits it uses that rather than the class.
var listDetail = document.getElementById("listDetail");
var addBtn = document.getElementById("addBtn");
var ul = document.getElementById("ul");
var cnt = 0
addBtn.onclick = function() {
if (listDetail.value !== "") {
var li = document.createElement("LI");
ul.appendChild(li);
} else {
alert("List item cannot be empty");
}
var entry = document.createElement("SPAN");
var entryText = document.createTextNode(listDetail.value);
entry.className = "userEntry";
entry.setAttribute("id", "entry" + cnt);
entry.appendChild(entryText);
li.appendChild(entry);
var span = document.createElement("SPAN");
var spanText = document.createTextNode("\u00D7");
span.className = "close";
span.appendChild(spanText);
li.appendChild(span);
var close = document.getElementsByClassName("close");
for (var i = 0; i < close.length; i++) {
close[i].onclick = function() {
this.parentElement.style.display = "none";
}
}
var edit = document.createElement("SPAN");
var eText = document.createTextNode("\u270E");
edit.className = "edit";
edit.setAttribute("id", "edit" + cnt);
edit.appendChild(eText);
li.appendChild(edit);
var editC = document.getElementById("edit" + cnt);
editC.onclick = function() {
var p = prompt("Edit your entry");
var obj = document.getElementById("entry" + cnt);
obj.innerText = p;
}
var liTag = document.getElementsByTagName("LI");
for (var j = 0; j < liTag.length; j++) {
liTag[j].onclick = function() {
this.classList.toggle("checked");
}
}
listDetail.value = "";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vquery/5.0.1/v.min.js"></script>
<div id="wrapper">
<div id="inputWrapper">
<input type="text" name="" id="listDetail" placeholder="What's the task about" autofocus>
<button id="addBtn">Add</button>
</div>
<ul id="ul"></ul>

Related

I want to remove item(s) from local storage

I am trying to remove items from my local storage. I m pretty new at this, and I m confused about what to do. Tried different things but nothing worked.
So this is my HTML:
Inside ul, I am creating a ToDo list.
My JS file creates elements inside UL. After each input, the item is saved to local storage.
I have two problems: My items are not adding up to my To-DO list, and can not delete items from local storage after I press the delete button on the span.
<div id="myDiv" class="header">
<h2>My To Do List</h2>
<input type="text" name="text" id="myInput" placeholder="Title...">
<span onclick="newElement()" class="addBtn">Add</span>
</div>
<ul id="myUl"></ul>
<script>
var myNodelist = document.getElementsByTagName("Li");
var i;
for (i = 0; i < myNodelist.length; i++) {
var span = document.createElement("SPAN");
var txt = document.createTextNode("\u00D7");
span.className = "close";
span.addEventListener("click", removeFromLocalStorage);
span.appendChild(txt);
myNodelist[i].appendChild(span);
console.log(span);
}
var close = document.getElementsByClassName("close");
var i;
for (i = 0; i < close.length; i++) {
close[i].onclick = function () {
var div = this.parentElement;
div.style.display = "none";
};
}
var list = document.querySelector("ul");
list.addEventListener(
"click",
function (ev) {
if (ev.target.tagName === "LI") {
ev.target.classList.toggle("checked");
}
},
false
);
function newElement() {
var li = document.createElement("li");
var inputValue = document.getElementById("myInput").value;
var t = document.createTextNode(inputValue);
li.appendChild(t);
if (inputValue === "") {
alert("You must write something");
} else document.getElementById("myUl").appendChild(li);
inputValue.value = "";
saveToLocalStorage();
var span = document.createElement("span");
span.classList = "close";
var text = document.createTextNode("\u00D7");
span.appendChild(text);
li.appendChild(span);
for (i = 0; i < close.length; i++) {
close[i].onclick = function () {
var div = this.parentElement;
div.style.display = "none";
removeItem();
};
}
}
function saveToLocalStorage() {
var inputValue = document.getElementById("myInput").value;
window.localStorage.setItem("myInput", JSON.stringify(inputValue));
}
Not sure even what I suppose to do. If any explanation about my code would be appreciated.

svg map open box when click but can not close it

cant close the box
the code im using
https://codepen.io/dudleystorey/pen/vNoeyW
var canadamap = document.getElementById("canada-map"),
provinceInfo = document.getElementById("provinceInfo"),
allProvinces = canadamap.querySelectorAll("g");
canadamap.addEventListener("click", function(e){
var province = e.target.parentNode;
if(e.target.nodeName == "path") {
for (var i=0; i < allProvinces.length; i++) {
allProvinces[i].classList.remove("active");
}
province.classList.add("active");
var provinceName = province.querySelector("title").innerHTML,
provincePara = province.querySelector("desc p");
sourceImg = province.querySelector("img"),
imgPath = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/";
provinceInfo.innerHTML = "";
provinceInfo.insertAdjacentHTML("afterbegin", "<img src="+imgPath + sourceImg.getAttribute('xlink:href')+" alt='"+sourceImg.getAttribute('alt')+"'><h1>"+provinceName+"</h1><p>"+provincePara.innerHTML+"</p>");
provinceInfo.classList.add("show");
}
})
you can set else to your code, to hide the info when click outside the map
var canadamap = document.getElementById("canada-map"),
provinceInfo = document.getElementById("provinceInfo"),
allProvinces = canadamap.querySelectorAll("g");
canadamap.addEventListener("click", function(e){
var province = e.target.parentNode;
for (var i=0; i < allProvinces.length; i++) {
allProvinces[i].classList.remove("active");
}
if(e.target.nodeName == "path") {
province.classList.add("active");
var provinceName = province.querySelector("title").innerHTML,
provincePara = province.querySelector("desc p");
sourceImg = province.querySelector("img"),
imgPath = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/";
provinceInfo.innerHTML = "";
provinceInfo.insertAdjacentHTML("afterbegin", "<img src="+imgPath + sourceImg.getAttribute('xlink:href')+" alt='"+sourceImg.getAttribute('alt')+"'><h1>"+provinceName+"</h1><p>"+provincePara.innerHTML+"</p>");
provinceInfo.classList.add("show");
} else {
provinceInfo.classList.remove("show");
provinceInfo.innerHTML = "";
}
})

create `select` element using javascript

I have an html table that I am creating dynamically its populating everything Accept select element I tried all the methods but its not working please have a look.
My complete code for table:-
function getreferData(dataArray) {
let selectArray = ["Intvw Scheduled", "Selected", "Rejected", "On Hold"];
var ray = dataArray.splice(0, 1)
let table = document.getElementById('thead1');
var tableHeaderRow = document.createElement("tr");
table.appendChild(tableHeaderRow);
for (i = 0; i < ray[0].length; i++) {
var tableHeader = document.createElement("th");
tableHeaderRow.appendChild(tableHeader);
tableHeader.innerHTML = ray[0][i];
}
let tbody = document.getElementById('perf');
for (var i = 0; i < dataArray.length; i++) {
let row = document.createElement("tr")
for (var j = 0; j < dataArray[i].length; j++) {
if (j == 4) {
let col = document.createElement("td")
var a = document.createElement("a");
a.setAttribute("class", "light-blue-text text-light-blue")
a.href = dataArray[i][j];
var node = document.createTextNode("Click here")
a.appendChild(node)
col.appendChild(a)
row.appendChild(col)
} else if (j == 6) {
var col = document.createElement("td");
col.appendChild(createDropdown("status-" + dataArray[i]));
var lbl = document.createElement("label");
lbl.setAttribute("for", "status-" + dataArray[i]);
col.appendChild(lbl)
row.appendChild(col)
} else if (j == 7) {
let col = document.createElement("td")
var a2 = document.createElement("a");
a2.setAttribute("class", "btn blue-grey darken-3 waves-effect waves-light");
a2.setAttribute("onclick", "editrefrecord(\"" + dataArray[i] + "\")");
a2.setAttribute("style", "color: white");
var node2 = document.createTextNode("UPDATE");
a2.appendChild(node2);
col.appendChild(a2);
row.appendChild(col)
} else {
let col = document.createElement("td")
col.innerText = dataArray[i][j]
row.appendChild(col)
}
}
tbody.appendChild(row);
}
function createDropdown(id) {
//create a radio button
var fragment = document.createDocumentFragment();
var select = document.createElement('select');
select.setAttribute("id", id);
selectArray.forEach(function (r) {
select.options.add(new Option(r, r));
});
fragment.appendChild(select);
return fragment;
}
}
The only thing you would like to focus is:-
let selectArray = ["Intvw Scheduled", "Selected", "Rejected", "On Hold"];
else if (j == 6) {
var col = document.createElement("td");
col.appendChild(createDropdown("status-" + dataArray[i]));
var lbl = document.createElement("label");
lbl.setAttribute("for", "status-" + dataArray[i]);
col.appendChild(lbl)
row.appendChild(col)
}
and the function to create select element :-
function createDropdown(id) {
//create a radio button
var fragment = document.createDocumentFragment();
var select = document.createElement('select');
select.setAttribute("id", id);
selectArray.forEach(function (r) {
select.options.add(new Option(r, r));
});
fragment.appendChild(select);
return fragment;
}
Currently My Html table looks like this and If you will see Status is not populating select option:-
The Inspect Element shows its created but its invisible:-
You Missed adding options
let selectArray = ["Intvw Scheduled", "Selected", "Rejected", "On Hold"];
var selectList = document.createElement("select");
selectList.id = "mySelect";
myParent.appendChild(selectList);
//Create and append the options
for (var i = 0; i < selectArray.length; i++) {
var option = document.createElement("option");
option.value = selectArray[i];
option.text = selectArray[i];
selectList.appendChild(option);
}

Passing argument to function doesn't get recognized by function

I built a list using javascript and add an eventlistener to each li element like this
for (var i = (page - 1) * records_per_page; i < (page * records_per_page); i++) {
var li = document.createElement('li');
li.id= "lijst";
li.className="lijst";
var p = document.createElement('p');
p.className = "name"
p.id = "Naam"
p.innerHTML = obj.Name[i];
li.appendChild(p);
var p = document.createElement('p');
p.className = "adres";
p.id = "Adres"
p.innerHTML = obj.Adres[i];
li.appendChild(p);
var p = document.createElement('p');
p.className = "gsm";
p.id = "GSM"
p.innerHTML = obj.GSM[i];
li.appendChild(p);
myUL.appendChild(li);
}
const element = document.querySelectorAll(".lijst");
element.forEach(function(el){
el.addEventListener('click',function(){
fillDiv(el);
})
});
When I call my function it doesn't recognize the argument I pass to the function.
function fillDiv(el){
FicheNaam = document.getElementById("FicheNaam");
FicheGSM = document.getElementById("FicheGSM");
FicheAdres = document.getElementById("FicheAdres");
FicheNaam.innerHTML = el.querySelector('.naam').textContent;
FicheGSM.innerHTML = el.querySelector('.gsm').textContent;
FicheAdres.innerHTML = el.querySelector('.adres').textContent;
}
function fillDiv(el){
FicheNaam = document.getElementById("FicheNaam");
FicheGSM = document.getElementById("FicheGSM");
FicheAdres = document.getElementById("FicheAdres");
FicheNaam.innerHTML = el.querySelector('.naam').textContent;
FicheGSM.innerHTML = el.querySelector('.gsm').textContent;
FicheAdres.innerHTML = el.querySelector('.adres').textContent;
}
var current_page = 1;
var records_per_page = 2;
var obj = {
Name: ["John","Peter","Ben","Jonathan"],
GSM: ["123","456","789","444"],
Adres: ["Adress1","Adress2","Adress3","Adress4"],
};
function changePage(page){
var btn_next = document.getElementById("btn_next");
var btn_prev = document.getElementById("btn_prev");
var listing_table = document.getElementById("myUL");
var page_span = document.getElementById("page");
if (page < 1) page = 1;
if (page > numPages(obj)) page = numPages(obj);
listing_table.innerHTML = "";
for (var i = (page - 1) * records_per_page; i < (page * records_per_page); i++) {
var li = document.createElement('li');
li.id= "lijst";
li.className="lijst";
var p = document.createElement('p');
p.className = "name"
p.id = "Naam"
p.innerHTML = obj.Name[i];
li.appendChild(p);
var p = document.createElement('p');
p.className = "adres";
p.id = "Adres"
p.innerHTML = obj.Adres[i];
li.appendChild(p);
var p = document.createElement('p');
p.className = "gsm";
p.id = "GSM"
p.innerHTML = obj.GSM[i];
li.appendChild(p);
myUL.appendChild(li);
}
const element = document.querySelectorAll(".lijst");
element.forEach(function(el){
el.addEventListener('click',function(){
fillDiv(el);
})
});
page_span.innerHTML = page +"/"+numPages(obj);
}
function prevPage(){
if (current_page > 1) {
current_page--;
changePage(current_page);
}
}
function nextPage()
{
if (current_page < numPages(obj)) {
current_page++;
changePage(current_page);
}
}
function numPages(obj)
{
return Math.ceil(obj.Name.length / records_per_page);
}
window.onload = function() {
changePage(1);
};
#filldiv{
background-color:grey;
float:right;
}
<div id="filldiv">
<p id="FicheNaam">Name</p>
<p id="FicheGSM">GSM</p>
<p id="FicheAdres">Address</p>
</div>
<a onclick="prevPage()" class="previous" id="btn_prev" aria-label="Previous">
<span aria-hidden="true">«</span></a>
<a class="next" onclick="nextPage()" id="btn_next" aria-label="Next">
<span id="page"></span>
<span aria-hidden="true">»</span> </a>
<ul id="myUL">
</ul>
Included a jsfiddle https://jsfiddle.net/h3o2Lbe8/ and snippet of my code.
I need to fill the div on the right with the information within each li.
Heres the fix:
function fillDiv(el) {
FicheNaam = document.getElementById("FicheNaam");
FicheGSM = document.getElementById("FicheGSM");
FicheAdres = document.getElementById("FicheAdres");
FicheNaam.innerHTML = el.querySelector('.name').textContent;
FicheGSM.innerHTML = el.querySelector('.gsm').textContent;
FicheAdres.innerHTML = el.querySelector('.adres').textContent;
}
Explanation:
The code is fine except for a naming issue.
In the function changePage() you used the classname 'name'
And in the fillDiv function you tried to use classname 'naam' in the query selector
FicheNaam.innerHTML = el.querySelector('.naam').textContent;
An exception occured in the funciton because el.querySelector('.naam') returns undefined and you tried to access .textContent property.
Exception in console
Screenshot of your code working

onmouseover show only one submenu ( Javascript )

Good day,
trying to make a small menu only with Javascript and got a problem that onmouseover event shows all submenus and not only one.
this is the part of the code that suppose to change style.display to block.
var ul = document.getElementById("navMainId"),
var liDropdown = ul.getElementsByClassName("dropdown");
for (var i = 0; i < liDropdown.length; i++) {
liDropdown[i].style.display = "inline-block";
liDropdown[i].onmouseover = function () {
var ul = document.getElementById("navMainId"),
dropdown = ul.getElementsByClassName("dropdown-content");
for (var i = 0; i < dropdown.length; i++) {
dropdown[i].style.display = "block";
}
}
liDropdown[i].onmouseleave = function () {
var ul = document.getElementById("navMainId"),
dropdown = ul.getElementsByClassName("dropdown-content");
for (var i = 0; i < dropdown.length; i++) {
dropdown[i].style.display = "none";
}
}
}
How can i change the code to make it work ?
here is whole code on Fiddle ( ssry it is a mess ) : https://jsfiddle.net/apvsnzt5/1/
I've updated the fiddle:
https://jsfiddle.net/apvsnzt5/3/
All you needed to do was change
dropdown = ul.getElementsByClassName("dropdown-content");
to
dropdown = this.getElementsByClassName("dropdown-content");
So that it targets the "this" (being the LI you are hovered over) rather than finding the "dropdown-content" inside the UL.
Also do it on the onmouseleave.
Seems you have incorrect reference to container when mouser over. You need concrete content based on your mosue position.
var dropdown = this.getElementsByClassName("dropdown-content");
try updated fiddle
add the following to your css part
.dropdown-content{
display:none ! important;
}
a:hover+.dropdown-content{
display:block ! important;
}
it will works fine.
var menuCont = document.createElement("div");
document.body.appendChild(menuCont);
var ulMain = document.createElement("ul");
menuCont.appendChild(ulMain);
ulMain.className = "navMain";
ulMain.id = "navMainId";
/****** MENU ******/
// Software
var liSoftware = document.createElement("li");
liSoftware.className = "menu dropdown";
ulMain.appendChild(liSoftware);
var aSoftware = document.createElement("a");
aSoftware.className = "menuName dropbtn";
aSoftware.href = "#";
aSoftware.textContent = "Test1";
liSoftware.appendChild(aSoftware);
// GeCoSoft
var liGeco = document.createElement("li");
liGeco.className = "menu dropdown";
ulMain.appendChild(liGeco);
var aGeco = document.createElement("a");
aGeco.className = "menuName dropbtn";
aGeco.href = "#";
aGeco.textContent = "Test2";
liGeco.appendChild(aGeco);
/******* Submenu *******/
// Software Sub
var divSubSoft = document.createElement("div");
divSubSoft.className = "dropdown-content";
liSoftware.appendChild(divSubSoft);
var aSub1 = document.createElement("a"),
aSub2 = document.createElement("a");
aSub1.className = "menuSubName";
aSub1.textContent = "SubMenu1";
aSub1.href = "#";
aSub2.className = "menuSubName";
aSub2.textContent = "SubMenu2";
aSub2.href = "#";
divSubSoft.appendChild(aSub1);
divSubSoft.appendChild(aSub2);
// Gecosoft Sub
var divSubGeco = document.createElement("div");
divSubGeco.className = "dropdown-content";
liGeco.appendChild(divSubGeco);
var aSub3 = document.createElement("a"),
aSub4 = document.createElement("a");
aSub3.className = "menuSubName";
aSub3.textContent = "Submenu3";
aSub3.href = "#";
aSub4.className = "menuSubName";
aSub4.textContent = "SubMenu4"
aSub4.href = "#";
divSubGeco.appendChild(aSub3);
divSubGeco.appendChild(aSub4);
/****** MENU STYLE ******/
var i = "";
ulMain.style.listStyleType = "none";
ulMain.style.margin = "0px";
ulMain.style.padding = "0px";
ulMain.style.overflow = "hidden";
ulMain.style.backgroundColor = "rgb(232, 225, 225)";
var ul = document.getElementById("navMainId"),
li = ul.getElementsByTagName("li");
for (var i = 0; i < li.length; i++) {
li[i].style.cssFloat = "left";
}
var a = ul.getElementsByTagName("a");
for (var i = 0; i < a.length; i++) {
a[i].style.display = "inline-block";
a[i].style.color = "black";
a[i].style.textAlign = "center";
a[i].style.padding = "14px 16px";
a[i].style.textDecoration = "none";
a[i].onmouseover = function () {
this.style.backgroundColor = "rgb(174, 170, 170)";
}
a[i].onmouseleave = function () {
this.style.backgroundColor = "rgb(232, 225, 225)";
}
}
/************ Dont know what to do here **************/
var liDropdown = ul.getElementsByClassName("dropdown");
for (var i = 0; i < liDropdown.length; i++) {
liDropdown[i].style.display = "inline-block";
liDropdown[i].onmouseover = function () {
var ul = document.getElementById("navMainId"),
dropdown = ul.getElementsByClassName("dropdown-content");
for (var i = 0; i < dropdown.length; i++) {
dropdown[i].style.display = "block";
}
}
liDropdown[i].onmouseleave = function () {
var ul = document.getElementById("navMainId"),
dropdown = ul.getElementsByClassName("dropdown-content");
for (var i = 0; i < dropdown.length; i++) {
dropdown[i].style.display = "none";
}
}
}
var divDropCont = ul.getElementsByClassName("dropdown-content");
for (var i = 0; i < divDropCont.length; i++) {
divDropCont[i].style.display = "none";
divDropCont[i].style.position = "absolute";
divDropCont[i].style.backgroundColor = "#f9f9f9";
divDropCont[i].style.minWidth = "160px";
divDropCont[i].style.boxShadow = "0px 8px 16px 0px rgba(0,0,0,0.2)";
}
var aDropCont = ul.getElementsByClassName("menuSubName");
for (var i = 0; i < aDropCont.length; i++) {
aDropCont[i].style.color = "black";
aDropCont[i].style.padding = "12px 16px";
aDropCont[i].style.textDecoration = "none";
aDropCont[i].style.display = "block";
aDropCont[i].style.textAlign = "left";
aDropCont[i].onmouseover = function () {
this.style.backgroundColor = "rgb(174, 170, 170)";
}
aDropCont[i].onmouseleave = function () {
this.style.backgroundColor = "rgb(249, 249, 249)";
}
}
.dropdown-content{
display:none ! important;
}
a:hover+.dropdown-content{
display:block ! important;
}

Categories