Bonjour, j'essaie actuellment de créer une barre de recherche par mots clefs (pour afficher des films par exemple avec le début du titre etc...), mais visiblement elle ne fonctionne pas

var filterFilms = function() {

 document.getElementById('filter').addEventListener('keyup', filterFilms {
          var filter = this.value.toLowerCase();
          var documents = document.querySelectorAll('.document');

          Array.prototype.forEach.call(documents, filterFilms(document) {
            // On a bien trouvé les termes de recherche.
            if (document.innerHTML.toLowerCase().indexOf(filter) > -1) {
              document.style.display = 'block';
            } else {
              document.style.display = 'none';
            }
          });
        });
}

Comment pourrais-je modifier mon code ?

J'obtiens aucun résultat quand je fais une recherche dans la bare de recherche...

18 réponses


Mickael Christine
Réponse acceptée

Hello,

Ta fonction filterFilms (vue le nom j'imagine quel filtre mais sur quoi par quoi comment), attend quoi en paramêtre ?

J'ai un peu de mal à comprendre pourquoi tu lui passe document sans S
Et pareil apres je comprend pas pourquoi tu vérifie document sans S et pourquoi tu lui ajoute/retire du style. Est-ce que tu te trompe pas entre documentS et document ?

Lartak
Réponse acceptée

Bonsoir.
C'est normal que ça ne fonctionne pas, car tu fais appel dans un évènement à une fonction depuis l'intérieur de celle-ci.
De plus que d'après le code que tu présentes, tu ne fais à aucun moment appel à la fonction en dehors de celle-ci.
Autre chose, tu n'as pas l'impression de faire une erreur en utilisant toLowerCase sur innerHTML ?

Hey ! Alors enfait j'ai un fichier HTML qui trie des films et j'aurais souhaité faire une barre qui trie par mots clefs
Par exemple pour rechercher "Les Avengers" on peut le retrouver si on fait "Les A", "Les", "Les Avengers" etc
Après, je me trompe surement entre document et documentS car je viens de débuter.. et je ne vois pas bien comment la "modifier"

J'ai également vu qu'il était possible d'utiliser la méthode "includes" pour renvoyer si une chaîne de caractères est bien comprise dans une autre mais je ne vois pas comment l'introduire dans mon code

Il y a la méthode startsWith qui permet de vérifier si une chaîne de caractères commence par une valeur, elle est évidemment à utiliser sur une chaîne de caractères et non sur du contenu HTML.
Mais si tu veux vérifier si la valeur est contenue dans une autre, il te faut en effet utiliser la méthode includes.
De toute manière, pour pouvoir utiliser l'une ou l'autre, il te faut corriger ton code, en prenant en compte ce que j'ai indiqué dans ma précédente réponse.

Ok maintenant que ta modif le début de ton code c'est plus claire.

Pose à l'ecrit ce que tu veux faire ligne par ligne tu y verra plus claire.

      // Au changement sur mon input (filter) 
              ...code
      // Je récupere la valeur tapé
              ...code
              console.log(ma value)
      // Je récupere mes elements html 
              ...code
              console.log(mes elements)
      // Je cherche dans ces elements si la valeur tapé y est contenu
              ...code
              console.log(la valeur de chaque element + resultat de ma condition)
      // Si elle n'y est pas
              ...code
              console.log(resultat de ma condition)

Tu peux parfaitement utiliser un toLowerCase sur un innerHTML, pas de souci la dessus.
Te lance pas sur des méthode call() ou des histoire d'index tu n'en as pas besoin.

Bon courage !!!

Bonjour,

Je suis sur le point d'apprendre et merci à Lartak car tes réponses m'oriente sur les trucs qui me restent à savoir, je viens de découvrir la méthode String.prototype.endsWith et String.prototype.includes, et je vais me renseigner sur les autres que tu as mentionné.

Super ! Merci beaucoup pour vos différentes réponses ! Je vais essayer de finaliser ce code et voir si cela fonctionne, en tout cas je vous remercie des conseils que vous m'avez donné :) Mais juste une question : Pourquoi êtes-vous "mitigés" sur le fait d'utiliser un toLowerCase sur un innerHTML ? :)

Aucune idée =)
Moi ca ne me choque pas vue que c'est bien une chaine de caractères que tu passe en lowercase et pas du html ;-)

Bonsoir, j'ai essayé de suivre vos conseils mais j'ai quelques lacunes et par conséquent, cela ne fonctionne pas :( Néanmoins, suis-je sur la bonne voie ? :):)

var filterFilms = function(f) {

// Au changement sur mon input (filter)
f('#filterFilms').keyup(function(event){
// Je récupere la valeur tapée
var input = f(this);
var val = input.val();
console.log(val)
}
// Je récupere mes elements html
var elements = f(this)
console.log(elements)
// Je cherche dans ces elements si la valeur tapé y est contenu
String.prototype.includes= function(html,title)
console.log(title + resultat de ma condition??)
// Si elle n'y est pas
...code
console.log(resultat de ma condition)

}

Pourquoi essaies tu de redéfinir la méthode includes via une fonction ?
Qui de plus est incorrecte ?
Il ne te faut pas faire :

String.prototype.includes

Mais plutôt:

const filmsElements = document.querySelectorAll('.document')
for (let i = 0; i < filmsElement.length; i++) {
    let filmElement = filmsElement[i], film = filmElement.innerText
    if (film.includes(val)) {
        filmElement.style.display = 'block';
    } else {
        filmElement.style.display = 'none';
    }
}

Voici d'autre possibilités en plus de la réponse de Lartak à toi de voir ce qui te convient.

    document.getElementById("filter").addEventListener("keyup", function () {
      var filter = this.value.toLowerCase();
      var documents = document.querySelectorAll(".doc");
      documents.forEach(function (doc) {
        if (doc.innerHTML.toLowerCase().includes(filter)) {
          doc.style.display = "block";
        } else {
          doc.style.display = "none";
        }
      });
    });

    document.getElementById("filter").addEventListener("keyup", function () {
      const filter = this.value.toLowerCase();
      document.querySelectorAll(".doc").forEach((doc) =>
        doc.innerHTML.toLowerCase().includes(filter)
          ? (doc.style.display = "block")
          : (doc.style.display = "none")
      );
    });

Voici le code que j'ai pu établir :) Mais, cela ne fonctionne pas et je ne sais pas pourquoi ...

let filter = document.getElementById('filter');
filter.addEventListener('keyup', filterFilms);
filter.value='';

(....)

var filterFilms = function() {

      let filter = document.getElementById('filter');
    let filterText = filter.value.toLowerCase();
    let allFilms = document.querySelectorAll('#films div.film');
    for (i in allFilms){
        //...code//
            let title = divFilm.querySelector('h3').textContent.toLowerCase();
        if (title.includes(filterText)) {
          i.style.display = "inline-block";
        } else {
          i.style.display = "none";
      console.log(filter)
        }
    }
}

Cela ne repère toujours pas quand je tape dans la barre de recherches et ne trie pas non plus les films en fonction de leurs titres ... :(

Hello, divFilm n'est déclaré null part dans ce que tu viens d'écrire
Tu peux aussi directement passé .film dans ta varibale allFilms

let allFilms = document.querySelectorAll('.film');

J'avais déclaré divFilm dans une autre fonction auparavant

var init = function() {

  addAllFilms();

  let filter = document.getElementById('filter');
  filter.addEventListener('keyup', filterFilms);
  filter.value='';

}

/*Chargement de la page*/
window.addEventListener('DOMContentLoaded', init);

var addAllFilms = function() {
  let filmContainer = document.getElementById('films');
  for(let i = 0; i < filmData.length; i++) {
    filmContainer.appendChild(createFilm( i ));
  }
}
/* Permet de créer un film sous la forme div.film 
Paramètre : index, un int qui représente l'index du film voulut dans le filmData
Contrainte : Que l'index existe ou soit valide
Retour : Le film sous la forme div.film
*/

var createFilm = function(index) { 
  let titre = filmData[index].title;
  let image = filmData[index].image;
  var divFilm = document.createElement("div");

  const idFilm = `${index}-film`
  divFilm.setAttribute('id',idFilm);
  divFilm.setAttribute('class',"film");
  divFilm.innerHTML = `<img src=${image} alt=${titre}/>
                        <h3>${titre}</h3>
                        `
  console.log(divFilm);

}

/*La fonction qui ne fonctionne pas */

var filterFilms = function() {

      let filter = document.getElementById('filter');
    let filterText = filter.value.toLowerCase();
    let allFilms = document.querySelectorAll('#films div.film');
    for (i in allFilms){
            let title = divFilm.querySelector('h3').textContent.toLowerCase();
        if (title.includes(filterText)) {
          i.style.display = "inline-block";
        } else {
          i.style.display = "none";
      console.log(filter)
        }
    }
}

Mais cela ne repère toujours pas quand je change avec`

let allFilms = document.querySelectorAll('.film')`

OH ! J'ai réussi à trouver comment cela se faisait-il !
merci beaucoup :):)

Voici différentes perspectives autres que la réponse de Lartak pour que vous puissiez percevoir ce qui fonctionne pour vous. divFilm n'est annoncé nulle part dans ce que vous venez de composer
Vous pouvez également passer directement .film dans votre variable allFilms. J'ai compris comment découvrir comment c'était fini!
beaucoup merci à vous à un tel point.BazoocamChatiw