Home > Computers and Internet > Endless / Infinite Scrolling using jQuery and .Net MVC

Endless / Infinite Scrolling using jQuery and .Net MVC


There is no need to rant here, because I got that out of the way in the previous post.  THIS is PURE code and examples.

Some background…  I had old school page controls on my website, because I wanted something to work and I didn’t want to have to figure out HOW to do this fancy scrolling thing that all the new kids were doing.  So it worked for a while, but then people started using my site…   Shameless plug: www.CheckOutMyStuff.net

So if you’ve made it to this page, most likely I’ve directed you to it because the Word Press search meta data haven’t been that great.  Plus, I don’t have the clout to post on StackOverflow.com, because I DON’T BLOG much. This has been addressed in the previous post/rant.

Since I want to keep this simple I’ll start from the bottom up since the tinier morsels are at the bottom and the grand finale Java Script is at the top.  I also expect that you
already have an MVC project up and ready to go.  This blog post does NOT go over how to create a .Net MVC project.

The Java Script code is pretty generic so it could be used to query ANY endpoint that returns JSON.

Ground Floor / Data Model

Let’s say you have some data you want to display in on your page.  You will need a model object so it can be displayed, and you’ll probably have quite a few since you want to scroll
them.  I have a “Stuff” model where most of the data I want to display and Id is used for building links, etc.

namespace SM.COMS.Models

{

       public class InfiniteScrollingStuff

       {

              public InfiniteScrollingStuff() { } 

              public string Description { get; set; } 

              public string FullName { get; set; } 

              public string Id { get; set; } 

              public string ImageUrl { get; set; }

       }

}

The Pipes / Returning The Data

The controller code is posted below.  Note that this is just a sample and the code is manufacturing the data, versus retrieving it from a database (that is left as an exercise for the reader).  Put your constants at the top of the controller or wherever you put them.  I chose values as multiples of 4 because I have some complex code that will split them up in the bootstrap rendering.

private const int INFINITE_SCROLLING_BATCH = 16;

private const int INFINITE_SCROLLING_INITIAL = 32;

[HttpGet]

public ActionResult GetPagedResults2(int lastRowId, bool isHistoryBack)

{

    // If “back” to this page, then don’t skip anything.

    var toSkip = isHistoryBack ? 0 : lastRowId;

 

    // If “back” to this page, then Take() ALL.  Otherwise Take() the page amount

    var toTake = isHistoryBack ? (lastRowId == 0 ? INFINITE_SCROLLING_INITIAL : lastRowId)

                 : (lastRowId == 0 ? INFINITE_SCROLLING_INITIAL : INFINITE_SCROLLING_BATCH);

 

    // Most likely you’ll have your context and the table here

 

    //var data = _data.StuffAndThings.Skip(toSkip).Take(toTake);

 

    // Then you’ll map your data to the model.

 

    // In this case we’ll just create some dummy data really FAST.

 

    var modelData = new List<InfiniteScrollingStuff>();

 

    for (int counter = 0; counter < 500; counter++)

    {

        modelData.Add(new InfiniteScrollingStuff

                 {

                     Id = Guid.NewGuid().ToString(),

                     FullName = $”Test Full Name {counter},

                     Description = $”Test Description {counter},

                     ImageUrl = $”/images/image{counter}.png”

// Of course this image will render as broken since not on your server.

                  });

    }

 

    // You could create a smaller set of data for testing and return the same thing over and over to build out your rows on the client.

 

    var result = modelData.Skip(toSkip).Take(toTake);

 

    return Json(result, JsonRequestBehavior.AllowGet);

}

A Room – With The View

Your view code will be very simple.  Probably just a title and then the data you want to be formatted.  NONE of the formatting will be done in the view.  The formatting will be done later in the Java Script code that requests the data.  The last “div” tag is a placeholder for the data that will be requested when the view is loaded and upon scrolling.

<input type=”hidden” id=”lastRowId” value=”0″ />

<div class=”row”>

       <div class=”col-sm-6″>

              <h2>@ViewBag.Title</h2>

       </div>

</div>
<div id=”infiniteScrollingData”></div>

The Coffee Table – Set Your Java Script Here

You COULD put your Java Script code within <script> tags inside your view, but that makes it harder to REUSE.  Possibly in ANOTHER blog I’ll show how you can reuse this generic Java Script code to adjust itself based on which view is being used.  REMEMBER, hidden fields can hold data, but they can ALSO hold CODE too.

// —-==== For Infinite scrolling page. ====————————————————-

 

var inCallback = false;           // Prevent multiple retrievals of the same data recursion

 

// Get default data…

$(document).ready(function () {

     GetDataForInfiniteScroll(false);

});

 

// Get next page of data on scroll

$(window).scroll(function () {

     if ($(window).scrollTop() == $(document).height() – $(window).height()) {

          GetDataForInfiniteScroll(true);

     }

});

 

// Data retrieval method

function GetDataForInfiniteScroll(scrollPage) {

 

    if (inCallback == true) {

        // Bust out of the possible multiple calls to this while the callback is attempting to return data.

        return;

    }

 

    inCallback = true;

 

    var lastRowId = ($(“#lastRowId”).val() * 1);

 

    // If there is no lastRowId text field then don’t make the request.

 

    if (isNaN(lastRowId)) {

         inCallback = false;

         return;

    }

 

    var isHistoryBack = (lastRowId > 0 && !scrollPage);

 

    var requestUrl = ‘/ViewData/GetPagedResults’ + ‘?lastRowId=’ + lastRowId

+ ‘&isHistoryBack=’ + isHistoryBack;

 

    $.ajax({

        type: ‘GET’,

        url: requestUrl,

        dataType: ‘json’,

        success: function (jsonData) {

            var rowid = lastRowId;

 

            if (jsonData == null) {

                inCallback = false;

                return;

            }

 

            var literalHtml = ;

 

            $.each(jsonData, function (index, item) {

 

                 literalHtml += ‘<a class=”btn-link” href=”/stuff/detail/’ + item.Id + ‘”>’

                             + ‘<img class=”img-responsive” src=”‘ + item.ImageUrl + ‘” /></a>’

                             + ‘<h4>’ + item.FullName + ‘</h4>’;

 

                 rowid++;

            });

 

            $(‘#infiniteScrollingData’).append(literalHtml);

 

            if (!isHistoryBack) {

                $(“#lastRowId”).val(rowid);

            }

 

            inCallback = false;

            },

            error: function () {

                inCallback = false;

                //alert(‘Error’);

         }

     });

 

     return false;

}

Sit Back And Relax…

HOPEFULLY you’ve hooked this all up into an existing project and it’s working well for you.  Granted, your mileage may vary and I don’t make any claims that these snippets are
ABSOLUTELY bug free.  Please feel free to post comments if I have made your life easier or I have screwed up somewhere.  THANKS!  Don’t bother subscribing to this blog because it will probably be ANOTHER year before I post another one.  Or do, and you’ll be in for a treat ONCE a year.  At least it won’t be too much noise.  😉

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: