Showing posts with label jQuery. Show all posts
Showing posts with label jQuery. Show all posts

Sunday, 29 September 2013

Using jQuery Mobile Table Options With ASP.NET GridView

I think many of you are aware of the FriendlyUrls feature added to ASP.NET Web Forms 4.5. It is available by default with Visual Studio 2012 if you have installed Web Tools update 2012.2 or later and it is available by default in Visual Studio 2013 RC as well. FriendlyUrls makes URLs of the web forms application friendly and it enables the option of creating views for mobile devices as well. In the pages specific to mobile devices, we can use the front-end mobile frameworks like jQuery mobile or Sencha Touch.

The default ASP.NET Web Forms template contains an optimized master page for mobile view, Site.Mobile.Master. This will be the default master page for all mobile specific pages.

Using front-end frameworks with server control is a bit tricky, but it is possible to use. In this post, we will see the way to use jQuery mobile’s table options with ASP.NET GridView.

Let’s make the server control ready. In the mobile page, add a GridView and bind data to it. Following is the mark-up of the GridView and the Select method that binds data from Customers table of Northwind database:


<asp:GridView runat="server" ID="gvCustomers" SelectMethod="GetCustomers"></asp:GridView>

public IQueryable GetCustomers()
{
    NorthwindEntities ctx = new NorthwindEntities();
    return ctx.Customers.Take(10).Select(c => new { c.ContactName, c.CompanyName, c.City, c.Phone, c.Region });
}

I chose 5 properties to make the output simpler. The page should contain the view port metadata tag and the scripts and styles needed for jQuery mobile.
<meta name="viewport" content="width=device-width" />
<link href="Content/jquery.mobile.theme-1.3.2.min.css" rel="stylesheet" />
<link href="Content/jquery.mobile.structure-1.3.2.min.css" rel="stylesheet" />
<link href="Content/jquery.mobile-1.3.2.min.css" rel="stylesheet" />
<script src="Scripts/jquery-1.8.2.js"></script>
<script src="Scripts/jquery.mobile-1.3.2.js"></script>

The root div in the Site.Mobile has to be marked with data-role attribute to make jQuery mobile act on the content contained in the page.
<form id="form1" runat="server">
    <div data-role="page" id="home">
        <!-- Rest of the default mark-up -->
    </div>
</form>

Let’s make the GridView appear as the table in the demo on the jQuery Mobile site, so that the user will have an option to see some of the less necessary columns only when they are needed. To enable them, the GridView should be rendered as a table with thead and tbody. This can be done by setting the TableSelection property of the header row after data is bound to the GridView as shown below:
protected void gvCustomers_DataBound(object sender, EventArgs e)
{
    gvCustomers.HeaderRow.TableSection = TableRowSection.TableHeader;
}

To make the rendered table look like table in the demo on jQuery mobile site, following client properties have to be applied on the table:

  • Some CSS classes have to be applied on the table
  • data-role and data-mode attributes on the table
  • data-priority attribute on less important columns

These properties can be set in the DataBound event of the GridView. Add the following statements to the DataBound event of the GridView:

gvCustomers.CssClass = "ui-responsive table-stroke";
gvCustomers.Attributes.Add("data-role", "table");
gvCustomers.Attributes.Add("data-mode", "columntoggle");

var headerCells = gvCustomers.HeaderRow.Cells;
headerCells[3].Attributes.Add("data-priority", "2");
headerCells[4].Attributes.Add("data-priority", "2");

With this, we are done with applying the required settings. Load the page on a mobile emulator; it should look as shown below:




Happy coding!

Sunday, 8 September 2013

Restricting Number of Suggestions in jQuery UI Auto Complete Using Underscore.js

jQuery UI’s autocomplete widget can be used with an array of objects or we can take complete control with by defining a function that emits the list of suggestions to be displayed. Restricting the count of suggestions to a given number is slightly tricky. There are several ways to skin this cat. In this post, we will see one of the ways to achieve the same using Underscore.js.

To make the number of suggestions configurable, a data- attribute can be used.

<input type="text" id="txtName" data-count="5" placeholder="Your name..." />

We need to define a source function to take control over suggestions to be displayed and filter data from the collection using underscore.js and value of the data-count attribute on the element. The source function should perform the following tasks:
  • Select a list of entries from the collection that contain the term entered using _.filter() function
  • Take first n(n being value of data-count attribute) entries from the filtered list using _.take() function
  • Pass the values selected in step 2 to response

var names=["Alex", "Andrew", "Andrea", "Anna", "Abbie", "Abraham", "Aisha", "Albert", "Albina", "Alisha", "Barbie", "Bailey", "Barton", "Bernardo", "Blaise", "Bobbie", "Blossom", "Brianna", "Buddy", "Byron", "Caesar", "Caleb", "Celicia", "Chalmer", "Chandra", "Cindi", "Clarence", "Codie", "Corey", "Cyrus"];
var textBox = $("#txtName");
textBox.autocomplete({
    minLength: 2,
    source: function(request, response){
        var filteredNames = _.take(_.filter(names, function(name){
            return name.toLowerCase().indexOf(request.term.toLowerCase()) != -1;
        }), textBox.data("count"));
        response(filteredNames);
    }
});

You can play with the sample on jsfiddle.


Happy coding!

Monday, 26 August 2013

Consuming Web API OData From .NET And JavaScript Client Applications

In last post, I created a Web API OData service that performs CRUD operations on an in-memory collection. In this post, we will consume the service from a .NET client and a web page.

Consuming Web API OData using a .NET client:

A Web API OData service can be consumed using WCF Data Services client. If you gave already worked with WCF Data Services, you already know about consuming Web API OData Service as well.

Right click on a .NET project and choose the option Add Service Reference. In the dialog, enter the OData service URL and click the Go button.



The dialog parses the metadata received from the server and shows the available entities under container as shown in the screenshot. As we created just one entity in the service, we see the entity Employee alone. Name the namespace as you wish and hit OK. Visual Studio generates some classes for the client application based on the metadata.

The generated code contains the following:

  1. A Container class, which is responsible for communicating with the service. It holds DataServiceQuery<TEntity> type properties for each EntitySet on the server
  2. A class for every entity type. This class contains all properties mapped on the server, information about key of the entity

A Container is much like a DbContext in Entity Framework. It handles all the operations. Container is responsible for building OData URLs and sending requests to the service for any operation that client asks for. Let’s start by creating a Container. Constructor of the container accepts a URI, which is base address of the Web API OData service.

Container container = new Container(new Uri("http://localhost:1908/odata"));


To fetch details of all employees, we need to invoke the Corresponding DataServiceQuery property.


var employees = container.Employees;

Although the statement looks like an in-memory operation, it generates the corresponding URL internally and calls the server. Similarly, to get details of an employee with a given Id, we can write a LINQ query as shown:

var employee = container.Employees.Where(e => e.Id == 3).FirstOrDefault();

The above query makes a call to the Get method accepting key in the Web API Controller.

To create a new employee, we need to create an object of the Employee class, add it and ask Container to save it. Following snippet demonstrates this:


Employee emp = new Employee() { Id = 0, Name = "Hari", Salary = 10000 };
container.AddToEmployees(emp);
container.SaveChanges();

Performing update is also much similar. The difference is with calling the SaveChanges method.

emp = container.Employees.Where(e => e.Id == 3).FirstOrDefault();
emp.Name = "Stacy";
container.UpdateObject(emp);
container.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);

If SaveChanges is called with SaveChangesOptions.ReplaceOnUpdate, it performs PUT operation on the resource. If SaveChangesOptions.PatchOnUpdate is passed, it performs PATCH operation on the resource.

To delete an entry, we need to pass an object to DeleteObject method and just like earlier cases; we need to call the SaveChanges method on the Container.


container.DeleteObject(container.Employees.Where(e => e.Id == 3).FirstOrDefault());
container.SaveChanges();


Consuming Web API OData using JavaScript client:

To consume the Web API OData service from a web page, the service has to be called using AJAX. The client can send an AJAX request to the URL of the OData service by specifying an HTTP verb to operate on the resource. To make our life easier, let’s use jQuery for AJAX calls.

To get details of all employees, we need to send a GET request to the OData URL. Values of entries in the collection are stored in a property named value in the object received as response. Fetching details of an employee with a given Id also follows similar approach. Following snippet demonstrates this:


$.getJSON(“/odata/Employees”, function(data){
    $.each(data.value, function(){
        //Modify UI accordingly
    });
});

$.getJSON(“/odata/Employees(3)”, function(data){
        //Modify UI accordingly
});


To add a new employee, we need to send the new object to $.post along with the URL.

var employee = {
    "Id": 0,
    "Name": “Ravi”,
    "Salary": 10000
};

$.post(“/odata/Employees”, employee).done(function(data){
    //Modify UI accordingly
});


Unfortunately, jQuery doesn’t have a shorthand method for PUT. But it is quite easy with $.ajax as well. To perform PUT on the resource, the request should be sent to the specific address with an ID and the modified object should be passed with the request.

var employee = {
    "Id": 3,
    "Name": “Ravi”,
    "Salary": 10000
};

$.ajax({
url: "/odata/Employees(" + employee.Id + ")",
       type: "PUT",
       data: employee
});


Building request for DELETE is similar to put, we just don’t need to pass the object.

$.ajax({
url: "/odata/Employees(" + id + ")",
type: "DELETE"
});


Happy coding!

Friday, 8 March 2013

Understanding Promise Pattern in JavaScript Using jQuery’s Deferred Object

Asynchronous programming is used almost everywhere these days. JavaScript is no exception. In rich JavaScript applications, we have to perform several tasks like calling a service using AJAX, caching data, applying animations and some new cases might arise while writing the application.

Irrespective of whether an operation is synchronous or asynchronous, we need a response from the when the operation is succeeded or even when it fails. Synchronous operations are usually enclosed within try…catch blocks to check for errors. As asynchronous operations run in background and we can’t determine when they will complete, their failures cannot be caught by the catch block. Even in case of successful completion, the response won’t be available for the immediate next statement. These cases are handled using callbacks.

We see several patterns in which callbacks are registered. While using raw AJAX invocations with XMLHttpRequest, we assign the callback to onreadystatechange property of the object, as shown below:

var xhr = new XMLHttpRequest();
xhr.open(“GET”,url, true);
xhr.send();

xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if(xhr.status == 200){
     successCallback(xhr.responseText);
        }
        else{
            failureCallback(xhr.responseText);
        }
    }
};

We also see the cases where the asynchronous function accepts a callback function as a parameter.
invokingAsyncFunction(successCallback(data), failureCallback(error));

These callbacks look good unless we have a chain of three or more asynchronous calls. When the number goes up, it becomes difficult to handle them and the code becomes less readable.

We can overcome this difficulty using the Promise pattern. The Promise pattern believes in returning a deferred object that can be used to call a piece of logic when the underlying asynchronous operation is either resolved or rejected. In other words, we can say the pattern promises us that it would send a result when it gets. The result can be data if the operation is successful or details of an error in case of failure.

The deferred object will hold the current state of the asynchronous operation. At any given time, the deferred object will have one of the three states: unresolved, resolved and rejected.

The deferred object would be in unresolved state when it is waiting for the asynchronous operation to complete. Once the operation is completed successfully, it enters resolved state. Otherwise, it enters rejected state.

jQuery library added support of deferred in jQuery 1.5. The library itself uses this feature for implementation of AJAX features.

jQuery’s deferred object makes it easy to write asynchronous code in JavaScript. Following steps must be followed while writing an asynchronous function using deferred object:

  1. Get a deferred object by calling the $.Deferred() constructor
  2. In case of success, call resolve function passing result of the operation
  3. In case of failure, call reject function passing the error details
  4. Return deferred’s promise object, which provides ways to attach callbacks and determine current state of the deferred object

With this understanding, let’s put the above AJAX logic in a function and make it asynchronous using jQuery’s deferred object:
function ajaxCallToAUrl(url){
  var deferred = $.Deferred();    //Getting a deferred object
  var xhr = new XMLHttpRequest();

  xhr.open(“GET”,url,true);
  xhr.send();

  xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
      if(xhr.status==200)
        deferred.resolve(xhr.responseText);  //Calling resolve() in case of success
      
      else
        deferred.reject(xhr.responseText);  //Calling reject() in case of failure
    }
  }
  return deferred.promise();  //Returning the promise object
}

Following are the steps to be followed while calling the above function:
  1. Call the function and store the returned promise in an object
  2. Attach a callback to done() function of promise. It will be called when the deferred object enters resolved state
  3. Attach a callback to fail() function of promise. It will be called when the deferred object enters rejected state

Following snippet demonstrates it:
var promise = ajaxCalToAUrl(url);
promise.done(function(data){
    //Update the UI to bind data obtained
}.fail(function(error){
    //Display the error message
});

The success and failure functions can also be attached to the promise object using then function as well. The then() function accepts three callbacks, first one is for success, second one is for failure and the third one is for handling progress. Failure and progress callbacks are optional. Progress callback is executed when deferred receives a progress notification. Above implementation can be expressed as follows using then function:
promise.then(function(data){
    //Update the UI to bind data obtained
}, function(error){
    //Display the error message
}, function(){
    //Notify user that the operation is in progress
});

Using then(), we can chain multiple operations as well. Following snippet demonstrates chaining:
var secondPromise = firstPromise.then(function(data){
    return callAnotherAsyncFunction(data);     //Assuming the function callAnotherAsyncFunction returns a promise
});

secondPromise.done(function(data){
    //Chained request is successful. Update UI with the data obtained
});
We can also combine multiple requests using $.when(). The when() function accepts multiple deferred objects. It returns a promise object. State of the when function changes to resolved when all the operations are successfully completed. If any of the operation is failed, state of when changes to rejected.
$.when(deferred1, deferred2).done(function(){
    //Logic to be executed on successful execution
}).fail(function(){
    //Logic to be executed upon failure of any of the operations
});

This is a beginning to using promises. jQuery's deferred object offers capabilities to forcefully reject the operation, notify change of status and some other features that we may require in an application.

References:


Documentation on jQuery’s official site about deferred objects
Article about deferred and promise on MSDN ScriptJunkie


Happy coding! 

Monday, 17 December 2012

A Real-time chart using SignalR and Flot

I have discussed about SignalR in some of my earlier posts. I lately found Flot, a jQuery plugin that makes it very easy to create charts on HTML pages without doing a lot of work. Since both SignalR and Flot are based on jQuery at the client end, they work well together. In this post, we will see how to create a chart showing price of a stock that changes every second.


On Server Side

As we are using SignalR, we need a hub class. To represent a stock value object, we need a class with a couple of properties in it. Following is the StockValue class that we will use to send data to client:
public class StockValue
{
    public int Time { get; set; }
    public double Price { get; set; }
}

For this solution, I have used Visual Studio 2012 and SignalR 1.0 RC. There are a number of changes made to SignalR in this version. Following are the changes that we will be using in this post:

Calling a client function from Server: Clients.All.functionName(data);
Calling a server function from client: proxy.server.functionName(data);
Defining a JavaScript client function: proxy.client.functionName(data);

We need a StockMarket class that does the following tasks:

  • Initializes stock values
  • Updates the stock values after certain period
  • Sends the updated data to all clients
Code of this class is as follows:
public class StockMarket
    {
        public static readonly Lazy<StockMarket> market = new Lazy<StockMarket>(() => new StockMarket());
        static List<StockValue> stockValues;
        Timer _timer;
 
        public static StockMarket Instance
        {
            get
            {
                return market.Value;
            }
        }
 
        public void InitializeStockvalues()
        {
            stockValues = new List<StockValue>()
                {
                    new StockValue(){Time=10,Price=10.4},
                    new StockValue(){Time=20,Price=10.5},
                    new StockValue(){Time=30,Price=10.2},
                    new StockValue(){Time=40,Price=10.5}
                };
            GetClients().All.drawChart(stockValues);
        }
 
        public void GenerateNextStockValue(object state)
        {
            Random randomGenerator = new Random();
            int changeInCost = randomGenerator.Next(100, 110);
 
            var lastStockValue = stockValues[stockValues.Count - 1];
            var nextStockValue = new StockValue();
            nextStockValue.Time = lastStockValue.Time + 10;
            nextStockValue.Price = changeInCost / 10.0;
 
            stockValues.Add(nextStockValue);
 
            GetClients().All.drawChart(stockValues);
        }
 
        public void PublishPrices()
        {
            if (stockValues == null)
            {
                InitializeStockvalues();
            }
            else
            {
                GenerateNextStockValue(null);
            }
            _timer = new Timer(GenerateNextStockValue, null, 1000, 1000);
        }
 
        public IHubConnectionContext GetClients()
        {
            return GlobalHost.ConnectionManager.GetHubContext<StockValuesHub>().Clients;
        }
    }

Finally, we need a Hub class to kick off the process on the server. The hub class is very simple as we have assigned most of the responsibilities to StockMarket class.
public class StockValuesHub : Hub
    {
        public void GetStockValues()
        {
            StockMarket.Instance.PublishPrices();
        }
    }


On Client Side

On the client HTML page, we need to add references to following JavaScript libraries:
  • jQuery library
  • SignalR jQuery library
  • Flot jQuery library
  • Reference to SignalR’s dynamic proxy library

Flot requires a div element to render chart. So, let’s add the following div element to our page:

<div id="canvasChart" style="height: 300px; width: 300px;"></div>

On page load, we need to invoke the GetStockValues() function to start the process.
var hub = $.connection.stockValuesHub;
var dataToChart = [];
 
$.connection.hub.start()
    .done(function () {
        hub.server.getStockValues();
     });

We need to define the drawChart function on client to consume the data sent by server and render the chart. It involves a bit of logic as Flot doesn’t operate on JSON data. We need to convert our data to a form that Flot understands.

Flot accepts values in the form of an array. In the API documentation of Flot, it is specified that, Flot accepts values in the form of an array of a series. Following is an example of the data to be passed into Flot (copied from API documentation):

[ [1, 3], [2, 14.01], [3.5, 3.14] ]

Since SignalR sends JSON data, we need to convert the data to above format before we render the chart. Each object in the collection has to be converted to an array with two elements. Following function does this job for us:

function convertToArray(data) {
    var dataArray = [];
    dataArray.push(data.Time);
    dataArray.push(data.Price);
    return dataArray;
}

Finally, let’s add the drawChart function to client proxy. Implementation of this function is pretty straight forward.
hub.client.drawChart = function (data) {
    if (dataToChart.length == 0) {
        $.each(data, function () {
            dataToChart.push(convertToArray(this));
        });
    }
    else {
        dataToChart.push(convertToArray(data[data.length - 1]));
    }
    $.plot($("#canvasChart"), [dataToChart]);
};


You can download the complete code here.

Happy Coding!

Wednesday, 10 October 2012

Creating TypeScript type declaration file for an existing jQuery plugin

Microsoft recently announced a scripting language that compiles into JavaScript. It is known as TypeScript.
TypeScript is super set of JavaScript. Using TypeScript, one can write type safe client side script. If you are not familiar with TypeScript yet, you may checkout the following resources:


Any existing JavaScript library can be used with TypeScript if a type declaration file is created for the library. A type declaration file provides a TypeScript interface to interact with the library. TypeScript team has created the declaration files for jQuery and Node.js libraries.

In this post, we will create a TypeScript declaration file for jQuery-idle Timeout plugin. It is a small plugin which signs off the user if the user didn’t interact with the page for some time. Using this plugin is very easy. Following is an example of the usage:
$(document).idleTimeout({
    inactivity: 5000,
    noconfirm: 1000,
    sessionAlive: 1000,
    redirect_url: 'TimedOut.html',
    click_reset: true,
    alive_url: 'default.htm',
    showDialog: false
});

The above script sets redirects user to the page TimedOut.html if the user didn’t interact with the page for 5 seconds or more.
From the usage of the plugin, it is clearly visible that,

  • The function idleTimeout is invoked using jQuery object
  • The function idleTimeout accepts a set of options
In the source of jQuery-idleTimeout plugin, we see the following assignment statement in the beginning:
var defaults = {
            inactivity: 1200000, //20 Minutes
            noconfirm: 10000, //10 Seconds
            sessionAlive: 30000, //10 Minutes
            redirect_url: '/js_sandbox/',
            click_reset: true,
            alive_url: '/js_sandbox/',
            logout_url: '/js_sandbox/',
            showDialog: true
        }

From here, we get to know the list of configurable options. As TypeScript is strongly typed, we need to define an interface to hold the above properties. One important thing to remember here is that, the fields should be made nullable in the interface.  

The interface can be as follows:
interface JQIdleTimeoutSettings {
    inactivity?: number;
    noconfirm?: number;
    sessionAlive?: number;
    redirect_url?: string;
    click_reset?: bool;
    alive_url?: string;
    logout_url?: string;
    showDialog?: bool;
    }


The function idleTimeout is invoked using a jQuery object. In the declaration file of jQuery, an interface is defined to hold all functions which have to be invoked using jQuery objects. Name of the interface is JQuery.

We shouldn’t modify the source of jQuery’s declaration file to add the idleTimeout function. Instead, we have to define an interface extending JQuery as follows:
interface JQueryTimeout extends JQuery {
    idleTimeout(settings: JQIdleTimeoutSettings): JQueryTimeout;
}

I made the declaration file open on GitHub. You can find it here.

Using the declaration file:
To use the declaration file in a TypeScript file, a reference of the declaration file should be added. Calling the idleTimeout function in TypeScript is quite similar to that of in JavaScript code. Only difference being, we need to type cast the jQuery object to type of JQueryTimeout.
/// <reference path="jQueryIdleTimeout.d.ts" />

(<JQueryTimeout>$(document)).idleTimeout({
                inactivity: 5000,
                noconfirm: 1000,
                sessionAlive: 1000,
                redirect_url: 'TimedOut.html',
                click_reset: true,
                alive_url: 'default.htm',
                showDialog: false
});
This is because, in TypeScript, $(document) returns an object of type JQuery. The function idleTimeout is declared in the interface JQueryTimeout, which is extended from the interface JQuery.

Happy coding!