I want to display genres of a movie - javascript

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

Related

container.appendChild is not a function

var refreshBtn = document.getElementsByClassName("refresh-button");
var container = document.getElementsByClassName("container");
const maxpalate = 32;
function RefreshFunction() {
for (let i = 0; i < maxpalate; i++) {
let randomhex = Math.floor(Math.random() * 0xffffffff).toString(16);
randomhex = `#${randomhex.padStart(6, "0")}`;
const color = document.createElement("li");
color.classList.add = "color";
color.innerHTML = `<div class="rect-box" style="background: ${randomhex}"></div>
<span class="hex-value">${randomhex}</span>`;
container.appendChild(color);
}
}
I am not getting the solution,please tell me the Solution of this
getElementsByClassName returns multiple elements. You need to use container[0] instead of container.
Call appendChild method instead of appandChild.
First of all, it is not appandChild it is appendChild.
Second "getElementsByClassName" returns an array but the "container" is a single element so you need to use a single element instead.
var container = document.getElementsByClassName("container");
const maxpalate = 2;
function RefreshFunction() {
debugger
for (let i = 0; i < maxpalate; i++) {
let randomhex = Math.floor(Math.random() * 0xffffffff).toString(16);
randomhex = `#${randomhex.padStart(6, "0")}`;
const color = document.createElement("li");
color.classList.add = "color";
color.innerHTML = `<div class="rect-box" style="background: ${randomhex}"></div>
<span class="hex-value">${randomhex}</span>`;
container[0].appendChild(color);
}
}
RefreshFunction()

Splitting a paragraph into an array and animating each contents of the array on button click

<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>

How can I display list of items from a text file?

I am creating a website that scrapes data from different websites and display them on my website by rendering the text file data.
I know how to do it in React (see my code below), but I want to do it in HTML using simple javascript. Please suggest me what I should do?
renderComments({comments}){
if(comments != null){
const commentList=comments.map((comment)=>{
return(
<li key={comment.id}>
<p> {comment.detail}</p>
<p>--{comment.author}</p>
</li>
);
});
return(
<div className="col-12 col-md-5 m-1">
<h4>Comments</h4>
<ul className='list-unstyled'>
{commentList}
</ul>
</div>
);
}
}
You can use document.createElement(tagName[, options]);
for (var i = 0; i < comments.length; i++) {
var comments = comments[i];
var ul = document.getElementsByClassName("list-unstyled")[0];
var li = document.createElement('li');
li.appendChild(document.createTextNode(comments));
ul.appendChild(li);
}
<ul className='list-unstyled'></ul>
Also you can use appendChild
for (var i = 0; i < comments.length; i++) {
var comments = comments[i];
var li = document.createElement('li');
li.innerHTML = comments;
document.getElementsByClassName("list-unstyled")[0].appendChild(li);
}
Here is the Vanilla JS equivalent, except the content of the child elements, which I left for you to finish using the same methods I've used:
function renderComments(comments) {
if (comments != null) {
let ans = document.createElement('div');
ans.classList.add('col-12', 'col-md-5', 'm-1');
let h4Node = document.createElement('h4');
h4Node.innerText = 'Comments';
ans.appendChild(h4Node);
let ulNode = document.createElement('ul');
ulNode.classList.add('list-unstyled');
for (let i = 0; i < comments.length; i++) {
let comment = comments[i];
let currNode = document.createElement('li');
currNode.setAttribute('key', comment.id);
// Here add the additional two <p> elements
ulNode.appendChild(currNode);
}
ans.appendChild(ulNode);
return ans;
}
}
let example = [{id: 1}, {id: 2}];
document.body.appendChild(renderComments(example));
The core of this are createElement and appendChild, which creates an HTML node and adds an element as a child, respectively.

Can't remove child from parent node

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

What to do when looping repeats in 2 different areas

The code gets the values of the input and sends it to the textarea, but when you add more than one title the values are repeated in the result of the titles, for example, the DESCRIPTIONS of title 1 are the same as in title 2, why does this happen? and how to make it work without changing the purpose?
Run the code in codepen.io or jsfiddle.net
This is what happens:
This is what should happen:
function result() {
var inp2 = document.getElementsByName("inp2");
var titu = document.getElementsByName("titu");
var res = document.getElementById("result");
res.value = "";
if (titu[0]) {
for (var k = 0; k < titu.length; k++) {
if (titu[k].value.trim() != '') {
res.value += `<div>
<span>${titu[k].value.trim()}</span>
</div>
<ul>\n`;
for (var j = 0; j < inp2.length; j++) {
if (inp2[j].value.trim() != '') {
res.value += `<li>${inp2[j].value.trim()}</li>\n`;
}
}
}
}
}else {
console.log("test")
res.value += `<ul>\n`;
for (var l = 0; l < inp2.length; l++) {
if (inp2[l].value.trim() != '') {
res.value += `<li>${inp2[l].value.trim()}</li>\n`;
}
}
}
};
// -----------------------------------------
if (document.getElementById("add2")) {
let cont2 = 1;
document.getElementById("add2").onclick = function clone2() {
let container2 = document.getElementById("output2");
let tempLinha2 = document.querySelector('#template2');
let clone2 = document.importNode(tempLinha2.content, true);
const label2 = clone2.querySelector("label");
label2.htmlFor = cont2;
clone2.querySelector("input").className = cont2;
container2.appendChild(clone2);
cont2++;
};
document.getElementById("del2").onclick = function del2() {
document.querySelector('#output2 #linha2:last-child').remove();
};
}
// ---------------------------------------
if (document.getElementById("addtit")) {
let cont3 = 1;
document.getElementById("addtit").onclick = function clone3() {
let container3 = document.getElementById("output2");
let tempLinha3 = document.querySelector('#template3');
let clone3 = document.importNode(tempLinha3.content, true);
const label3 = clone3.querySelector("label");
label3.htmlFor = cont3;
clone3.querySelector("input").className = cont3;
container3.appendChild(clone3);
cont3++;
document.getElementById('add2').id = 'add3';
document.getElementById('del2').id = 'del3';
};
document.getElementById("deltit").onclick = function deltit() {
document.querySelector('#output2 #alg:last-child').remove();
document.getElementById('add3').id = 'add2';
document.getElementById('del3').id = 'del2';
};
}
// -----------------------------------------
if (document.getElementById("add3")) {
let cont4 = 1;
document.getElementById("add3").onclick = function clone4() {
let container4 = document.getElementById("output3");
let tempLinha4 = document.querySelector('#template2');
let clone4 = document.importNode(tempLinha4.content, true);
const label4 = clone4.querySelector("label");
label4.htmlFor = cont4;
clone4.querySelector("input").className = cont4;
container4.appendChild(clone4);
cont4++;
};
document.getElementById("del3").onclick = function del4() {
document.querySelector('#output3 #linha2:last-child').remove();
};
}
<div class="container">
<button id="addtit">+ TITLE</button>
<button id="deltit">- TITLE</button>
<button id="add2">+ DESCRIPTION</button>
<button id="del2">- DESCRIPTION</button>
<div id="output2"></div>
<div class='botoes'>
<button onclick="result()" id='done'>DONE</button>
</div>
<div class="header"><span class="title">RESULT</span>
</div>
<div class="linha"><textarea id="result"></textarea>
</div>
</div>
<!-- template 2 -->
<template id="template2">
<div class="linha" id="linha2"><div class="coluna1"><label for="0">DESCRIPTION:</label></div><div class="coluna2"><input name="inp2" class="0" type="text"/></div>
</div>
</template>
<!-- template 3 -->
<template id="template3">
<div id="alg">
<div class="linha"><div class="coluna1"><label for="0">TITLE:</label></div><div class="coluna2"><input name="titu" class="0" type="text"/></div>
</div>
<div class="linha" id="linha3"><div class="coluna1"><label for="0">DESCRIPTION:</label></div><div class="coluna2"><input name="inp2" class="0" type="text"/></div>
</div>
<div id="output3"></div>
</div>
</template>
Ok. it's because this part of code in function result:
if (titu[0]) {
for (var k = 0; k < titu.length; k++) {
if (titu[k].value.trim() != '') {
res.value += `<div>
<span>${titu[k].value.trim()}</span>
</div>
<ul>\n`;
for (var j = 0; j < inp2.length; j++) {
if (inp2[j].value.trim() != '') {
res.value += `<li>${inp2[j].value.trim()}</li>\n`;
}
}
}
}
}
your titles have the same names : 'titu' , and your descriptions have same names : 'inp2', and you have two nested loops, for each title, loop on description, and it results as you see.
it's better to change your code and make different names and ids
by the way. if you persist to do not change your code, you should use one loop for both of them, like this code
if (titu[0]) {
for (var k = 0; k < titu.length; k++) {
if (titu[k].value.trim() != '') {
res.value += `<div>
<span>${titu[k].value.trim()}</span>
</div>
<ul>\n`;
if (inp2[k].value.trim() != '') {
res.value += `<li>${inp2[k].value.trim()}</li>\n`;
}
}
}
}
UPDATE
for the case of more description for each title, you have to change the code of onClick methods of Title+ and Description+, the added title and all of its description must have same parent, and after doing that, it's possible to solve the problem like this . (assuming the parent that I already have said has class name 'parent')
function result() {
var parents = document.querySelectorAll(".parent")
parents.forEach(function(parent){
var title = parent.querySelector("titu");
var descriptions = parent.querySelectorAll("inp2");
var res = document.getElementById("result");
if (title.value.trim() != '') {
res.value += `<div>
<span>${title.value.trim()}</span>
</div>
<ul>\n`;
}
descriptions.forEach(function(inp2){
if (inp2.value.trim() != '') {
res.value += `<li>${inp2.value.trim()}</li>\n`;
}
});
});
}
notice that this code could work after modifying Title+ and Description+ events and add same parent with class name parent to title and descriptions inputs

Categories