Dynamic load more button on multiple tables

I have two (maybe more in the future) tables with over 100 rows each.
I created a table using the ‘Table Press’ plugin which works perfectly and now I am trying to create a function that shows only 8 rows, adds a ‘load more’ button to each table, and on click, loads the next 8 rows.

Currently I have a little problem with it’s functionality.
When I click one load more button (it doesn’t matter which one I click first), it loads the next 8 rows (9-16).
When I click the other load more button, it loads rows 17-25, instead of it’s next 8.

You can see a working example of this here: https://codepen.io/pixelboutiqueuk-the-lessful/pen/JjogZXa?editors=0010

I’m kind of a newbie with jQuery so any help would be much appreciated.
This is what jQuery I have:

    // load more buttons
    var songTotalRows = $('.songs-table tr').length;
    if ( songTotalRows > 8 ) {
        $('.songs-table').after('<div class="load-more"><input id="song-show" type="button" value="Load More" /></div>');
    }
    
    var albumTotalRows = $('.album-table tr').length;
    if ( albumTotalRows > 8 ) {
        $('.album-table').after('<div class="load-more"><input id="album-show" type="button" value="Load More" /></div>');
    }

    var totalrowshidden;
    var rows2display=8;
    var rem=0;
    var rowCount=0;
    var forCntr;
    var forCntr1;
    var MaxCntr=0;
    
    $('.hide').click(function() {
        var rowCount = $('.spotify-table tr').length;
        rowCount=rowCount/2;
        rowCount=Math.round(rowCount)
    
        for (var i = 0; i < rowCount; i++) {
            $('tr:nth-child('+ i +')').hide(300); 
        }                            
    });
    
    $('#song-show').click(function() {
        rowCount = $('.songs-table tr').length;
        MaxCntr=forStarter+rows2display;
    
        if (forStarter<=$('.songs-table tr').length) {
            for (var i = forStarter; i < MaxCntr; i++) {
             $('.songs-table tr:nth-child('+ i +')').show(200);
            }
            forStarter=forStarter+rows2display
        } else {
            $('#song-show').hide();
        }
    });
    
    $('#album-show').click(function() {
        rowCount = $('.album-table tr').length;
        MaxCntr=forStarter+rows2display;
    
        if (forStarter<=$('.album-table tr').length) {
            for (var i = forStarter; i < MaxCntr; i++) {
             $('.album-table tr:nth-child('+ i +')').show(200);
            }
            forStarter=forStarter+rows2display
        } else {
            $('#album-show').hide();
        }
    });
    
    var rowCount = $('.spotify-table tr').length;
    for (var i = $('.spotify-table tr').length; i > rows2display; i--) {
        rem=rem+1
        $('.spotify-table tr:nth-child('+ i +')').hide(200);
    }
    
    forCntr=$('.spotify-table tr').length-rem;
    forStarter=forCntr+1

Thank you

The problem is (I think) less to do with jQuery and more to do with a confusion of variable names. You’re using the same variables to maniuplate multiple tables, which means that when the rowCount (for example) changes for one table, it’s changing for all tables.

It might make sense to step back and rethink, maybe get it working properly for one table without using global variables. For example, what about this approach:

- for the current table, hide rows beyond index N.
- If the number of rows is equal to the number of visible rows, hide the 'show more' button.
- When the 'show more' is clicked, get all the rows *in this table*.
   - create a "made visible" counter, initialized to 0.
   - Start looping over all the rows. If the current row's visibility is visible, continue to loop.
   - At the first row with a visibility of hidden (or none, however you do), turn it visible and 
      increment our "made visible" counter.
   - if our "made visible" counter matches N, break out of our outer loop - we've made all the rows
     visible we need for this pass. 

Note that none of that requires any global variables. All the information is determined each time we click the ‘show more’, based on the actual DOM. We can dynamically get all the rows for the current table, we can check for and change the visibility, and the temporary “made visible” counter is created and discarded anew each time we click ‘show more’. Each table is self-contained, and doesn’t rely on anything outside of itself to determine its visible row position or counter.

This works for one table.
How can I use the same function for the second table? Or do I need to do two completely separate functions? And how do I do that?

// ALBUM
    var albumTotalRows = $('.album-table tr').length;
    if ( albumTotalRows > 8 ) {
        $('.album-table').after('<div class="load-more"><input id="album-show" type="button" value="Load More" /></div>');
    }

    var totalrowshidden;
    var rows2display = 8;
    var rem = 0;
    var rowCount = 0;
    var forCntr;
    var forCntr1;
    var MaxCntr = 0;
    
    $('.album-hide').click(function() {
        var rowCount = $('.album-table tr').length;
        rowCount = rowCount/2;
        rowCount = Math.round(rowCount)
    
        for (var i = 0; i < rowCount; i++) {
            $('tr:nth-child('+ i +')').hide(300); 
        }                            
    });
    
    $('#song-show').click(function() {
        rowCount = $('.songs-table tr').length;
        MaxCntr = forStarter + rows2display;
    
        if (forStarter<=$('.songs-table tr').length) {
            for (var i = forStarter; i < MaxCntr; i++) {
             $('.songs-table tr:nth-child('+ i +')').show(200);
            }
            forStarter = forStarter + rows2display
        } else {
            $('#song-show').hide();
        }
    });
    
    $('#album-show').click(function() {
        rowCount = $('.album-table tr').length;
        MaxCntr = forStarter+rows2display;
    
        if (forStarter <= $('.album-table tr').length) {
            for (var i = forStarter; i < MaxCntr; i++) {
             $('.album-table tr:nth-child('+ i +')').show(200);
            }
            forStarter = forStarter + rows2display
        } else {
            $('#album-show').hide();
        }
    });
    
    var rowCount = $('.spotify-table tr').length;
    for (var i = $('.spotify-table tr').length; i > rows2display; i--) {
        rem=rem+1
        $('.spotify-table tr:nth-child('+ i +')').hide(200);
    }
    
    forCntr = $('.spotify-table tr').length - rem;
    forStarter = forCntr+1```

The issue here is, you’re asking about how to “abstract” the functionality, but you’re hardwiring in class names and variable names. How about this approach:

  1. create a class, call it .is-hidden, with a display: none;. Use this for toggling shown/not shown.
  2. for each table, hide all rows by assigning them that class, then remove it from the first N rows, rendering them visible.
  3. For each table, wire the “Show more” link to find all rows in the current table that are visible, and turn the first N rows in that set visible.
  4. If there are no more rows in the current table with the .is-hidden, then give the “show more” the class of “.is-hidden”, hiding that.

Taking this approach, the only variables we really need are the show_num, and the references to the tables and to the show more buttons. Everything else is being pulled from those table rows directly, thus making each of them not only indpendent of each other, but also independent of any outside variable information.

To see it in action… https://codepen.io/snowmonkey/pen/bGddRop?editors=0101