Executando verificação de segurança...
2

#DÚVIDA - addEventListener não funciona ao clicar na div

Pessoal estou tentando mas não vai, não consegui achar o erro, ao clicar na div, mostra o conteúdo, porém ao clicar novamente, ele não fecha os detalhes.

Meu código é esse aqui:

fetch('https://api.themoviedb.org/3/movie/popular?api_key=307f3bce2cf2642bb1caa0463410a0de&language=en-US&page=1', {
    method: 'GET'
})
    .then(response => response.json())
    .then(function (json) {
        let container = document.querySelector('.container');
        let i = 1;

        // console.log(json);
        json.results.map(function (value, i) {
            container.innerHTML += `
            
            <div class="item"><ol start="${i + 1}"><li><p class="title"><div class="details" style="cursor:pointer;">` + value.title + `<p class="more">+ detalhes</p></div><hr>
            <div class="description" style="display:none;" >`+ value.overview + `</div>
            </hr>
            
            </p></li></ol></div>`;
        });

        let titles = document.querySelectorAll('.item');
        for (let j = 0; j < titles.length; j++) {
            titles[j].addEventListener('click', function (e) {
                if (e.target.querySelector('.description').style.display = "none") {
                    e.target.querySelector('.description').style.display = "block";
                } else {
                    e.target.querySelector('.description').style.display = "none";
                }
            });
        }
    });

Detalhe:
Não sei o porque mas ele está abrindo a "descrição dos filmes" só quando clica no cantinho esquerdo perto do número.

Obrigado pela ajuda desde já!

Carregando publicação patrocinada...
2

No if vc tem que usar == em vez de =. Isso porque o = é uma atribuição, e não uma comparação.

Por exemplo, veja este código:

var x = 'abc';
if (x = 'def') {
    x = 'ghi';
}
console.log(x); // ghi

Nesse código, ao chegar no if, a variável x recebe o valor 'def', e este é avaliado no if. E o JavaScript considera que qualquer string não-vazia é equivalente a true.

Ou seja, sempre vai entrar nesse if. Mas se mudar para if (x == 'def'), aí funciona da forma esperada (só entra no if se x for igual a 'def').

No seu código é a mesma coisa, não importa o valor do display, ele sempre entra no if e muda o display pra block.

1
3

Outra sugestão. Em vez de tratar isso com JavaScript, por que não usar o elemento details? Ele serve justamente para o que vc está fazendo: ter um texto "detalhes", que ao ser clicado, mostra o texto adicional. Ficaria assim:

fetch('https://api.themoviedb.org/3/movie/popular?api_key=307f3bce2cf2642bb1caa0463410a0de&language=en-US&page=1', {
    method: 'GET'
  })
  .then(response => response.json())
  .then(function(json) {
    let container = document.querySelector('.container');
    container.innerHTML = '<ol start="1">';
    json.results.forEach(function(value) {
      container.innerHTML += `<li>${value.title}
            <details>
              <summary>detalhes</summary>
              ${value.overview}
            </details>
            </li>`;
    });
    container.innerHTML += '</ol>';
  });

Ou seja, agora eu tenho uma lista (ol), e cada elemento dela (cada li) contém uma tag details. O texto do summary é o "detalhes", e ao ser clicado, ele revela o restante do conteúdo.

E em vez de colocar estilos inline, vc pode usar este CSS:

li {
  list-style-type: decimal;
}
summary {
  cursor: pointer;
  list-style-type: "+ ";
}

Que fica do jeito que vc queria (filmes com numeração começando do 1, e o "+" antes de "detalhes"):

gif mostrando como ficou

O resto da formatação vc tem que ajustar também, claro, mas aí é com vc :-)

Também troquei map por forEach. Sei que com map "funciona", mas a ideia de map é fazer algo com os elementos e retornar outro array com os resultados. Mas no seu caso vc estava ignorando o resultado do map (o array que ele retorna), então forEach faz mais sentido (só quero iterar pelos elementos e fazer algo com eles, mas não quero gerar outro array com os resultados).

Ou, em vez disso, pode usar um for mesmo:

fetch('https://api.themoviedb.org/3/movie/popular?api_key=307f3bce2cf2642bb1caa0463410a0de&language=en-US&page=1', {
    method: 'GET'
  })
  .then(response => response.json())
  .then(function(json) {
    let container = document.querySelector('.container');
    container.innerHTML = '<ol start="1">';
    for (const value of json.results) {
      container.innerHTML += `<li>${value.title}
            <details>
              <summary>detalhes</summary>
              ${value.overview}
            </details>
            </li>`;
    }
    container.innerHTML += '</ol>';
  });
1

Nossa que massa, não conhecia a details, uma outra forma de resolver o problema. Sou iniciante na programação e estou treinando ainda, mas ajudou bastante!

2
1
2

Ah, só mais uma coisa: vc acabou divulgando sua api_key (está na própria URL: ?api_key=etc). Então agora todo mundo vai poder usá-la.

Eu não vi como é a política de uso desta API, mas veja lá. Se for paga, por exemplo, outras pessoas usarão e a conta vai pra vc.

Se não for paga, ainda sim pode ter limites de uso (X requests por mês, por exemplo), e se tiver mais gente usando, pode acabar com seu limite sem vc saber.

Enfim, sugiro invalidar esta key e gerar outra.

1
2

Mano basicamente é porque o teu "description" ele é filho de uma ol > li, então fazendo uns testes aqui eu percebi que quando clica no numero da lista, ele faz a função, mas quando clica no texto não, é porque na logica do teuu js ta assim

e.target.querySelector('.description').style.display = "none"

então tipo toda vez que clicar em um elemento em que ele tenha o FILHO com a classe ".description" é que ele vai aplicar o if else(inclusive corrige teu if else porque ele como atribuição o correto seria comparação como esse abaixo:).
e.target.querySelector('.description').style.display == "none"

resumindo, como o teu .description não é filho de nenhuma tag 'p', 'hr' então quando clica no titulo ou no "+detalhes" ele executa o if else mas não aplica em nada entende?

Fiz um codigo que rodou usando ParentNode. O Atributo "parentNode" faz referencia a um elemento pai no DOM, no caso eu usei ele duas vezes porque ha casos em que o "Target" esta muito abaixo na camada do DOM. Acredito que essa não seja a melhor forma de resolver tal problema mas no momento resolve sua situação, faça os testes e diga se rodou por ai

Segue abaixo o código que funcionou para o seu caso:


        fetch('https://api.themoviedb.org/3/movie/popular?api_key=307f3bce2cf2642bb1caa0463410a0de&language=en-US&page=1', {
    method: 'GET'
})
    .then(response => response.json())
    .then(function (json) {
        let container = document.querySelector('.container');
        let i = 1;

        json.results.map(function (value, i) {
            container.innerHTML += `
            
            <div class="item"><ol start="${i + 1}"><li> <p class="title"> <div class="details" style="cursor:pointer;">` + value.title +  `<p class="more">+ detalhes</p>
                            </div>  <hr> <div class="description" style="display:none;" >` + value.overview +  `</div> </hr> </p> </li> </ol></div>`;
        });
        let titles = document.querySelectorAll('.item');
        for (let j = 0; j < titles.length; j++) {
            titles[j].addEventListener('click', function (e) {
                if (e.target.parentNode.parentNode.querySelector('.description').style.display == "none") {
                    e.target.parentNode.parentNode.querySelector('.description').style.display = "block";
                } else {
                    e.target.parentNode.parentNode.querySelector('.description').style.display = "none";
                }
            });
        }
    });
1

Muito obrigado, arrumei meu if e com o parentNode funcionou, mas vou tentar ir mais a fundo e tentar fazer funcionar sem o parentNode. Valeu mesmo!