Home > database >  How do you make a function in JavaScript that displays 10 elements at a time with a button?
How do you make a function in JavaScript that displays 10 elements at a time with a button?

Time:03-20

I am displaying data from a JSON file to a website using HTML. I want it to display the first 10 actors in the list and the movie they are in. Then I want the user to be able to press a button and be able to display the next 10, and another button to go back 10. I have been able to display the first 10 onl oad, I have an index on line 17 that counts how many rows I have added to "newContent" and once it reaches 10 it breaks the loop on line 36. But when I press the button on the page the index no longer works. It just goes past 10 without breaking till the loop goes through the entire JSON file.

var actors = [];


const xhr = new XMLHttpRequest(); //Gets the http request

xhr.onload = function() {
  if (xhr.status == 200) {
    var responseObject = JSON.parse(xhr.responseText);
    var newContent = '';

    var parameter = 0;
    var counter = 0;

    function table(parameter) {

      var index = 0;

      for (var i = parameter; i < responseObject.movies.length; i  ) {
        for (var j = 0; j < responseObject.movies[i].cast.length; j  ) {
          //Checking for duplicates
          if ((actors.indexOf(responseObject.movies[i].cast[j]) == -1)) {
            var letter = responseObject.movies[i].cast[j].charAt(0);
            if ((/[a-zA-Z]/).test(letter)) {
              newContent  = '<tr >';
              newContent  = '<td>'   responseObject.movies[i].cast[j]   '</td>';
              newContent  = '<td>'   responseObject.movies[i].title   '</td>';
              newContent  = '<td>'   index   '</td>';
              newContent  = '</tr>';
              index  ;
            }
          }
        }
        counter  ;

        if (index == 10) {
          break;
        }
      }
      return newContent;
    }
    document.getElementById('castNames').innerHTML = table(0);

    var showMoreBtn = document.getElementById('showMoreBtn');
    showMoreBtn.addEventListener('click', showMore, false);


    function showMore() {
      parameter = counter;
      return document.getElementById('castNames').innerHTML = table(parameter);
    }

  }


}


xhr.open('GET', "static/data/movies.json", true);
xhr.send();
table {
  width: 100%;
}

tr {
  border-bottom: 1px solid black;
}

th {
  color: black;
}

td {
  padding-top: 5px;
  color: black;
}
<!doctype html>
<html lang="en">

<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

  <link rel="stylesheet" href="static/css/style.css">

</head>

<body>

  <nav >
    <div >
      <img src="static/images/movieLogo.png" alt="reel of film" width="50px" height=a uto style="margin-right: 25px;">
      <div  id="navbarNav">
        <ul >
          <li><a href="{{ url_for('index') }}" >Home</a></li>
          <li><a href="{{ url_for('movies') }}" >Movies</a></li>
          <li><a href="{{ url_for('actors') }}" >Actors</a></li>
        </ul>
      </div>
    </div>
  </nav>

  <div id="buttonClass">
    <button id="showMoreBtn"  type="button">More</button>
    <!--<button id="viewLessBtn" class = "button" type="button">More</button>-->
  </div>
  <table>
    <thead>
      <tr>
        <th >Name</td>
          <th >Movie</td>
      </tr>
    </thead>

    <tbody id="castNames">

    </tbody>
  </table>

  <!--<p id="castNames"></p>-->

  <script src="{{ url_for('static', filename='actorDisplay.js') }}"></script>

  <!-- Optional JavaScript; choose one of the two! -->

  <!-- Option 1: Bootstrap Bundle with Popper -->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg OMhuP IlRH9sENBO0LRn5q 8nbTov4 1p" crossorigin="anonymous"></script>

  <!-- Option 2: Separate Popper and Bootstrap JS -->
  <!--
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-7 zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG 2QOK9T ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
    -->
</body>

</html>

TLDR index in my JavaScript in the function table() is working when I load the page but not when I call the function with the button to see the next 10.

Here is a snippet of the JSON file.

{"movies": [{
    "title": "Affair in Havana",
    "year": 1957,
    "cast": [
      "John Cassavetes",
      "Sara Shane",
      "Raymond Burr"
    ],
    "genres": [
      "Noir"
    ]
  },
  {
    "title": "Affair in Reno",
    "year": 1957,
    "cast": [
      "John Lund",
      "Doris Singleton"
    ],
    "genres": [
      "Comedy"
    ]
  },
  {
    "title": "An Affair to Remember",
    "year": 1957,
    "cast": [
      "Cary Grant",
      "Deborah Kerr",
      "Cathleen Nesbitt",
      "Richard Denning"
    ],
    "genres": [
      "Romance"
    ]
  },
  {
    "title": "Ali Baba Bunny",
    "year": 1957,
    "cast": [],
    "genres": [
      "Animated"
    ]
  },
  {
    "title": "Aquaman",
    "year": 2018,
    "cast": [
      "Jason Momoa",
      "Amber Heard",
      "Willem Dafoe",
      "Patrick Wilson",
      "Dolph Lundgren",
      "Yahya Abdul-Mateen II",
      "Nicole Kidman"
    ],
    "genres": [
      "Superhero",
      "Action",
      "Adventure"
    ]
  },
  {
    "title": "Bumblebee",
    "year": 2018,
    "cast": [
      "Hailee Steinfeld",
      "John Cena",
      "Jorge Lendeborg Jr.",
      "Jason Drucker",
      "Rachel Crow",
      "Pamela Adlon"
    ],
    "genres": [
      "Action",
      "Adventure",
      "Science Fiction"
    ]
  },
  {
    "title": "Welcome to Marwen",
    "year": 2018,
    "cast": [
      "Steve Carell",
      "Leslie Mann",
      "Diane Kruger",
      "Falk Hentschel",
      "Janelle Monáe",
      "Eiza Gonzalez",
      "Gwendoline Christie"
    ],
    "genres": [
      "Fantasy",
      "Drama"
    ]
  },
  {
    "title": "Holmes and Watson",
    "year": 2018,
    "cast": [
      "Will Ferrell",
      "John C. Reilly",
      "Rebecca Hall",
      "Ralph Fiennes",
      "Rob Brydon",
      "Kelly Macdonald",
      "Lauren Lapkus",
      "Hugh Laurie"
    ],
    "genres": [
      "Action",
      "Mystery",
      "Comedy"
    ]
  },
  {
    "title": "On the Basis of Sex",
    "year": 2018,
    "cast": [
      "Felicity Jones",
      "Armie Hammer",
      "Justin Theroux",
      "Jack Reynor",
      "Cailee Spaeny",
      "Sam Waterston",
      "Kathy Bates"
    ],
    "genres": [
      "Biography",
      "Drama"
    ]
  },
  {
    "title": "Destroyer",
    "year": 2018,
    "cast": [
      "Nicole Kidman",
      "Tatiana Maslany",
      "Sebastian Stan",
      "Toby Kebbell",
      "Scoot McNairy"
    ],
    "genres": [
      "Crime",
      "Thriller"
    ]
  }]}

CodePudding user response:

You attempt to break the outer loop when index == 10. But it gets incremented in the inner loop. So it can pass 10 in that inner loop and never equal 10 when it gets tested in the outer loop. Now if you also break from the inner loop, you may miss some actors from the last "processed" movie.

So... Instead of attempting to break loops... And figure out where to resume after, why not simply process the whole json and append ALL rows.

After this, you simply have to change a counter variable to toggle the style.display of the rows.

// We'll run the "main" function outside of an xhr callback for this demo.

/*
const xhr = new XMLHttpRequest(); //Gets the http request

xhr.onload = function () {
  if (xhr.status == 200) {
    main(xhr.responseText);
  }
};

xhr.open('GET', "static/data/movies.json", true);
xhr.send();
*/

// Main function
function main(xhrResponse) {
  // Use this one when trying with xhr
  // var responseObject = JSON.parse(xhrResponse);
  var responseObject = json;
  
  var newContent = "";
  var actors = [];

  function table() {
    var index = 0;

    for (var i = 0; i < responseObject.movies.length; i  ) {
      for (var j = 0; j < responseObject.movies[i].cast.length; j  ) {
        //Checking for duplicates
        if (actors.indexOf(responseObject.movies[i].cast[j]) == -1) {
          var letter = responseObject.movies[i].cast[j].charAt(0);
          if (/[a-zA-Z]/.test(letter)) {
            newContent  = `<tr >
                            <td>${responseObject.movies[i].cast[j]}</td>
                            <td>${responseObject.movies[i].title}</td>
                            <td>${index}</td>
                          </tr>`
            index  ;
            // Add this to enable the duplicate actor condition
            // actors.push(responseObject.movies[i].cast[j])
          }
        }
      }
    }
    return newContent;
  }

  function displayRows() {
    document.getElementById("castNames").querySelectorAll("tr").forEach(function(tr, index) {
      tr.style.display = index < counter ? "table-row" : "none"
    })
  }

  var counter = 10

  function showMore() {
    counter  = 10
    displayRows()
  }

  function showLess() {
    counter -= 10
    displayRows()
  }

  // Event handlers for the buttons
  var showMoreBtn = document.getElementById("showMoreBtn");
  showMoreBtn.addEventListener("click", showMore, false);
  var showMoreBtn = document.getElementById("viewLessBtn");
  showMoreBtn.addEventListener("click", showLess, false);

  // On xhr load table creation
  document.getElementById("castNames").innerHTML = table();
  displayRows()
}


// The json
var json = {
  movies: [{
      title: "Affair in Havana",
      year: 1957,
      cast: ["John Cassavetes", "Sara Shane", "Raymond Burr"],
      genres: ["Noir"]
    },
    {
      title: "Affair in Reno",
      year: 1957,
      cast: ["John Lund", "Doris Singleton"],
      genres: ["Comedy"]
    },
    {
      title: "An Affair to Remember",
      year: 1957,
      cast: [
        "Cary Grant",
        "Deborah Kerr",
        "Cathleen Nesbitt",
        "Richard Denning"
      ],
      genres: ["Romance"]
    },
    {
      title: "Ali Baba Bunny",
      year: 1957,
      cast: [],
      genres: ["Animated"]
    },
    {
      title: "Aquaman",
      year: 2018,
      cast: [
        "Jason Momoa",
        "Amber Heard",
        "Willem Dafoe",
        "Patrick Wilson",
        "Dolph Lundgren",
        "Yahya Abdul-Mateen II",
        "Nicole Kidman"
      ],
      genres: ["Superhero", "Action", "Adventure"]
    },
    {
      title: "Bumblebee",
      year: 2018,
      cast: [
        "Hailee Steinfeld",
        "John Cena",
        "Jorge Lendeborg Jr.",
        "Jason Drucker",
        "Rachel Crow",
        "Pamela Adlon"
      ],
      genres: ["Action", "Adventure", "Science Fiction"]
    },
    {
      title: "Welcome to Marwen",
      year: 2018,
      cast: [
        "Steve Carell",
        "Leslie Mann",
        "Diane Kruger",
        "Falk Hentschel",
        "Janelle Monáe",
        "Eiza Gonzalez",
        "Gwendoline Christie"
      ],
      genres: ["Fantasy", "Drama"]
    },
    {
      title: "Holmes and Watson",
      year: 2018,
      cast: [
        "Will Ferrell",
        "John C. Reilly",
        "Rebecca Hall",
        "Ralph Fiennes",
        "Rob Brydon",
        "Kelly Macdonald",
        "Lauren Lapkus",
        "Hugh Laurie"
      ],
      genres: ["Action", "Mystery", "Comedy"]
    },
    {
      title: "On the Basis of Sex",
      year: 2018,
      cast: [
        "Felicity Jones",
        "Armie Hammer",
        "Justin Theroux",
        "Jack Reynor",
        "Cailee Spaeny",
        "Sam Waterston",
        "Kathy Bates"
      ],
      genres: ["Biography", "Drama"]
    },
    {
      title: "Destroyer",
      year: 2018,
      cast: [
        "Nicole Kidman",
        "Tatiana Maslany",
        "Sebastian Stan",
        "Toby Kebbell",
        "Scoot McNairy"
      ],
      genres: ["Crime", "Thriller"]
    }
  ]
};

// For this demo... Call the function here to simulate xhr
main()
table {
  width: 100%;
}

tr {
  border-bottom: 1px solid black;
}

th {
  color: black;
}

td {
  padding-top: 5px;
  color: black;
}
<!doctype html>
<html lang="en">

<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <link rel="stylesheet" href="static/css/style.css">
</head>

<body>
  <nav >
    <div >
      <img src="static/images/movieLogo.png" alt="reel of film" width="50px" height=a uto style="margin-right: 25px;">
      <div  id="navbarNav">
        <ul >
          <li><a href="{{ url_for('index') }}" >Home</a></li>
          <li><a href="{{ url_for('movies') }}" >Movies</a></li>
          <li><a href="{{ url_for('actors') }}" >Actors</a></li>
        </ul>
      </div>
    </div>
  </nav>

  <div id="buttonClass">
    <button id="showMoreBtn"  type="button">More</button>
    <button id="viewLessBtn"  type="button">Less</button>
  </div>
  <table>
    <thead>
      <tr>
        <th >Name</td>
          <th >Movie</td>
      </tr>
    </thead>

    <tbody id="castNames">

    </tbody>
  </table>

  <!--<p id="castNames"></p>-->

  <script src="{{ url_for('static', filename='actorDisplay.js') }}"></script>

  <!-- Optional JavaScript; choose one of the two! -->

  <!-- Option 1: Bootstrap Bundle with Popper -->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg OMhuP IlRH9sENBO0LRn5q 8nbTov4 1p" crossorigin="anonymous"></script>

  <!-- Option 2: Separate Popper and Bootstrap JS -->
  <!--
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-7 zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG 2QOK9T ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
    -->
</body>

</html>

CodePudding user response:

100% @Louys Patrice Bessette has a better answer, and probably a more well-thought-through solution. But I have finally figured it out myself as well before I saw their solution. Decided to post my solution anyways if anyone else like me doesn't still fully understand Jquery(which I should, but I'm trying to use what I know now)

const xhr = new XMLHttpRequest(); //Gets the http request

xhr.onload = function() {
  if (xhr.status == 200) {
    var responseObject = JSON.parse(xhr.responseText);
    var newContent = '';

    var counter = 0;
    var startBool = false;
    var btnCounter = 0;
    var startArray = [];

    function table(parameter) {

      var index = 0;

      for (var i = parameter; i < responseObject.movies.length; i  ) {     
        for (var j = 0; j < responseObject.movies[i].cast.length; j  ) {
            if (index == 10) {
                counter = i   1;
                break;
            }
            var letter = responseObject.movies[i].cast[j].charAt(0);
            if ((/[a-zA-Z]/).test(letter)) {
              if (startBool == false) {
                  startArray.push(i);
                  startBool = true;
              }

                newContent  = '<tr >';
                newContent  = '<td>'   responseObject.movies[i].cast[j]   '</td>';
                newContent  = '<td>'   responseObject.movies[i].title   '</td>';
                newContent  = '<td>'   index   '</td>';
                newContent  = '<td>'   i   '</td>';
                newContent  = '</tr>';
                index  ;
            }       
        }
        if (index == 10) {   
            counter = i   1;   
            break;
        }      
      }
      return newContent;
    }
    document.getElementById('castNames').innerHTML = table(0);

    var showMoreBtn = document.getElementById('showMoreBtn');
    showMoreBtn.addEventListener('click', showMore, false);

    function showMore() {
        startBool = false;
        btnCounter  ;
        newContent = "";       
        return document.getElementById('castNames').innerHTML = table(counter);
    }

    var showLessBtn = document.getElementById('showLessBtn');
    showLessBtn.addEventListener('click', showLess, false);

    function showLess() {
        btnCounter--;
        counter = startArray[btnCounter];
        newContent = "";
        return document.getElementById('castNames').innerHTML = table(counter);
    }
  }
}
xhr.open('GET', "static/data/movies.json", true);
xhr.send();
table {
  width: 100%;
}

tr {
  border-bottom: 1px solid black;
}

th {
  color: black;
}

td {
  padding-top: 5px;
  color: black;
}
<!doctype html>
<html lang="en">

<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

  <link rel="stylesheet" href="static/css/style.css">

</head>

<body>

  <nav >
    <div >
      <img src="static/images/movieLogo.png" alt="reel of film" width="50px" height=a uto style="margin-right: 25px;">
      <div  id="navbarNav">
        <ul >
          <li><a href="{{ url_for('index') }}" >Home</a></li>
          <li><a href="{{ url_for('movies') }}" >Movies</a></li>
          <li><a href="{{ url_for('actors') }}" >Actors</a></li>
        </ul>
      </div>
    </div>
  </nav>

  <div id="buttonClass">
    <button id="showMoreBtn"  type="button">More</button>
    <button id="showLessBtn" class = "button" type="button">Less</button>
  </div>
  <table>
    <thead>
      <tr>
        <th >Name</td>
          <th >Movie</td>
      </tr>
    </thead>

    <tbody id="castNames">

    </tbody>
  </table>

  <!--<p id="castNames"></p>-->

  <script src="{{ url_for('static', filename='actorDisplay.js') }}"></script>

  <!-- Optional JavaScript; choose one of the two! -->

  <!-- Option 1: Bootstrap Bundle with Popper -->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg OMhuP IlRH9sENBO0LRn5q 8nbTov4 1p" crossorigin="anonymous"></script>

  <!-- Option 2: Separate Popper and Bootstrap JS -->
  <!--
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-7 zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG 2QOK9T ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
    -->
</body>

</html>

  • Related