Hey friends I'm using window.matchMedia("(max-width: 1300px)"); to add some divs to the DOM when the screen width is less than 1300px, Then I need to remove them when the screen width goes back over 1300px. I'm getting an error in my console saying the node I'm trying to remove isn't a child. But it is?? Any Ideas?
line 75
https://jsfiddle.net/hby2rn13/
const ham = document.querySelector('.nav-box');
const menu = document.querySelector('.menu');
const menuClose = document.querySelector('#menu-close');
const leftArrow = document.querySelector('#left');
const rightArrow = document.querySelector('#right');
const img = document.querySelector('.image-slider');
const width = window.matchMedia("(max-width: 1300px)");
let num = 1;
adjustMenuDesign();
window.addEventListener('resize', adjustMenuDesign);
function adjustMenuDesign() {
const tostadas = document.querySelector('.tostadas');
const tostadasRow = document.querySelector('.tostadas-row');
const tortas = document.querySelector('.tortas');
const tortasRow = document.querySelector('.tortas-row');
const columnRight = document.querySelector('.column-right .column');
const menu = document.querySelector('.menu-section');
const columnWrap = document.createElement('div');
const column = document.createElement('div');
const tacos = document.querySelector('.column-right .tacos');
const nodesToRemove = document.getElementsByClassName('remove');
if (width.matches) { // If media query matches
columnRight.removeChild(tortas);
columnRight.removeChild(tostadas);
columnRight.removeChild(tostadasRow);
columnRight.removeChild(tortasRow);
column.appendChild(tostadas);
column.appendChild(tostadasRow);
column.appendChild(tortas);
column.appendChild(tortasRow);
column.classList.add('column');
columnWrap.classList.add('column-new');
columnWrap.appendChild(column);
menu.appendChild(columnWrap);
removeNodes(nodesToRemove);
} else {
putNodesBack(nodesToRemove);
menu.removeChild(columnWrap);
columnRight.appendChild(tortas);
columnRight.appendChild(tostadas);
columnRight.appendChild(tostadasRow);
columnRight.appendChild(tortasRow);
}
function removeNodes(nodes) {
for(let i = nodes.length-1; i >= 0; i--) {
tacos.removeChild(nodes[i]);
}
}
function putNodesBack(nodes) {
for(let i = nodes.length-1; i >= 0; i--) {
tacos.appendChild(nodes[i]);
}
}
}
I m not sure this is what you are trying to accomplish but as I went through your fiddle (as you highlighted line 75) I found that you are trying to remove a div element inside class 'menu-section' the problem here is you have more than one div element inside class 'menu-section' you need to specify which div you want to remove per say give that div some class name or id and select the specific one to remove or you can call an index value like menu.removeChild(columnWarp[0]) you can try this. hope this is what you are expecting.
For more please refer Remove all the child elements of a DOM node in JavaScript
Example
<div class="parent"></div>
<button onClick="create();">add</button>
<button onClick="createFoo();">add Foo element</button>
<button onClick="remove();">remove created div</button>
<button onClick="removeTd();">remove selected div</button>
<script>
function create() {
const columnWrap = document.createElement('div');
columnWrap.innerHTML = 'Empty div no id';
const menu = document.querySelector('.parent');
menu.appendChild(columnWrap);
}
function remove() {
const columnWrap = document.createElement('div');
columnWrap.innerHTML = 'Empty div no id';
const menu = document.querySelector('.parent');
menu.appendChild(columnWrap);
if(confirm("Are you sure??")){
menu.removeChild(columnWrap);
}
}
function createFoo() {
const columnWrap = document.createElement('div');
columnWrap.innerHTML = 'Empty div with id foo';
columnWrap.id ="foo";
const menu = document.querySelector('.parent');
menu.appendChild(columnWrap);
}
function removeTd() {
const menu = document.querySelector('.parent');
const delElement = document.querySelector('#foo');
if(confirm("Are you sure??")){
menu.removeChild(delElement);
}
}
</script>
Happy Coding <3 !
Thanks
Related
function showMovies (dataMovie) {
const main = document.getElementById('main');
main.innerHTML = '';
for (let i = 0; i < dataMovie.length; i++) {
const newMovie = document.createElement('div');
newMovie.innerHTML =
`<div class="movie-img">
<img src="${url_poster + dataMovie[i].poster_path}" alt="${dataMovie[i].title}-poster">
</div>
<div class="movie-info">
<h3>${dataMovie[i].title}</h3>
<div class="genres">
</div>
<p>${dataMovie[i].release_date}</p>
</div>
<div class="movie-overview">
<h3>Synopsis:</h3><br>
<p>${dataMovie[i].overview}</p>
</div>`
main.appendChild(newMovie);
for (let j = 0; j < genresList.length; j++) {
dataMovie[i].genre_ids.forEach(id => {
if (genresList[j].id === id) {
let g = '';
const div = document.querySelector('.genres');
const p = document.createElement('p');
g += genresList[j].name;
p.innerHTML = `<p>- ${g} </p>`
div.appendChild(p);
}
});
}
}
I want to display all genres of one movie.
When i get one movie i've got no problem, when i get more than one, the first takes all the genres and no genres are displayed for the others.
movieData is my data.results of the api (tmdb).
You are selecting the same .genres all the time.
Try this please:
const div = newMovie.querySelector('.genres');
function showMovies(dataMovie) {
const main = document.getElementById('main');
main.innerHTML = '';
for (let i = 0; i < dataMovie.length; i++) {
const newMovie = document.createElement('div');
newMovie.innerHTML =
`<div class="movie-img">
<img src="{url_poster + dataMovie[i].poster_path}" alt="{dataMovie[i].title}-poster">
</div>
<div class="movie-info">
<h3>{dataMovie[i].title}</h3>
<div class="genres">
</div>
<p>{dataMovie[i].release_date}</p>
</div>
<div class="movie-overview">
<h3>Synopsis:</h3><br>
<p>{dataMovie[i].overview}</p>
</div>`
main.appendChild(newMovie);
for (let j = 0; j < genresList.length; j++) {
dataMovie[i].genre_ids.forEach(id => {
if (genresList[j] === id) {
let g = '';
const div = newMovie.querySelector('.genres');
const p = document.createElement('p');
g += genresList[j].name;
p.innerHTML = `<p>- ${g} </p>`
div.appendChild(p);
}
});
}
}
}
var genresList = [1,2,3,4,5,6,7,8]
showMovies([{genre_ids:[1,2,3]},{genre_ids:[4,5,6]}])
<div id="main"></div>
The problem is that when you write const div = document.querySelector('.genres'); you are always selecting the first element on the page that matches the selector.
One idea would be to add an id to the movie container, which you can then use on your query.
For instance something like this:
when you create the container div:
const newMovie = document.createElement('div');
newMovie.classList.add('new-movie');
newMovie.setAttribute('movie-id', dataMovie[i].id);
then on your selector:
const div = document.querySelector(`.new-movie[movie-id="${dataMovie[i].id}"] .genres`);
This would give you the .genres div inside the correct container (instead of the first one on the page).
For a different approach you could also try to use
const div = newMovie.querySelector('.genres');
instead of
const div = document.querySelector('.genres');
Which should give you the same result
<div id="container">
<button id="button">Click!</button>
</div>
JS:
const container = document.querySelector("#container");
const button = document.querySelector("#button");
button.addEventListener("click", () => {
let para = document.createElement("p");
para.textContent = "Text message one. Text message two. Text message three.";
let strText = para.textContent;
let splitText = strText.split(".");
for (let i=0; i<splitText.length;i++) {
splitText.textContent += "<span>" + splitText[i] + "</span>";
}
container.appendChild(splitText[i]);
});
I AM STUCK! How can I write my code such that onclicking the button, the array components of the paragraph is shown(animated) on the div one after another ??
I know about the css animation and transition but I just don't know how to apply it here.
Do you mean something like this?
const container = document.querySelector("#container");
const button = document.querySelector("#button");
let idx = 0;
let sentnce = "Text message one. Text message two. Text message three.";
let texts = sentnce.split(".").slice(0, -1);
button.addEventListener("click", () => {
if (idx < texts.length) {
let p = document.createElement("p");
p.textContent = texts[idx];
container.appendChild(p);
++idx;
}
});
<div id="container">
<button id="button">Click!</button>
</div>
I have a problem with the function below. It's taking the data from JSON and it's creating a menu item. The problem is when there are more than 2 menu items, and I try to increase the quantity of the first item then the value of the second item is increasing.
function ShowTheMenu(theCategoryId) {
var parentEl = document.getElementById("itemlist");
ClearMenu();
for (let i = 0; i < data.length; i++) {
if (data[i].KategorijaBroj == theCategoryId) {
// MAIN PARENT
var itemBox = document.createElement("div");
itemBox.classList.add("itembox");
var itemImage = document.createElement("img");
itemImage.classList.add("itemimage");
itemImage.src = "/menuitemsimages/" + data[i].Image;
var itemContent = document.createElement("div");
itemContent.classList.add("itemcontent");
var itemTitle = document.createElement("h3");
itemTitle.classList.add("itemtitle");
itemTitle.innerHTML = data[i].Title;
var itemPrice = document.createElement("p");
itemPrice.classList.add("itemprice");
itemPrice.innerHTML = "$" + data[i].Price;
var itemQnt = document.createElement("p");
itemQnt.classList.add("quantity");
itemQnt.innerHTML = "Quantity";
var buttonsBox = document.createElement("div");
buttonsBox.classList.add("divcontrolbtns");
var itemQuantity = 0;
var quantityValue = document.createElement("div");
quantityValue.innerHTML = itemQuantity;
var increaseBtn = document.createElement("div");
increaseBtn.classList.add("controlbtns");
increaseBtn.innerHTML = "+";
increaseBtn.addEventListener("click", function () {
if(itemQuantity < 10) {
itemQuantity++;
}
quantityValue.innerHTML = itemQuantity;
})
var decreaseBtn = document.createElement("div");
decreaseBtn.classList.add("controlbtns");
decreaseBtn.innerHTML = "-";
decreaseBtn.addEventListener("click", function () {
if(itemQuantity > 0) {
itemQuantity--;
}
quantityValue.innerHTML = itemQuantity;
})
var itemAddToCart = document.createElement("button");
itemAddToCart.classList.add("btn-add-to-cart");
itemAddToCart.textContent = "Add to cart";
var itemDesc = document.createElement("p");
itemDesc.classList.add("itemdesc");
itemDesc.innerHTML = data[i].Description;
itemBox.appendChild(itemImage);
itemContent.appendChild(itemTitle);
itemContent.appendChild(itemDesc);
itemContent.appendChild(itemPrice);
itemContent.appendChild(itemAddToCart);
itemContent.appendChild(itemQnt);
buttonsBox.appendChild(increaseBtn);
buttonsBox.appendChild(quantityValue);
buttonsBox.appendChild(decreaseBtn);
itemContent.appendChild(buttonsBox);
itemBox.appendChild(itemContent);
parentEl.appendChild(itemBox);
}
}
}
IMAGE
What should I do in order for the chosen menu item value to be changed?
Try to do something like this bellow. I try to use same HTML structure that you use but to be honest, I suggest that you change a little bit ;)
<!DOCTYPE html>
<html>
<head>
<script>
// Qt
var quantity = new Array();
function ShowTheMenu(theCategoryId) {
// Clear menu
// ClearMenu();
// bt+
increaseBtn = (i) => {
// Item target
let item = document.getElementById('item_' + i);
// Qt target
let qtSpan = item.getElementsByClassName('qt');
// Qt
let qt = parseInt(qtSpan[0].innerHTML);
// Fix some errors
if (qt === undefined || !qt) qt = 0;
// Increase
if (qt < 10) qt++;
// Update
qtSpan[0].innerHTML = qt;
};
// bt-
decreaseBtn = (i) => {
// Item target
let item = document.getElementById('item_' + i);
// Qt target
let qtSpan = item.getElementsByClassName('qt');
// Qt
let qt = parseInt(qtSpan[0].innerHTML);
// Fix some errors
if (qt === undefined || !qt) qt = 0;
// Decrease
if (qt > 0) qt--;
// Update
qtSpan[0].innerHTML = qt;
};
//
var data = new Array();
data[0] = {
Image:
'https://s2.glbimg.com/WcYUQNaattnUf7d8U8MUBfk7loU=/620x430/e.glbimg.com/og/ed/f/original/2015/10/30/pizza.jpg',
KategorijaBroj: 1,
Title: 'Delicious Pizza',
Price: 10,
Description: 'Description test',
};
for (let i = 0; i < data.length; i++) {
if (data[i].KategorijaBroj == theCategoryId) {
// Img
let img = data[i].Image; // '/menuitemsimages/' + data[i].Image;
// Title
let title = data[i].Title;
// Price
let price = '$' + data[i].Price;
// Description
let desc = data[i].Description;
// Qtd
let qt = 2;
// Matriz
let newItem = `<div id="item_${i}" class="itembox">
<div class="itemcontent">
<img src="${img}" border=0 width=100/>
<h3 class="itemtitle">${title}</h3>
<p class="itemprice">${price}</p>
<div class="quantity">
<span>Quantity : </span>
<span class="qt">${qt}</span>
</div>
<div class="controlbtns">
<button class="addbtn" onClick="increaseBtn(${i})">+</button>
<button class="removebtn" onClick="decreaseBtn(${i})">-</button>
</div>
<button class="btn-add-to-cart">Add to cart</button>
<p class="description">${desc}</p>
</div>
</div>`;
// Get the menulist itens
let parentEl = document.getElementById('itemlist');
// Add item
parentEl.insertAdjacentHTML('beforeend', newItem);
}
}
}
</script>
</head>
<body>
<div id="itemlist"></div>
<script>
ShowTheMenu(1);
</script>
</body>
</html>
It's because both items are sharing the same variable, in this case, itemQuantity.
Option 1
If they all should have their own counter I would recommend using an object for tracking this.
const itemQuantity = {
'item1': 2,
'item2': 5
}
if you add some unique class or id to the element you can use this in your onclick event to use as a key. (Where I used 'item1' and 'item2')
Option 2
If you create a function that does everything that's inside your for loop and then just call that function it should also work. This works because every function then creates its own scoped variable of itemQuanity.
Go with whatever options feel best for now. How to manage data in your frontend has a lot of different ways and opinions. You'll quickly discover what works best in what scenario.
What Olavo Mello is mentioning in his answer could still make your code better. using string literals for small HTML snippets is often more readable than using document.createElement(). I would recommend fixing your counter issue first and then look if you could improve your code with Olavo Mello's answer in mind. Good luck :)
So I'm creating multiple new child divs inside another parent div with this code:
var parentDiv = document.querySelector('.parent-div')
const newDiv = document.createElement('div');
parentDiv.appendChild(newDiv);
So now I want to add an onlick event for every div I created, that resets the color for every other div inside the parent div, so that no multiple child divs are selected, and then set the color only for the clicked div to another color!
Any ideas?
var parentDiv = document.querySelector('.parent-div');
for (let i = 0; i < 10; ++i) {
const newDiv = document.createElement('div');
newDiv.className = "my-class";
newDiv.innerText = `Foo${i}`;
parentDiv.appendChild(newDiv);
}
parentDiv.onclick = (event) => {
document.querySelectorAll('.my-class').forEach((el) => {
el.className = "my-class";
});
event.target.className += " active";
}
.my-class {
color: red;
}
.active {
color: blue;
}
<div class="parent-div"></div>
let parentDiv = document.querySelector('.parent-div');
for (let x = 0; x < 10; x++) {
let newDiv = document.createElement('div');
newDiv.classList.add('see')
parentDiv.appendChild(newDiv);
}
parentDiv.addEventListener('click', (e) => {
if (e.target.tagName === 'DIV') {
e.target.style.backgroundColor = 'red';
}
})
Just to suggest a more robust and flexible way:
// Utility functions
const EL = (sel, EL) => (EL||document).querySelector(sel);
const ELS = (sel, EL) => (EL||document).querySelectorAll(sel);
const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
// Now...
// Get element (Use an ID, not a class)
const EL_parent = EL('#parent');
// Function to toggle "is-active" class
const toggleActive = (EL_target, EL_parent) => {
const EL_active = EL(".is-active", EL_parent);
if (EL_active) EL_active.classList.remove("is-active");
EL_target.classList.add("is-active");
};
// Function to create new child elements
const newChild = (content) => ELNew("div", {
className: "child",
innerHTML: content,
onclick() {
toggleActive(this, EL_parent);
}
});
// Create a couple of elements....
EL_parent.append(
newChild("1 Lorem"),
newChild("2 Ipsum"),
newChild("3 Dolor"),
);
.is-active {
background: gold;
}
<div id="parent"></div>
So just a better way, and to avoid sloppy code like className = or Event.target without the use of .closest(), as shown in the other answers.
I'm not sure if this is how you would want to do it for many reasons, but it might be beneficial for you to change the HTML value of the parent div. For example,
var parentDiv = document.querySelector('.parent-div')
parentDiv.innerHTML = parentDiv.innerHTML + "<div class='{class name}'></div>";
The approach proposed here is aware of which div was clicked the last time, changes its style accordingly and creates the onclick when the item is created.
var parentDiv = document.querySelector('.parent-div');
let lastDiv = undefined;
for (let i = 0; i < 10; i++) {
let newDiv = document.createElement('div');
newDiv.style.width = "100px";
newDiv.style.height = "100px";
newDiv.style.backgroundColor = "black";
newDiv.style.border = "1px solid white";
newDiv.onclick = function() {
if (lastDiv) lastDiv.style.backgroundColor = "black";
newDiv.style.backgroundColor = "green";
lastDiv = newDiv;
};
parentDiv.appendChild(newDiv);
}
<div class="parent-div"></div>
I have a variable called 'newItem' which essentially is a block of html code that will be appended directly to the dom when activated (this code is for a javascript shopping cart). I have the line of 1 below and am trying to access the textContent of 'amount-items' on the very last div (class='dropDown-price') as indicated by Number(amountItems.textContent) but am left with a null on the console.
What am i doing wrong, why doesnt .textContent gain access to the '1' for the 'amount-items' class?
Thanks for any help i can get
//dropdown menu hidden
const cartDropdown = document.querySelector('.cart-dropDown-items');
//every single + symbol
const addToCartButtons = document.querySelectorAll('.addToCart');
//price of item
const foodPrices = document.querySelectorAll('.selection-row-title');
//name of item
const foodNames = document.querySelectorAll('.selection-row-foodName');
//weight of item
const foodWeights = document.querySelectorAll('.selection-row-weight');
const items = [];
let total = 0;
for (let i=0; i<addToCartButtons.length; i++) {
addToCartButtons[i].addEventListener('click', function() {
const newItem = document.createElement('div');
newItem.className = 'dropDown-item';
let amountItems = document.querySelector('.amount-items');
newItem.innerHTML =
`<div class='dropDown-title dropDown-info'>
${foodNames[i].innerHTML}
</div>
<div class='dropDown-amount dropDown-info'>
<p class='amount-items'>1</p>
</div>
<div class='dropDown-price dropDown-info'>
${Number(foodPrices[i].innerHTML.substring(1)) * Number(amountItems.textContent)}
</div>`;
console.log(newItem)
// if item currently exists in array, just update amount in checkout and increase count++
if (items.includes(addToCartButtons[i].value)) {
items.push(addToCartButtons[i].value);
for (let i=0; i<items.length; i++) {
if (items[i].includes(addToCartButtons[i].value)) {
Number(amountItems.innerHTML) + 1;
}
}
}
// if items does not exist in array, update dom with new item UI and count = 1 by default
else {
items.push(addToCartButtons[i].value);
cartDropdown.appendChild(newItem);
}
console.log(items)
})
}