Releasing “Netflix Catalog using HTML+ODATA+DATAJS+JQUERY”

I am delighted to share the information that i have released my first ever project on CodePlex. Yes i have released a small application to the community which can be used as a reference application to play around some of the buzzing technology like OData and frameworks like Jquery and DataJS. So read on to know the details.

What is “Netflix Catalog using HTML + ODATA + DATAJS + JQUERY” ?

Ever since i have read about the Open Data Protocol or OData as it is popularly known as, i have have taken keen interest in knowing this technology. I have been speaking on OData, WCF Data Services and related things in our community UG meets and at tech events. You can find all about OData at http://wwww.odata.org

OData has SDK for almost all the platforms at this point. One such SDK was for PHP. The SDK comes with a samples/demo code. One of the sample is known as “PHP-Netflix-Demo”. The demo is pretty simple and has the following features:

  • Uses Genres collection to list Genres in the demo
  • Uses Languages collection  to list Languages in the demo
  • Uses Titles collection to search by name or browse by Genre or browse by Language and list the movie title

I looked at the demo and i said to myself i need to port this to HTML + Jquery demo. My objective was to port the whole app as is and it may serve as  a reference app for somebody who wants to learn OData things. At the time i started a new awesome wonderful JavaScript library or framework was pushed out from Microsoft called “datajs” http://datajs.codeplex.com. The app would have been incomplete if i had not incorporated the library. It abstracts most of the stuff from the developer and provides simple API methods for reading/writing OData feeds. It also has a Caching and Sorting API inbuilt.

So Netflix Catalog is a single page application which allows you to browse Netflix catalog based on Genre/Language/Name and browse the titles.

What Technologies are used in the application?

Initially when i started i had in mind only HTML + JQuery. But with datajs released at the same time, included the same. Here is the technologies/frameworks used in building the app:

  • HTML – the front end is just a single HTML page index.html. Nothing else
  • JQuery – have used the following plugins for the client side DOM processing
    • Templating – a Jquery based template engine for dynamic UI generation
    • Raty – a Jquery based rating plugin used for generating the Rating stars for each movie
    • Corners – a Jquery based div corner rounding plugin
    • Center – a Jquery based element centering plugin

  • DataJS – a new JavaScript based library for easy accessing of OData feeds for read and write.

How does app look like ?

I have hosted the app at the following URL – http://netflixcatalog.99on.com. You can have a look at the live version. Here are couple of screen shots of the application:

Here is the Search Panel:

NetflixCatalogSearchPanel 

Here is the Movie Listing:

NetFlixMovieDisplay

Lets look at how the application was developed in the next section.

How did i develop the application?

To start out with lets look at the file system of the application:

NetflixCatalogFileSystem

That’s all it is there to this. Images folder – contains some helper images, Scripts folder – contains all the scripts necessary for the client side processing, Styles folder – contains the style sheet for the application. And then the main ingredient of the application – index.html. The application is a single HTML page which is divided into 2 sections. As seen in the screen shot i have a search panel and then once search is done we display the movies. Lets look at the sections one by one.

Movie Search Panel:

As seen in the screen shots, movie search panel provides searching movies by Genre/Languages and also you can type in a name and search by that. Also you can just browse the whole Movies collection and also TV shows collection.

The Genres and Languages are all coming from the Netflix Genre Collection and Language Collection. Here is the Genre Collection OData URL – http://odata.netflix.com/catalog/Genres. Similarly the Languages Collection OData URL is -  http://odata.netflix.com/catalog/Languages

One interesting concept i was able to achieve here was Caching these collection on the client side. Thanks to DataJS library which has an inbuilt caching provision, when the page is visited for the first time in a session, genres and languages are all cached. Here is the code for the same:

First i prepare the Genre cache as below:

   1:  var genreCache = datajs.createDataCache({
   2:                                          name: "genres",
   3:                                          source: MOVIE_GENRES_URI,
   4:                                          prefetchSize: -1
   5:                                      });

 

The  read through a range by mentioning the which page to read and how much to read as below:

   1:  genreCache.readRange(0, genreCount).then(FillGenresCallBack, ErrorCallBack);

After this the genres are all cached on the client side. No more going over the network for next time.

The languages are also cached on the similar fashion to that of genre.

When a user selects a genre or language or name, we build the following URL and fire at Netflix:

Movie listing by Genre:

http://odata.netflix.com/Catalog/Genres(‘Action)/Titles?$orderby=ReleaseYear desc,Name asc

Notice that we are asking for titles where Genre = Action.

Movie listing by Language:

http://odata.netflix.com/Catalog/Languages(‘Hindi’)/Titles?$orderby=ReleaseYear desc,Name asc

Notice that we are asking for titles where Language = Hindi.

Movie listing by Name:

http://odata.netflix.com/Catalog/Titles?$filter=startswith(Name,’Mission’)&$orderby=ReleaseYear desc,Name asc

Notice that we are asking for titles where Name startswith ‘Mission’.

All the titles are ordered by descending order of the Release Year and ascending order of the Title name.

Movie Listing:

As seen in the previous section different URL are built based on the user action. Again i am making use of DataJS caching feature to cache the titles. When the URL is built based on the user action, the following cache is built:

   1:  if(moviesCache != null)
   2:          moviesCache.destroy();
   3:   
   4:      moviesCache = datajs.createDataCache({
   5:      name: "movies",
   6:      source: uri,
   7:      pageSize: pageSize,
   8:      prefetchSize: 10,
   9:      });

 

Notice carefully that i am specifying what the pagesize of the cache is. Also notice the option “prefetchSize”. This is a little gem that datajs team has provided within the framework. What it does is, as the name goes by, pre-fetches the data and caches it. For e.g. lets say i have a pagesize set to 10 and i am giving prefetchsize as 10, so initially the caching framework brings in 20 – the first page worth 10 records and a prefetch size of 10 more records. So when user clicks on Page 2, the experience is as if the data is being fetched from local. But when he clicks on Page 3 the caching framework is smart enough to go and grab next 10 records + it pre fecthes 10 more in the background and this continues till all the records are fetched. Then you have the whole collection cached out and user can go back and forth without seeing any delay as no network call is made.

I am using Jquery templating technique to generate the movie listing divs. i have created a text file called moviedisplay.txt and kept it in scripts/template folder. Here is the code which uses the templating engine to loop through the titles collection and render the markup based on the template.

   1:  moviesCache.readRange(startIndex, pageSize).then(FetchTitlesCallBack);
   2:   
   3:  function FetchTitlesCallBack(data) 
   4:  {
   5:   $.get('/scripts/templates/moviedisplay.txt', function (template) 
   6:   {
   7:     $.tmpl(template, results, 
   8:     {
   9:      runtime: function () 
  10:      {
  11:         var runTime = this.data["Runtime"];
  12:         if (runTime == null)
  13:           return "N/A";
  14:         else
  15:           return GetRunTimeInMinutes(runTime);
  16:      }
  17:    }).appendTo('#movieListingContainer');
  18:    }
  19:  );
  20:  }


Notice tmpl() method of the templating engine which does all the magic. We are feeding it a template and results to loop through and ask it to append the result to movieListingContainer. That’s the magical power of Jquery and its ecosystem.

here is how my template for movie display looks like:

   1:  <div id='moviesDiv'>
   2:      <div class='movieTitleCard'>
   3:          <div class='movieName'>${Name}</div>
   4:          <span class='movieReleaseYear'>${ReleaseYear}</span>
   5:          <span class='movieRating'>${Rating}</span>
   6:          <span class='movieRuntime'>${ $item.runtime() }</span>
   7:      </div>
   8:      <div style="padding: 2px">
   9:          <table>
  10:              <tr>
  11:                  <td><img src='${BoxArt.LargeUrl}'></td>
  12:                  <td valign="top">
  13:                      <div class="movieSynopsis">${Synopsis}</div> 
  14:                      <br/>
  15:                      <table>
  16:                          <tr>
  17:                              <td><div id="movieratingdiv${Id}" class="rating"  avgrating="${AverageRating}"></div></td>
  18:                              <td><span class="movieAverageRating">${AverageRating}</span></td>
  19:                              <td><span >Member Average</span></div></td>
  20:                          </tr>
  21:                      </table>
  22:                  </td>
  23:              </tr>
  24:          </table>
  25:      </div>
  26:  </div>
  27:  <br/>

Notice the place holder for data insertion. Anything with ${} notifies the templating engine to find that field in the results and replace the value in the template.

And that’s how i was able to achieve this application. I am happy the way it has turned out. Of course there are many more small pieces which i have not outlined. If you go through the source code you will come to know what is happening very easily.

The whole of the java script is inside Netflix.js in the scripts folder. All function names are self explanatory and can be easily understood as to what’s their intent. I haven’t followed any OO programming model in the JS side. My whole intention was to prove the fact that ODATA + DATAJS + JQUERY is an awesome deadly combination to quickly build a full fledged application with minimal effort.

The project is currently hosted on CodePlex. Here is the URL for the same: http://netflixcatalogdatajs.codeplex.com/. The project is released under MIT license meaning you can go ahead use the source code for your needs. Also you can browse the live version at http://netflixcatalog.99on.com.

Go ahead and give it a spin and if you have any suggestions or comments, you can contact me either on codeplex or here. This has been a milestone in my career. Hope i will be able to contribute more to the community in coming days.

As usual till next time – Happy Coding. Code with Passion, Decode with Patience.

  • Dhinesh Kumar

    Hello Lohith

    Can you please show us a demo that describes the add, update, delete using OData.request

    Best regardsDhinesh Kumar

    • http://kashyapas.com Lohith

      Hi

      Writing a blog post on that now. Expect the article soon :) thanks for dropping by and your comments.

  • Dhinesh Kumar

    Hello Lohith

    Can you please show us a demo that describes the add, update, delete using OData.request

    Best regardsDhinesh Kumar

  • Dinu_3gee

    Hello Lohith

    Can the similar CRUD datajs operations are possible using mobile emulators?

    regards
    Dhinesh Kumar

    • http://kashyapas.com Lohith

      Hi Dhinesh

      Havent tried it. let me work and that and come back to you.