Search code examples
javascriptjquerycssajaxadaptive-design

pagination depending on window size - approach to find number of items per page


Sorry for being long and thank you very much for your usual time and guidance.

I have a div of unknown dimensions; in fact, its width and height are set using percentages so the final values in pixels depend on the window innerWidth an innerHeight properties.

I need to create an ajax pagination inside that div. In other words, I have two child div s (figure below). The second one is for pagination links. The first one is responsible of holding items (aligned horizontally and vertically). It will be (automatically) of unknown width . As a result, the number of items inside depend on its final width and height because all items have a fixed known width and hieght (Let's say 80 pixels width and 50 pixels height).

I hope the following figure is illustrating my issue in the best manner: enter image description here

The goal is to find a good approach to find the values of X and Y.

  • X= number of items per row
  • Y= the number of items per column

These two values will help finding the number of items per page (to be used server side for pagination). Pagination links will be created by dividing the total number of pages by this value. Note: Everything is done with ajax.

What I am planning to do:

  • create a javascript function calculate_viewport() to be the first thing to execute before any other thing parsed/exectued.
  • create a javascript function that calculates X and Y values based on values returned by calculate_viewport().
  • use the X and Y for an ajax call that request a certain page.

    <script type="text/javascript">
    
    function calculate_viewport() {
        var width_and_height_object;
        // calcluate width and height using of current window.innerWidth  and window.innerHeight
        // put values in an object width_and_height_object
        return width_and_height_object; }
    
    function calculate_XandY(width_and_height_object) {
        var XandY_object;
        // calcluate X and Y values by perfoming necessary division operations
        return XandY_object; }
    
    var XandY = calculate_XandY(viewport()); </script>
    
    <!DOCTYPE html> <html>
        <head>
        </head>
        <body>
            <div id="parent" style="height: 70%; width: 50%">
                <div id="items_container" style="height: calc(100% - 30px); width: 100%"></div>
                <div id="pagination" style="height: 30px; width: 100%">></div>
            </div>
        </body>
        <script src="jquery.js"></script>
        <script type="text/javascript">
                $('a.next a.previous').click(function(e){
                     e.preventDefault();         
                     $.ajax({
                        type: "GET",
                        url: url_to_page_of_items,
                        data: { number_of_items_per_page : X_times_Y },
                        cache: false, 
                        success: callback // append result to items container div 
                     });        
               return false;
            });
        </script> </html>
    

What do you think about this approach? Are there any other better ways to achieve this goal? Is it acceptable to create a <script> tag before the <html> tag just to make early window size calculation?

N.B: For the server side part, I manage to paginate results via some functions offered by the ORM library I am using. I use a server-side template engine that renders a page of items as HTML. I am ready to provide any code upon request for this part. Thanks


Solution

  • You'll never get the layout math right on your own. My recommendation is to lay out all of the items before hand (flex box is ideal here!), get the count, and then fill them in using ajax.

    Here's a quick demo I whipped up. The actual JS is pretty simple, using jQuery.

    var MARGIN = 10; //This should match your CSS
    
    var itemContainerHeight = $(".foo").height();
    var count = 0;
    
    $(".item").each(function () {
      if ($(this).position().top + $(this).height() + MARGIN > itemContainerHeight) {
        $(this).hide();
      } else {
        count++;
      }
    });
    
    $('.pagination').text("I can display "+count+" items!");
    

    The important line is the one containing .position(). That'll get the location of each of the items top edge, add the height to find their bottom edge, and check if it's past the bounds of the item container.

    After this you can just use the count to query the necessary items from the server. I'd also recommend using visbility: hidden; on all of the items so the user doesn't see them before they're ready.