Delete item at his index in FileList - javascript

I am trying to delete an image from the FileList at his own index , i tried adding an uuid to the image and to the delete button so that have the same uuid , but when i delete for ex the 3rd image , in the front-end it deletes the right images with the div parent , but in back-end it deletes the first image inside FileList
let gellery = document.getElementById("gallery");
let imageUpload = document.getElementById("gallery-photo-add");
let savedValues = document.getElementById("saved-values");
imageUpload.addEventListener("change", function(e) {
let images = imageUpload.files;
let imageValue = 0;
let list = new DataTransfer();
let dt = new DataTransfer();
savedValues.files.forEach(file => {
list.items.add(file);
})
for (let i = 0; i < images.length; i++) {
let image = images[i];
let div = document.createElement("div");
let imgElement = document.createElement("img");
let change = document.getElementById('upload-pics')
let uuid = self.crypto.randomUUID();
imgElement.src = URL.createObjectURL(image);
imgElement.setAttribute('value', imageValue);
imageValue++;
div.setAttribute('style', 'width:300px!important;')
change.setAttribute('style', 'width:300px!important;height: auto!important;display: flex!important;align-items: center;justify-content: center;')
gallery.appendChild(div);
jQuery(div).insertBefore(change);
div.appendChild(imgElement);
let deleteButton = document.createElement("a");
imgElement.setAttribute("uuid", uuid);
deleteButton.setAttribute("uuid", uuid);
deleteButton.setAttribute("class", "remove_field");
Object.defineProperty(image, "uuid", {
value: uuid
});
div.appendChild(deleteButton);
list.items.add(image);
deleteButton.addEventListener("click", function() {
console.log(deleteButton.getAttribute("uuid"), uuid);
if (deleteButton.getAttribute("uuid") === image.uuid) {
dt.items.add(image);
list.items.remove(images);
div.remove();
console.log(list.files);
savedValues.files = dt.files;
console.log(savedValues.files)
}
});
list.files = dt.files;
console.log(list.filest)
}
savedValues.files = list.files;
console.log(savedValues.files)
});
I was trying to delete the image at the respective index from FileList, but it deletes always the first item inside FileList

Related

How do i show an image via input while a certain object is selected ( nft card/image previewer )

How do I use file input to load a picture, store the picture in cookies, or some other to store te picture that doesn't use an alternate language, and only show said picture when a particular object (nft card) is being displayed. The program is basically an image slider that shows information along with a picture pertaining to the current selected nft card.
const prevbtn = document.querySelector("#prev-btn");
const nextbtn = document.querySelector("#next-btn");
let cardName = document.querySelector("#name");
let cardDescription = document.querySelector("#description");
let cardPrice = document.querySelector(".eth");
let cardTime = document.querySelector("#time2");
let cardCreator = document.querySelector("span");
let deck = [];
let card;
let formSubmit = document.querySelector(".formsubmit");
let formName = document.querySelector("#form-name");
let formDescription = document.querySelector("#description2");
let formPrice = document.querySelector("#form-price");
let formTime = document.querySelector("#time-left");
let formCreator = document.querySelector("#creator-name");
let formNFTart = document.querySelector("#nft-art")
let selectedFile;
let picShow = document.getElementById("newimagetoggle");
let picChange = document.querySelector(".nft-card-image")
let newElement = document.createElement("input");
newElement.setAttribute("type", "file");
newElement.setAttribute("accept", "image/*");
//NFT Card Class creator
class NFTcard {
constructor(id, name, description, price, time, creator, image) {
this.id = id
this.name = name
this.description = description
this.price = price
this.time = time
this.creator = creator
this.imageID = image
}
};
// set starting card
let currentCard = 0
// create deck to store nft Card creations
deck = [];
// Create new NFT and change NFT Image from user input
let createNewNFT = function () {
// new image
selectedFile = newElement.files[0]
let reader = new FileReader();
reader.addEventListener("load", function () {
// convert image file to base64 string
picChange.src = reader.result;
}, false);
if (selectedFile) {
reader.readAsDataURL(selectedFile);
}
// retrieve user nft data and place in new nft card object
let newNftName = formName.value
newNftName = new NFTcard(`${deck.length}`, `${formName.value}`, `${formDescription.value}`, `${formPrice.value}eth`, `${formTime.value}`, `${formCreator.value}`, `${deck.length}`);
deck.push(newNftName);
// clear input fields
formName.value = ""
formDescription.value = ""
formPrice.value = ""
formTime.value = ""
formCreator.value = ""
}
picShow.addEventListener('click', function () {
newElement.click();
});
formSubmit.onclick = function () {
createNewNFT();
};
// Switch to current card
let switchCard = function () {
card = deck[currentCard];
cardName.textContent = card.name;
cardDescription.textContent = card.description;
cardPrice.textContent = card.price;
cardTime.textContent = card.time;
cardCreator.textContent = card.creator;
picChange.src = card.imageID
}
// load initial card
window.addEventListener("DOMContentLoaded", function () {
switchCard(currentCard);
});
//Next button switch card
nextbtn.addEventListener('click', function () {
currentCard++;
if (currentCard > deck.length - 1) {
currentCard = 0
};
switchCard(currentCard);
})
//Prev button switch card
prevbtn.addEventListener('click', function () {
currentCard--;
if (currentCard < 0) {
currentCard = deck.length - 1;
}
switchCard(currentCard)
})```

How to detect if XML has a tag and then to add it as innerHTML with JS?

In my XML there are some items that have a description tag, while others do not. I would like to display all the items as blog posts, but the description on them should be shown only if it is included.
When I loop through the items, as soon as it detects an item with no description tag, the code breaks. Thus only the first 3 items are displayed on my website, as they have a description but the 4th item does not.
I have tried the if statement in many ways but can't get it to work. Here's what I am working with:
loadXMLFeed = () => {
const url =
'https://myurl.rss';
fetch(url)
.then((response) => response.text())
.then((data) => {
let parser = new DOMParser();
let xml = parser.parseFromString(data, 'application/xml');
loadContent(xml);
});
};
document.addEventListener('DOMContentLoaded', loadXMLFeed);
function loadContent(x) {
let list = document.getElementById('item');
let item = x.getElementsByTagName('item');
let itemNum = x.getElementsByTagName('item').length;
for (let i = 0; i < itemNum; i++) {
let li = document.createElement('li');
li.className = 'listItem';
li.innerHTML = `
<h3>${item[i].getElementsByTagName('title')[0].innerHTML}</h3>
<p>${item[i].getElementsByTagName('description')[0].innerHTML}</p>
`;
list.appendChild(li);
}
}
Finally managed to fix this, using this code:
function loadContent(x) {
let list = document.getElementById('item');
let item = x.getElementsByTagName('item');
let itemNum = x.getElementsByTagName('item').length;
for (let i = 0; i < itemNum; i++) {
let li = document.createElement('li');
li.className = 'listItem';
let title = (li.innerHTML = `
<h3>${item[i].getElementsByTagName('title')[0].innerHTML}</h3>
`);
if (item[i].getElementsByTagName('description')[0]) {
li.innerHTML =
title +
`<p>${item[i].getElementsByTagName('description')[0].innerHTML}</p>`;
}
list.appendChild(li);
}
}

Javascript - can't iterate over object in incremental search

I'm very new to javascript/dev so I hope there is a an obvious solution that I've not thought of. My code returns search items from TVMaze.com API. The feature giving me trouble is the incremental search (as a user types in input box, the code returns and displays images by creating a new div and appending images, removing and replacing the an div).
My problem is that on deleting all characters from input box, I receive the error: "Uncaught (in promise) TypeError: shows is not iterable" which I suppose means that there is no object to iterate over? Thanks in advance for any help.
const input = document.querySelector("#query");
input.addEventListener("input", async function (e) {
e.preventDefault();
const searchTerm = e.target.value;
const config = { params: { q: searchTerm } };
const res = await axios.get(`http://api.tvmaze.com/search/shows?`, config);
makeImages(res.data);
clearList();
});
const makeImages = (shows) => {
const div = document.createElement("div");
for (let result of shows) {
if (result.show.image) {
const img = document.createElement("IMG");
img.className += "resultImage";
img.src = result.show.image.medium;
const title = document.createElement("h3");
title.className += "resultTitle";
title.innerText = result.show.name;
const year = document.createElement("h4");
year.className += "score";
year.innerText = result.show.premiered;
var sub = year.innerText.substring(0, 4);
var yearNum = parseInt(sub);
div.append(year);
div.append(img);
div.append(title);
document.body.appendChild(div);
}
if (yearNum <= 2000) {
var retro = document.createElement("h5");
retro.className = "retro";
retro.innerText = "retro";
div.append(retro);
}
}
};
let clearList = () => {
var allImg = document.querySelectorAll("IMG");
if (allImg.length === 0) {
document.createElement("div");
return makeImages();
}
var oldDiv = document.querySelector("div");
oldDiv.remove();
console.log(oldDiv);
};

How do I Convert a HTML Collection into an array, without emptying it? #2

I am trying to convert an HTML Collection of "li"s into an array, but the result in the array being emptied.
I read this question and applied that, but it doesn't work.How do I convert a HTMLCollection into an array, without emptying it?
<body>
<ul id="base"></ul>
<script>
const json = [{
"id" : "1",
"date" : "2013/05/05",
},{
"id" : "2",
"date" : "2019/05/05",
}];
for (item of json) {
const list = document.createElement('li');
list.textContent = `${item.date}`;
base.appendChild(list)
}
///the code above works fine.
const base = document.getElementById("base");
const myNodeList = base.getElementsByTagName("li");
console.log(myNodeList);
// gives HTMLCollection
const myArray = Array.from(myNodeList)
// returns empty array
</script>
</body>
the result
I tested the same code on console and it worked fine as below.
The code cannot work before you are using base before initializing it. Placing the initialization before using it makes it work.
Here I modified it: https://jsfiddle.net/tk78z5gq/
Thank you so much guys!
The problem was async.
I should have said that earlier, I fetch the data from NeDB with async function.
The array was empty because DOM was executed before async function fetching data was executed.
The full code below was fixed one. I'm not sure this is best way, but at least it worked.
let dataM = null;
async function getHTMLData() {
const response = await fetch('/api');
const data = await response.json();
dataM = data;
const base = document.getElementById("base");
for (item of data) {
const root = document.createElement('li');
root.className = "col-md-auto";
root.title = `${item.date}`;
const border = document.createElement('div');
border.className = "row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative";
root.appendChild(border);
const flex = document.createElement('div');
flex.className = "col p-4 d-flex flex-column position-static";
border.appendChild(flex);
const country = document.createElement('strong');
country.className = "d-inline-block mb-2 text-primary";
const title = document.createElement('h3');
title.className = "mb-0";
const date = document.createElement('div');
date.className = "mb-1 text-muted";
date.id = "date";
const fieldItem = document.createElement('p');
fieldItem.className = "mb-auto";
const imageRoot = document.createElement('figure');
imageRoot.className = "image mb-2";
const link = document.createElement('a');
link.className = "p-4";
const linkText = document.createTextNode("Source");
country.textContent = `${item.country}`;
title.textContent = `${item.title}`;
date.textContent = `${item.date}`;
fieldItem.textContent = `${(item.fieldItem)}`;
for (var i = 0; i < item.imageSrc.length; i++) {
const image = document.createElement('img');
image.src = item.imageSrc[i];
image.alt = 'seized items'
image.className = "w-5 h-5";
// image.crossOrigin ="use-credentials";
imageRoot.appendChild(image);
}
const imageText = document.createElement('text');
imageText.innerHTML = `<br>${item.imageText}`;
imageRoot.appendChild(imageText);
link.appendChild(linkText);
link.title = "Source";
link.href = item.URL;
link.className = "";
flex.append(country, title, date, fieldItem, imageRoot, link);
base.appendChild(root);
}
}
sortDate();
async function sortDate() {
const gethtml = await getHTMLData();
const base = await document.getElementById("base");
const myNodeList = await base.getElementsByTagName("li");
const myArray = Array.from(myNodeList);
myArray.sort(function (a, b) {
return new Date(a.title) > new Date(b.title)? -1
: new Date(a.title) < new Date(b.title)? 1
: 0;
})
for (i = 0; i < myArray.length; i++) {
base.appendChild(base.removeChild(myArray[i]))}
}
index.js
app.get('/api', (request, response) => {
database.find({}).exec(function(err, data){
if (err) {
response.end();
return;
}
response.json(data);
})
});

Add style color to an appended li - Javascript

When adding a new item to the list i would like it to change color based on the input value.
How do i add the input.value to my new appended li item?
I have created a codepen if anyone would be able to help
http://codepen.io/o-sewell/pen/mOBjvQ
// DIV TOGGLE
const toggleButton = document.querySelector('#toggleList');
const listDiv = document.querySelector('.list');
// User INPUT
const userInput = document.querySelector('.userInput');
const button = document.querySelector('button.description');
const p = document.querySelector('p.description');
let listItem = document.querySelectorAll('li');
// ADD ITEM
const addItemInput = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('button.addItemButton');
button.addEventListener('click', () => {
for (let i = 0; i < listItem.length; i++) {
listItem[i].style.color = userInput.value;
}
p.innerHTML = userInput.value + ':';
});
toggleButton.addEventListener('click', () => {
if (listDiv.style.display == 'none') {
listDiv.style.display = 'block';
toggleButton.textContent = 'Hide list';
} else {
listDiv.style.display = 'none';
toggleButton.textContent = 'Show list';
}
});
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
console.log(appendedItem);
for (let i = 0; i < appendedItem.length; i++) {
appendedItem[i].style.color = userInput.value;
}
console.log(appended item);
addItemInput.value = '';
});
Here is the new one :
//DIV TOGGLE
const toggleButton = document.querySelector('#toggleList');
const listDiv = document.querySelector('.list');
var lastPickedColor = "black"; // it will store the last picked color
//User INPUT
const userInput = document.querySelector('.userInput');
const button = document.querySelector('button.description');
const p = document.querySelector('p.description');
let listItem = document.querySelectorAll('li');
//ADD ITEM
const addItemInput = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('button.addItemButton');
button.addEventListener('click', () => {
lastPickedColor = userInput.value;
for(let i = 0; i < listItem.length; i++) {
listItem[i].style.color = lastPickedColor;
}
p.innerHTML = userInput.value + ':';
});
toggleButton.addEventListener('click', () => {
if (listDiv.style.display == 'none') {
listDiv.style.display = 'block';
toggleButton.textContent = 'Hide list';
} else {
listDiv.style.display = 'none';
toggleButton.textContent = 'Show list';
}
});
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.style.color = lastPickedColor; // so it will add li with last picked color
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
console.log(appendedItem);
for(let i = 0; i < appendedItem.length; i++) {
appendedItem[i].style.color = userInput.value;
}
console.log(appendeditem);
addItemInput.value = '';
});
I added lastPickedColor variable to top of the page whenever you change the color, it will store the lastPickedColor and all list add with this color.
The answer is quite simple.
You're defining the initial list when the js is executed, but the new element is created dynamically. Therefore, you'll have to create a new nodelist based on all elements, including the new one. You can simply redefine it inside the current click event:
button.addEventListener('click', () => {
listItem = document.querySelectorAll('li');
for(let i = 0; i < listItem.length; i++) {
listItem[i].style.color = userInput.value;
}
p.innerHTML = userInput.value + ':';
});
To give it the same color as the existing ones, change this function to apply the styling directly on the latest added element:
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
appendedItem.style.color = userInput.value;
addItemInput.value = '';
});
Working codepen example
so I have made 2 changes for your code to work. Please see
http://codepen.io/amoolya/pen/GNMXqa?editors=1111
First change
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
appendedItem.style.color = list.firstElementChild.style.color; //The newly appended item is given the color of the first list element. In your case, this would be whatever color the user chose last.
});
Second Change:
I added
document.querySelectorAll('li');
inside your event handler for the color change button so that each time, the length of the new list is calculated.

Categories