0

As a student project, we are trying to build a website that gives recommendations for movies. After recommendations are generated we want the user to be able to click on any of the movie posters in order to pull up more information about that specific movie. The .on('click') currently selects all of the results which are not ideal...

As it stands this is what we have:

axios.get(omdbCall + movieTitles)
  .then(function(response){

  let movies = response.data.results;

  for (i=0; i < movies.length; i++) {
     var posterPath = movies[i].poster_path;
     var movieID = movies[i].id;
     var movTitle = movies[i].title;
     var movImg = "https://image.tmdb.org/t/p/w92";

     $('#movPoster').append('<img class="posters" src=' + movImg + posterPath + '>');
   }

     $(".posters").on("click", function () {
        console.log("I clicked a poster!");
     })
})

We also tried changing the rendered img tag to include an id based on the movie title or its imdbID. We tried using this selector for both attempts:

$("#" + movTitle)

With this change in the append function:

$('#movPoster').append('<img id=' + movTitle + ' src=' + movImg + posterPath + '>');

I expected to be able to select just one element but that ain't what's happening. I hope I explained properly and in enough detail. Any help would be greatly greatly appreciated. Thank you!

Masuk Helal Anik
  • 2,155
  • 21
  • 29

2 Answers2

0

you are making .on('click') event direclty on dynamically generated html. This won't work. Because when the script was loaded initially, there is no element with class posters.

You have to use something like this

$("#not_dynamic_element").on("click", ".posters", function(){
 // Code here
});

The logic is you have to select an element that is not dynamically loaded. i.e, a static element which is an ancestor of posters class.

For example say you have a div with class posters-container which is already present on page load. You are appending the img tag with class posters to this div. So you need to get click on all img tag with class posters, you could write,

$(".posters-container").on("click", ".posters", function(){
 // Code here
});

Hope you understood the logic and what the issue was.

UPDATE - LOGIC ISSUE IN FIDDLE

I see what's wrong in your fiddle. I am trying to make it simple. So check this code you have written

axios.get(finalSearch)
    .then(function(response){
        // console.log(response);
        let movies = response.data.Similar.Results;
        // let posters = response.data.results.poster_path;
        for (i=0; i < movies.length; i++){
            // console.log(movies[i].Name);
            var movArr = movies[i].Name;
            var movStr = movArr.split(" ");
            var movieTitles = movStr.join("+")
            getMoviePosters(movieTitles);
        }         
    })
    .catch(function(err) {
        console.log(err);
    })

In this code you can see that you are calling the function getMoviePosters(movieTitles) inside a for loop. Your for loop contains the following line which you use to select the dynamically generated movie poster element.

$("#movPoster").on("click", function () {
    console.log("I clicked a poster!");             
})

So i would suggest you to call this click function after the for loop as shown below (Remove the previous code). Also add posters class to click function.

axios.get(finalSearch).then(function(response){
    // console.log(response);
    let movies = response.data.Similar.Results;
    // let posters = response.data.results.poster_path;
    for (i=0; i < movies.length; i++){
        // console.log(movies[i].Name);
        var movArr = movies[i].Name;
        var movStr = movArr.split(" ");
        var movieTitles = movStr.join("+")
        getMoviePosters(movieTitles);
    }
    $("#movPoster").on("click", '.posters', function () {
        console.log("I clicked a poster!");             
    })
})
melvin
  • 2,571
  • 1
  • 14
  • 37
  • Thank you for taking the time to respond. Your answer made perfect sense but when I tried to change the code its still giving me issues. It still logs out 20 clicks instead of 1. 20 happens to be the number of objects i get from the api so maybe its somehow only selecting those responses? Apologies if i'm missing the obvious here... – Sid Telidevara Apr 20 '19 at 19:55
  • Can you make a fiddle or something where i could check ? Can you create a similar issue in js fiddle ? – melvin Apr 21 '19 at 06:19
  • https://jsfiddle.net/CT5555/n015c9s4/28/ That should give you a clearer picture. We already needed to submit today so this isnt time sensitive. This is only for my own learning purposes – Sid Telidevara Apr 22 '19 at 16:48
  • @SidTelidevara I really appreciate your efforts to learn. I saw the error on checking the fiddle. It's logical. Please check my answer (UPDATED) – melvin Apr 23 '19 at 03:54
  • @SidTelidevara You are always welcome. Hope you understood what i tried to expain. :) – melvin Apr 24 '19 at 05:46
0

reason

Maybe when the code$(".posters").on("click",...) runs while img.posters or #movPoster still not rendered in html.So the click events not triggered.

solution

  • You can try to move your code inner$(function() { // move your codes here });(related question!), or just add console.log($('#movPoster'), $('#movPoster .posters')) before $(".posters").on("click",...) to verify whether the target elements exist or not.
  • And bind the click events to #movPoster instead of img.posters

advice

For better performance, you should refactor your code:

  • Bind the click events to #movPoster instead of img.posters which makes performance worser for too much events listener.

  • the code $('#movPoster').append(element) in the loop will cause unneccessay repaint for each loop will insert element inner #movPoster. You could rewrite it like this:

var dom = '';
for(var i=0; i<3; i++) {
 dom += '<img src="">'
}
$('#movPoster').append(dom) // only insert dom 1 time, not 3 times
ishowman
  • 61
  • 6
  • Thank your for your response. I implemented your advice but i still seem to be getting 20 clicks instead of 1. Adding ```console.log($('#movPoster'), $('#movPoster .posters'))``` before the event clicker logs out all of the objects being called. Is it possible that my on.click is selecting the api response instead of the actual elements being generated? Another quick question we have. Your first suggestion to place our code inside ```$(function(){...}``` is a little confusing. Since your link suggests it's a DOM issue would we put the entire api call inside or just the event listener? – Sid Telidevara Apr 20 '19 at 20:28