I'm making a map using leaflet.js.
I made a function where user selects a country and it generates easybuttons with that selection with specific information.
The problem is when I select one country after another it creates more easybuttons and doesn't remove the previously created button.
Please check the image so you can know what the problem is.
function generateList() {
const list = document.querySelector('.dropdown-content');
countryList.sort(function (a, b) {
if (a.properties.country < b.properties.country) {
return -1;
}
if (a.properties.country > b.properties.country) {
return 1;
}
return 0;
});
countryList.forEach((country) => {
const a=document.createElement('a');
const p=document.createElement('p');
//flying to the country on user click on country
a.addEventListener('click', () => {
flyToStore(country);
const city=country.properties.city;
const currency1=country.properties.currency;
const contry=country.properties.country;
L.easyButton('fa-solid fa-cloud fa-lg',function (){
weatherdetails(city);
$('#weathermodal').modal('show');
}).addTo(myMap);
L.easyButton('fa fa-dollar fa-lg',function (){
currencyexchange(currency1);
$('#myModal').modal('show');
}).addTo(myMap);
L.easyButton('fa fa-info-circle fa-lg',function (){
moredetails(contry);
$('#detailsmodal').modal('show');
}).addTo(myMap);
});
a.classList.add('country-item');
countries=country.properties.country;
a.innerText =countries ;
//div.appendChild(p);
list.appendChild(p);
p.appendChild(a);
});
}
I think you need to hold a reference to that button instance. Then call your map removeControl it.
function generateList() {
const list = document.querySelector('.dropdown-content');
countryList.sort(function (a, b) {
if (a.properties.country < b.properties.country) {
return -1;
}
if (a.properties.country > b.properties.country) {
return 1;
}
return 0;
});
lastButton1 = null;
lastButton2 = null;
lastButton3 = null;
countryList.forEach((country) => {
const a = document.createElement('a');
const p = document.createElement('p');
//flying to the country on user click on country
a.addEventListener('click', () => {
if (lastButton1) {
myMap.removeControl(lastButton1);
myMap.removeControl(lastButton2);
myMap.removeControl(lastButton3);
lastButton1 = null
}
flyToStore(country);
const city = country.properties.city;
const currency1 = country.properties.currency;
const contry = country.properties.country;
lastButton1 = L.easyButton('fa-solid fa-cloud fa-lg', function () {
weatherdetails(city);
$('#weathermodal').modal('show');
})
lastButton2 = L.easyButton('fa fa-dollar fa-lg', function () {
currencyexchange(currency1);
$('#myModal').modal('show');
})
lastButton3 = L.easyButton('fa fa-info-circle fa-lg', function () {
moredetails(contry);
$('#detailsmodal').modal('show');
})
lastButton1.addTo(myMap);
lastButton2.addTo(myMap);
lastButton3.addTo(myMap);
});
a.classList.add('country-item');
countries = country.properties.country;
a.innerText = countries;
//div.appendChild(p);
list.appendChild(p);
p.appendChild(a);
});
}
Related
i have an array named todoList, all of my data is in it.
i saved them to localstorage like this:
https://codepen.io/arashkazerouni/pen/YzLxdoQ
const saveToLocal = (array) => {
window.localStorage.setItem("todo", JSON.stringify(array));
};
todoList = JSON.parse(window.localStorage.getItem("todo"));
i used this saveToLocal function after any change in todoList, and it works.
the only problem is when i refresh the page, all items gone.
but if i add new todo, all of them will shown again
and there is page script :
const input = document.querySelector("input");
const button = document.querySelector("button");
const todos = document.querySelector(".todos");
const alertRed = document.querySelector(".alert-red");
let todoList = [];
const saveToLocal = (array) => {
window.localStorage.setItem("todo", JSON.stringify(array));
};
todoList = JSON.parse(window.localStorage.getItem("todo"));
const addToDOM = () => {
// todos.innerHTML = "";
for (let i = 0; i < todoList.length; i++) {
const html = `
<div class="todo" id=${i}>
<p class="todo-text" >${todoList[i]}</p>
<i class="fa-solid fa-check" ></i>
<i class="fa-solid fa-trash"></i>
</div>
`;
todos.insertAdjacentHTML("beforeend", html);
}
};
// Add items to list
button.onclick = (e) => {
e.preventDefault();
// todos.innerHTML = "";
if (!todoList.includes(input.value) && input.value !== "") {
todoList.push(input.value);
saveToLocal(todoList);
}
// console.log(todoList);
addToDOM();
input.value = "";
};
// Handle Enter Press
document.onkeypress = (e) => {
if (e.key === "Enter") {
button.click();
}
};
todos.onclick = (e) => {
e.preventDefault();
const isCheck = e.target.classList.contains("fa-check");
const isTrash = e.target.classList.contains("fa-trash");
if (isCheck) e.target.previousElementSibling.classList.toggle("checked");
if (isTrash) {
const element = e.target.parentElement;
const elementID = parseInt(element.id);
element.classList.add("removed");
todoList = todoList.filter((element) => element !== todoList[elementID]);
saveToLocal(todoList);
setTimeout(() => {
addToDOM();
}, 300);
}
};
I am doing some practice javascript exercise. My project look like 'trello' but much soft and simple.
When i writing some notes to input, javscript adding note dynamically but if i refresh the page/chrome, all things gone or lost.
So i wanna apply localstorage on my project. How can i do it.
My Note project: https://codepen.io/daniel_134/pen/NWwYKyK[My Note project]1
var input = document.querySelector('#text-input');
document.querySelector("#ad-note-btn").addEventListener("click", () => {
if (input.value.length > 1) {
// GET-INPUT-VALUE
var getvalue = input.value;
// CREATE-NEW-NOTE
const newLi = document.createElement("textarea");
newLi.value = getvalue;
newLi.className = "note-li";
// ADD-NEW-NOTE
var ul = document.querySelector('#list-items');
ul.appendChild(newLi);
// EMPTY-INPUT-WHEN-CREATING-NEW-NOTES
input.value = " ";
// DELETE-NOTES
const dleLi = document.createElement("button");
dleLi.textContent = "delete";
dleLi.className = "list-btn";
ul.appendChild(dleLi);
dleLi.addEventListener("click", () => {
newLi.remove();
dleLi.remove();
edLi.remove();
saveLi.remove();
})
// EDIT-NOTES
const edit = () => {
if( newLi.value.length > 0 ) {
newLi.disabled = true;
} else {
newLi.disabled = false;
}
}
edit()
const edLi = document.createElement("button");
edLi.textContent = "Edit";
ul.appendChild(edLi);
edLi.className = "list-btn";
edLi.addEventListener("click", () => {
if ( newLi.disabled = true ) {
newLi.disabled = false;
}else {
newLi.disabled = true;
}
})
const saveLi = document.createElement("button");
saveLi.textContent = "save";
ul.appendChild(saveLi);
saveLi.className = "list-btn";
saveLi.addEventListener("click", () => {
edit();
})
} else {
ul.appendChild();
}
})
document.querySelector("#clear-btn").addEventListener("click", () => {
input.value = " ";
})
2
it'll look like that , for example :
when you load your page .
load todoList var todoList = JSON.parse(localStorage.getItem('todo-list'))
and display it
when you add new element to your to-do list
var todoList = JSON.parse(localStorage.getItem('todo-list'));
var new_todo = [{
title:'for example ...',
complete:false
}];
localStorage.setItem('todo-list',JSON.stringify(new_todo));
}else{
todoList.push({
title:'for example ...',
complete:false
});
localStorage.setItem('todo-list',JSON.stringify(todoList));
}
I am making a list where you can edit or delete items. I am listening for 2 events on the same table. One for edit and one for delete, I am listening on the table and not the actual buttons as they are created dinamycally. Edit and Delete both have the same id, the id of the product, which I am using later for the http requests.
,
Now when I press edit the console.logs from the delete functions fire up,but nothing happens, if I am trying to save the item the http request doesnt work, it will not take the id (but it logs it to the console)
If I press the delete button once nothing happnes, if I press it a second time the page refreshes and the item is deleted.
Is there a way to listen for those events separately or for them to not interfere with one another? All I want is if I press the edit button the respective item's values to go to the input field and when I press Add Item update the product in the JSON file as well, and on delete press, to delete the item from the JSON file and remove from the html document.
Update: Managed to resolve edit function
Here is my code:
import { http } from "./http.js";
import { ui } from "./ui.js";
const productsURL = "https://61363d1a8700c50017ef54c1.mockapi.io/product";
// const addProductBtn = document.querySelector('.new-product-btn');
const adminContainer = document.querySelector('.admin-container');
const addItem = document.querySelector('.admin-add-item-btn');
const imgInput = document.getElementById('image');
const nameInput = document.getElementById('name');
const priceInput = document.getElementById('price');
const stockInput = document.getElementById('stock');
const categoryInput = document.getElementById('category');
const typeInput = document.getElementById('type');
const descriptionInput = document.getElementById('description');
const validSvg = document.querySelectorAll('.valid_input_svg');
// const adminForm = document.getElementById('admin-form');
const adminTable = document.getElementById('admin-tbody');
const editBtn = document.querySelectorAll('.edit-btn');
const adminBtn = document.querySelectorAll('.admin-delete-btn');
const cancel = document.getElementById('cancel');
let productToEdit;
let edit = false;
let id;
document.addEventListener('DOMContentLoaded', listAdminProducts);
// adminForm.addEventListener('submit', validateInput);
addItem.addEventListener('click', addOrEditProducts);
// adminTable.addEventListener('click', editOrDeleteItem);
adminTable.addEventListener('click', deleteProduct);
adminTable.addEventListener('click', editProduct);
cancel.addEventListener('click', cancelEdit);
function listAdminProducts() {
http.get(productsURL).then(products => {
ui.showAllAdminProducts(products);
});
};
function addOrEditProducts() {
if (edit === true && validateInput() === true) {
productToEdit = {
image: imgInput.value,
name: nameInput.value,
price: priceInput.value,
stock: stockInput.value,
category: categoryInput.value,
type: typeInput.value,
description: descriptionInput.value,
};
http
.put(`${productsURL}/${id}`, productToEdit)
.then(() => listAdminProducts());
console.log(`${productsURL}/${id}`)
ui.clearFields();
id = '';
edit = false;
return;
} else if (edit === false && validateInput() === true) {
const product = {
image: imgInput.value,
name: nameInput.value,
price: priceInput.value,
stock: stockInput.value,
category: categoryInput.value,
type: typeInput.value,
description: descriptionInput.value
};
http.post(productsURL, product).then(() => listAdminProducts());
ui.clearFields();
};
};
function editProduct(e) {
console.log('works');
if (e.target.classList.contains('edit-btn')) {
edit = true;
id = e.target.getAttribute('id');
console.log(id);
console.log(e.target)
http.get(`${productsURL}/${id}`).then((data) => {
imgInput.value = data.image;
nameInput.value = data.name;
priceInput.value = data.price;
stockInput.value = data.stock;
categoryInput.value = data.category;
typeInput.value = data.type;
descriptionInput.value = data.description;
});
console.log(`${productsURL}/${id}`)
};
// id = '';
}
function deleteProduct(e) {
console.log(e.target);
if (e.target.className === 'admin-delete-btn') {
console.log(e.target);
id = e.target.getAttribute('id');
console.log(id);
http
.delete(`${productsURL}/${id}`)
.then(() => listAdminProducts())
.catch("Error on delete");
id = '';
}
ui.showSuccessMessage('Product deleted', adminContainer);
}
function cancelEdit() {
ui.clearFields;
imgInput.className = '';
nameInput.className = '';
priceInput.className = '';
stockInput.className = '';
categoryInput.className = '';
edit = false;
}
function validateInput() {
let valid = true;
if (imgInput.value == '') {
if (imgInput.classList.contains('input-invalid')) {
imgInput.classList.remove('input-invalid');
};
ui.showAdminMessage('Must contain a link to an image', 0);
imgInput.classList.add('input-invalid');
valid = false;
} else {
imgInput.classList.add('input-valid');
validSvg[0].style.display = "block";
removeClass(imgInput, 0);
};
if (nameInput.value === '') {
if (nameInput.classList.contains('input-invalid')) {
nameInput.classList.remove('input-invalid');
};
ui.showAdminMessage('Name is requierd', 1);
nameInput.classList.add('input-invalid');
valid = false;
} else {
// stockInput.classList.remove('input-invalid');
nameInput.classList.add('input-valid');
validSvg[1].style.display = "block";
removeClass(nameInput, 1);
};
if (priceInput.value == "" || isNaN(priceInput.value) || priceInput.value < 0) {
if (priceInput.classList.contains('input-invalid')) {
priceInput.classList.remove('input-invalid');
};
ui.showAdminMessage('Price must be a number greater then 0', 2);
priceInput.classList.add('input-invalid');
valid = false;
} else {
// stockInput.classList.remove('input-invalid');
priceInput.classList.add('input-valid');
validSvg[2].style.display = "block";
removeClass(priceInput, 2);
};
if (stockInput.value == "" || isNaN(stockInput.value) || stockInput.value < 0) {
if (stockInput.classList.contains('input-invalid')) {
stockInput.classList.remove('input-invalid');
};
ui.showAdminMessage('Stock must be a number greater then 0', 3);
stockInput.classList.add('input-invalid');
valid = false;
} else {
// stockInput.classList.remove('input-invalid');
stockInput.classList.add('input-valid');
validSvg[3].style.display = "block";
removeClass(stockInput, 3);
};
if (categoryInput.value === 'barware' || categoryInput.value === 'spirits') {
// categoryInput.classList.remove('input-invalid');
categoryInput.classList.add('input-valid');
validSvg[4].style.display = "block";
removeClass(categoryInput, 4);
} else {
ui.showAdminMessage('Category must be barware or spirits', 4);
categoryInput.classList.add('input-invalid');
valid = false;
};
return valid;
};
function removeClass(element, index) {
// console.log(element, index);
setTimeout(() => {
element.className = '';
validSvg[index].style.display = "none";
}, 3000)
}
Finally managed to resolve it, I had to put e.preventDefault() in both functions, so the page will not reload first
I want to change the index of newAr on each click and console log the values of next object in newAr showed in looper function
Note: I only want the index second object values on second click and third object values in newAr on third click
HTML only has a button nothing else
const button = document.querySelector("button");
let firstVar = () => {
const firstVarVariable = Math.round(Math.random() * 10);
if (firstVarVariable < 5) {
return true;
} else {
return false;
}
};
let secondVar = () => {
const firstVarVariable = Math.round(Math.random() * 10);
if (firstVarVariable < 5) {
return true;
} else {
return false;
}
};
let thirdVar = () => {
const firstVarVariable = Math.round(Math.random() * 10);
if (firstVarVariable < 5) {
return true;
} else {
return false;
}
};
const newAr = [];
const pusher = () => {
newAr.push({
one: firstVar(),
two: secondVar(),
three: thirdVar(),
});
console.log(newAr);
looper();
};
const looper = () => {
for (const value of newAr) {
console.log(value.one);
console.log(value.two);
console.log(value.three);
}
// I want to change the index of newAr array on click
// Like i want to console log first object in array on first click
// and second object on other click and third object
// alsp please tell me if i can change some approch
};
button.addEventListener("click", () => {
pusher();
});
let randomBool = () => Math.random() < 0.5;
// all three functions did the same thing...
const newAr = [];
const pusher = () => {
newAr.push({
one: randomBool(),
two: randomBool(),
three: randomBool(),
});
console.log(newAr);
looper();
};
let index = 0; // counter / array index
const looper = () => {
let value = newAr[index++]; // always getting the next element (starting from 0).
console.log(value.one);
console.log(value.two);
console.log(value.three);
};
/***/
const button = document.querySelector("button");
button.addEventListener("click", () => {
pusher();
});
<button>Test</button>
i have a search system on my website it works but i can not click on items i search. its a simple script that creates li elements dephended on my search input but how can i add this elements a custom links? because if you can not click on item you searched that does not make any sense... i want to add this const people elements custom links.code:
const people = [
{name:'გადაარჩინე დედამიწა'},
{name:'ანტიმელა'},
{name:'mr.capsule'},
{name:'capsule battle royale'}
];
const list = document.getElementById('list');
function setlist (group) {
clearlist();
for (const person of group) {
const item = document.createElement("li");
item.classList.add("list-group-item");
const text = document.createTextNode(person.name);
item.appendChild(text);
list.appendChild(item);
}
if (group.length === 0) {
setnoresults();
}
}
function clearlist () {
while (list.firstChild) {
list.removeChild(list.firstChild);
}
}
function getrelevency (value, searchTerm) {
if (value === searchTerm) {
return 2;
}else if (value.startsWith(searchTerm)) {
return 1;
}else if (value.includes(searchTerm)) {
return 0;
}
}
function setnoresults () {
const item = document.createElement('li');
item.classList.add('list-group-item');
const text = document.createTextNode('შედეგები ვერ მოიძებნა... სცადეთ თავიდან');
item.appendChild(text);
list.appendChild(item);
}
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', (event) => {
let value = event.target.value;
if (value && value.trim().length > 0) {
value = value.trim().toLowerCase();
setlist(people.filter(person => {
return person.name.includes(value);
}).sort((personA, personB) => {
return getrelevency(personB.name, value) - getrelevency(personA.name, value);
}));
}else {
clearlist();
}
});
You should add it in setlist function.
function setlist (group) {
clearlist();
for (const person of group) {
const item = document.createElement("li");
item.classList.add("list-group-item");
const link = document.createElement("a");
link.href = "http://..."; // put here where the link should point
item.appendChild(link);
const text = document.createTextNode(person.name);
link.appendChild(text);
list.appendChild(item);
}
if (group.length === 0) {
setnoresults();
}
}
i got solution with this way checking what search input is and if its targeted search it will add a link on custom search. if statemant is doing everything!
function setlist (group) {
clearlist();
for (const person of group) {
const item = document.createElement("li");
item.classList.add("list-group-item");
if (person.name === "გადაარჩინე დედამიწა") {
const link = document.createElement("a");
link.href = "https://google.com"; // put here where the link should point
link.text = "გადაარჩინე დედამიწა"
item.appendChild(link);
}
const text = document.createTextNode(person.name);
item.appendChild(text);
list.appendChild(item);
}
if (group.length === 0) {
setnoresults();
}
}