DataJS, which is the JavaScript library for data centric web application from Microsoft released a major version – V1 on Jun 29 2011. Kudos to DataJS team to have achieved this great moment.

image

One notable change in DataJS codeplex site is the documentation. The help topics have been streamlined and now boast a rich set of example/sample codes. At this moment totally there are 7 samples available. They are:

Today lets take a deep dive inside the first example “Read Data Sample”.

Prerequisites:

From the “Read Data Sample” documentation page download the “sample.htm”. Yes the demo code is just a single HTM file.

Next you need to download the datajs library from the downloads page: http://datajs.codeplex.com/releases/view/69267. There are 2 versions available – a minified and a non minified version. Download the sample and the datajs library to a folder on your system

About the Sample:

This sample uses OData feed from one of my favourite company namely Telerik. Telerik TV is a site where Telerik hosts webcasts for all of their products i.e. a dedicated video library for all of the Telerik Products. This video library data is available as a Open Data for public consumption. Here is the OData feed for the same: http://tv.telerik.com/services/odata.svc/. This exposes the following collection:

  • Libraries – List of product libraries that can be browsed
  • Series – Video series on different products that can be browsed
  • Tags – Tag list that can be browsed
  • Videos – List of all the videos that can be browsed

The UI is quite simple. We have a textbox which accepts a search string and searches the Videos collection and displays the results. Here is the screenshot of the same:

image

Inside the Code:

First lets look at the necessary scripts required for the page to work. We need JQuery and DataJS libraries. JQuery is referenced from the ASP NET CDN. DataJS will be pointed to the same directory where the HTM page is. Assumption is you have already done the pre requisite. Here is the script section:

   1:  <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js"></script>
   2:  <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
   3:  <script type="text/javascript" src="datajs-0.0.4.min.js"></script>

Next, lets look at the UI code. Interesting part is that of the text box and the click event handler of the button.The textbox is a standard HTML INPUT element of type TEXT. The results area is a DIV element. Here is the code for the same:

   1:  <input id="searchBox" value="HTML" />
   2:  <button id="searchButton">Search</button>
   3:  <div id="resultsArea"></div>

Next, lets dive into the JQuery code that binds the search button click event. If you are not familiar with JQuery then just stop reading this and head over to jquery.com and get a basic overview of what is JQuery is all about. Here is the click event binding:

   1:   $("#searchButton").click(function () {
   2:  //Rest of the code
   3:  });

Now lets look at the logic to search the odata feed based on the search string entered. First thing we do is grab the string entered from the search textbox and break it into words. Here is the code:

   1:   var phrase = $("#searchBox").val();
   2:  // Break into words.
   3:  var re = /\b(\w+)\b/g;
   4:  var words = phrase.match(re);

If we find any words entered, then we go ahead and build the request URI. In OData world, the way to search is by making use of the $filter clause. The $filter clause allows us to put WHERE clauses on the data set. In this example what we are trying to do is search the “Description” field for occurrence of the text entered in the search box. We make use of the string function “substring”. Here is the syntax of substring function:

image

As you can see, the first parameter is the string to search for, and second parameter is the string in which the search string should be searched for. The return value of the function is boolean meaning it will let us know if the search string was found or not. In our example, for each word in the search string we build substring function and use the AND condition to join them. Meaning if 2 words are entered as search string then we want to get back all those videos which contain both of the word in the description and return that video details. Now lets look at the code:

   1:  // Root URI for the service.
   2:  var serviceUri = "http://tv.telerik.com/services/odata.svc/";
   3:  // Create the URI by adding a filter and selecting only
   4:  // the properties we care about.
   5:  var requestUri = serviceUri + "Videos?" +
   6:                  "$select=Name,Description,ImageUrl,Url&" +
   7:                  "$top=50&" +
   8:                  "$orderby=DatePublish%20desc&" +
   9:                  "$filter=";
  10:  $.each(words, function (key, word) {
  11:                  if (key) requestUri += "%20and%20";
  12:                  // The word will go as an OData literal, so double any single quotes.
  13:                  word = word.replace(/'/g, "''");
  14:                  // We're building a URI, so escape the value.
  15:                  word = encodeURIComponent(word);
  16:                  requestUri += "substringof('" + word + "', Description)";
  17:              });
In line number 5 we start building the URI. Line number 6 set the column to be selected using the $select clause. Line number 7 sets the number of records to fetch from the dataset by using the $top clause. Line number 8 sets the order by on the data set using the $orderby clause. From line number 9 to 17 we build the $filter clause
Now that we have the URI built up, what’s left is to make the call, retrieve the data and paint the UI. Here is the code for the same:
   1:   OData.defaultHttpClient.enableJsonpCallback = true;
   2:              OData.read(requestUri, function (data) {
   3:                  $("#searchResultsTemplate").tmpl(data).appendTo("#resultsArea");
   4:              }, function (err) {
   5:                  $("#resultsArea").text(JSON.stringify(err));
   6:              });

The code makes use of the “read” API method to access the OData feed. We pass in the URI, a success call back and an error call back. In line number 3 notice the usage of JQuery templating feature. What’s cool about JQuery templates is that, you make a UI block and mark it as a template and the JQuery templating feature allows you to use this over a record list without the need to loop and build the UI. What it also provides is the capability of data binding through the use of ${<column name>} syntax. Here is the template that has been defined for this example:

   1:  <script type="x-jquery-tmpl" id="searchResultsTemplate">
   2:  {{each results}}
   3:  <div class='resultBox'>
   4:  <div><span class='resultName'>${$value.Name}</span></div>
   5:  <table><tr>
   6:    <td valign='top'><a href="${$value.Url}"><img border="0" src="${$value.ImageUrl}" /></a></td>
   7:    <td valign='top'>${$value.Description}</td>
   8:  </tr></table>
   9:  </div>
  10:  {{/each}}
  11:  {{if __next}}
  12:  <div class='moreBox'>More results are available - try refining your query.</div>
  13:  {{/if}}
  14:  </script>

Notice line number 11. Remember that we had set the number of records to pick was 50 through the use of $top clause. Suppose the search string produced more than 50 records what OData service does is, it returns the 50 records and puts a “__next” token in the payload. So here we are just checking for the presence of that and output a message if we find it. Voila, we have a completely working

Final Thoughts:

What we learn from this sample, as the datajs team has it on the documentation, are:

  • Using datajs with jQuery and jQuery templates.
  • Building a URI to customize a read request: asking for specific properties, searching for keywords, sorting the results.
  • Reading data through datajs and handling success and error cases.

Hope this post was helpful in understanding the sample. Intention of the post was to just highlight the different points of the sample.

Till next time, Happy Coding. Code with passion, Decode with patience.