Blog Archives

App beta testing gets better with new TestFlight SDK

Developers looking to beta test their apps before getting them into the App Store have a number of options for finding and communicating with beta testers, but few are as slick and easy to use as TestFlight. Now the provisioning tool gets even better, thanks to a number of updates in version two, which made its official debut on Monday.

The new version of TestFlight comes with an SDK that allows developers to make their beta testing process a lot more involved, and it provides improved tools for gathering feedback. Feedback and communication are key to a successful beta test (which is why I’m not a great tester myself), and the new features available to developers through TestFlight’s API are all about improving information flow between devs and testers.

Highlights of what developers can look forward to include:

  • In-App Questions. Trigger questions at specific checkpoints to get feedback from users as they’re using the software exactly at points where you think there might be an issue.
  • In-App Updates. Make sure your test group is on the same page with in-app update prompts, which also allow you to update to the latest version instantly over the air.
  • Feedback. In-app forms and tester email responses all feed into the developer dashboard and allow for instant replies between tester and coder.

There’s more, too, so be sure to head over to the official TestFlight website and check it out if you’re interested. Developers and testers alike can still sign up for free, too, and all of these new features arrive as free updates for existing and new users alike. Inevitably, TestFlight will have to bring some tiered paid options or advertising to the table to keep things going, but judging by developer response and its adoption by big brands so far, it won’t have too much trouble getting people to pay for the product when it does.

As for general consumers, even if you never actually use or see TestFlight in action, you’ll probably feel its effects: A better beta process with more communication options built in should lead to better shipping products popping up in the App Store.

Related research and analysis from GigaOM Pro:
Subscriber content. Sign up for a free trial.

App beta testing gets better with new TestFlight SDK

Developers looking to beta test their apps before getting them into the App Store have a number of options for finding and communicating with beta testers, but few are as slick and easy to use as TestFlight. Now the provisioning tool gets even better, thanks to a number of updates in version two, which made its official debut on Monday.

The new version of TestFlight comes with an SDK that allows developers to make their beta testing process a lot more involved, and it provides improved tools for gathering feedback. Feedback and communication are key to a successful beta test (which is why I’m not a great tester myself), and the new features available to developers through TestFlight’s API are all about improving information flow between devs and testers.

Highlights of what developers can look forward to include:

  • In-App Questions. Trigger questions at specific checkpoints to get feedback from users as they’re using the software exactly at points where you think there might be an issue.
  • In-App Updates. Make sure your test group is on the same page with in-app update prompts, which also allow you to update to the latest version instantly over the air.
  • Feedback. In-app forms and tester email responses all feed into the developer dashboard and allow for instant replies between tester and coder.

There’s more, too, so be sure to head over to the official TestFlight website and check it out if you’re interested. Developers and testers alike can still sign up for free, too, and all of these new features arrive as free updates for existing and new users alike. Inevitably, TestFlight will have to bring some tiered paid options or advertising to the table to keep things going, but judging by developer response and its adoption by big brands so far, it won’t have too much trouble getting people to pay for the product when it does.

As for general consumers, even if you never actually use or see TestFlight in action, you’ll probably feel its effects: A better beta process with more communication options built in should lead to better shipping products popping up in the App Store.

Related research and analysis from GigaOM Pro:
Subscriber content. Sign up for a free trial.

Use ASP.NET’s HttpHandler to bridge the cross-domain gap

When you’re developing client-side applications, a problem you’ll almost inevitably have to deal with is how to work with services that reside outside your website’s domain. Though many modern APIs do support JSONP, which is a clever workaround to somewhat mitigate the cross-domain problem, JSONP has its own problems.

Worse, if you encounter an API with no JSONP support, the cross-domain barrier can quickly become a formidable one. CORS is slowly becoming a viable alternative, but it requires that the remote service support it via special HTTP headers and browser support for CORS is still not ubiquitous.

Until CORS is more broadly supported, an alternative solution is to bounce cross-domain requests through the web server that hosts your website. In ASP.NET, the best tool for implementing that sort of middleman endpoint is the HttpHandler.

In this post, I’ll show you how to create an HttpHandler to service cross-domain requests, how to use jQuery to communicate with the handler, and an example of one improvement that this approach makes possible.

An example remote API

To focus on an example that’s already familiar to many, I’m going to use Twitter. Twitter’s API does support JSONP, which is a viable alternative for consuming it across domains. In fact, the Twitter status that you see in my sidebar to the right was retrieved from Twitter’s API via JSONP.

However, not every service supports JSONP, its third-party script injection mechanism is sometimes problematic, and using JSONP robs us of niceties like local caching. So, for the sake of a good example, let’s find a way to use the Twitter API on the client-side without resorting to JSONP.

Specifically, I’m interested in querying the service for my last few status updates. The Twitter API request to accomplish that looks like this:

Twitter will respond to that with a JSON array of objects representing my (or your) last 20 tweets, which is exactly what we’re after.

The best tool for the job: HttpHandler

If you’re accustomed to using ASP.NET’s page methods and ScriptServices to facilitate communication between client and server, those tools begin to look like a hammer that matches every JSON-shaped nail in sight. However, when simply relaying an external API’s JSON through to the client, they often add unnecessary overhead and complexity.

Rather, a lower-level tool is more appropriate in this case.

HttpHandlers are one of ASP.NET’s most under-utilized tools. They’re simple to implement and allow you to handle requests closer to the metal than WebForms pages or MVC controller actions.

One place in particular where HttpHandlers shine is where you would otherwise consider writing Response.Write statements in a WebForms page’s code-behind. This anti-pattern of using ASPX’s code-behind to get closer to the metal looks similar to approaches that you’ll see on some other platforms, such as PHP, but is not equivalent.

Unfortunately, even if you don’t use WebForms controls or ASPX markup at all, executing that low-level code from an ASPX page’s code-behind requires that every request filter through the full page life cycle. That means even the simplest request still has to percolate all the way from PreInit to Unload, adding needless overhead.

Instead, the HttpHandler is where you should write that sort of code that ultimately boils down to Response.Write calls.

Choosing the right handler type

A tricky issue when you’re writing your first HttpHandler is that Visual Studio presents you with two templates, “ASP.NET Handler” and “Generic Handler”:

The add item dialog presents two choices of HttpHandler templates

Both are similar, but the “ASP.NET Handler” template’s approach requires modifying your web.config to configure which URL your handler accepts requests at. Mucking around in the web.config isn’t terribly difficult, but it’s extra friction which makes the process less approachable.

In the spirit of keeping things simple, let’s stick with the more traditionally file-based “Generic Handler”.

Getting started with your first HttpHandler

After choosing that template, specifying a name, and adding the new file to your site, you’ll end up with a bit of boilerplate code that includes this method:

public void ProcessRequest(HttpContext context) {
  context.Response.ContentType = "text/plain";
  context.Response.Write("Hello World");
}

If you start the site up in Visual Studio and then request your newly-created HttpHandler in a browser, Handler1.ashx if you accept the default name, you will see “Hello World” as you might expect.

That’s not very impressive yet, but the response you saw made its way to your browser without touching WebForms’ page life cycle or filtering through ASP.NET MVC’s routing engine and action filters. While those things are worthwhile niceties for the majority of your application, they’re unwanted overhead when all you need is to efficiently relay some content through the server.

Bouncing a request to Twitter through the HttpHandler

To adapt an HttpHandler for relaying requests to the Twitter API, we can use .NET’s handy WebClient class to make the request to Twitter’s API, and then return the result back through as the handler’s response:

public void ProcessRequest(HttpContext context) {
  WebClient twitter = new WebClient();
 
  // The base URL for Twitter API requests.
  string baseUrl = "http://api.twitter.com/1/";
 
  // The specific API call that we're interested in.
  string request = "statuses/user_timeline.json?id=Encosia";
 
  // Make a request to the API and capture its result.
  string response = twitter.DownloadString(baseUrl + request);
 
  // Set the content-type so that libraries like jQuery can 
  //  automatically parse the result.
  context.Response.ContentType = "application/json";
 
  // Relay the API response back down to the client.
  context.Response.Write(response);
}

That code simply makes an HTTP request to the Twitter API and blindly bounces the result back through as the HttpHandler’s response. For the time being, everything is hard-coded, but we’ll improve on that soon enough.

Using the handler proxy on the client-side

With our web server doing the heavy lifting, using this server-side proxy to make a remote request is trivial:

$.getJSON('TwitterProxy.ashx', function(tweets) {
  // Call a magical function that does all the presentational work.
  displayTweets(tweets);
});

The jQuery code here is actually identical what you’d use when requesting the API via JSONP. Whether that response is truly being fulfilled by the specified URL or it’s being relayed through our HttpHandler, it’s all the same to the jQuery code on the client-side.

As you’ll see when we add caching, this can easily be exploited for good.

Mixing things up with QueryString parameters

The hard-coded approach works well enough, but what if we wanted to be able to query any Twitter account’s recent updates instead of being limited to just that boring Encosia character?

Since HttpHandlers receive an instance of the current HttpContext as the parameter to their ProcessRequest method, it’s easy to access QueryString parameters and react accordingly. For example, this would allow us to request any Twitter account’s timeline by via an id parameter on the QueryString:

public void ProcessRequest(HttpContext context) {
  WebClient twitter = new WebClient();
 
  string baseUrl = "http://api.twitter.com/1/";
 
  // Extract the desired account ID from the QueryString.
  string id = context.Request.QueryString["id"];
 
  // Make a request to the API for the specified id.
  string request = "statuses/user_timeline.json?id=" + id;
 
  // Same as before, from here on out:
  string response = twitter.DownloadString(baseUrl + request);
 
  context.Response.ContentType = "application/json";
  context.Response.Write(response);
}

Now it works exactly the same way as before, but we can choose which Twitter account’s timeline is requested. For example, this URL would request Scott Guthrie‘s latest tweets:

TwitterProxy.ashx?id=ScottGu

Supplying parameters with $.getJSON

To pass this new parameter in from the client-side, you could handcraft the entire URL including the appropriate QueryString. Even better though, $.getJSON has an optional “data” argument that accepts a JavaScript object and converts it to QueryString parameters:

$.getJSON('TwitterProxy.ashx', { id: 'ScottGu' }, function(tweets) {
  displayTweets(tweets);
});

jQuery will automatically URLEncode the parameters you specify in the “data” argument and properly assemble them into the final URL to be requested:

Screenshot of the HttpHandler request generated by the jQuery code above.

Which is exactly what we need it to do.

Using a configuration object like this is cleaner than manually concatenating a string together and makes it easier to vary the parameter at runtime.

Improving performance with server-side caching

An advantage the HttpHandler proxy has over CORS and JSONP is that you can perform any arbitrary server-side processing that you wish, both before and after the remote service repsonds. A great way to take advantage of that is adding a server-side caching layer.

Server-side caching will reduce how often requests actually trigger API calls and can significantly improve performance for requests that are already cached. A caching middleman like this is especially valuable when dealing with rate-limited APIs like Twitter’s.

Let’s say that we wanted to cache Twitter responses for up to five minutes, for example:

public void ProcessRequest(HttpContext context) {
  // This will be the case whether there's a cache hit or not.
  context.Response.ContentType = "application/json";
 
  // Check to see if the twitter status is already cached,
  //   then retrieve and return the cached value if so.
  // 8/3/11: Updated with more robust test, thanks to ctolkien.
  object tweetsCache = context.Cache["tweets-" + id];
 
  if (tweetsCache != null) {
    string cachedTweets = tweetsCache.ToString();
 
    context.Response.Write(cachedTweets);
 
    // We're done here.
    return;
  }
 
  WebClient twitter = new WebClient();
 
  // Move along; nothing to see here. The concatenation is just
  //  to avoid horizontal scrolling within the meager 492
  //  pixels I have to work with here.
  string url = "http://api.twitter.com/1/statuses/" +
               "user_timeline.json?id=Encosia";
 
  string tweets = twitter.DownloadString(url);
 
  // This monstrosity essentially just caches the WebClient result
  //  with a maximum lifetime of 5 minutes from now.
  // If you don't care about the expiration, this can be a simple
  //  context.Cache["tweets"] = tweets; instead.
  context.Cache.Add("tweets", tweets,
    null, DateTime.Now.AddMinutes(5),
    System.Web.Caching.Cache.NoSlidingExpiration,
    System.Web.Caching.CacheItemPriority.Normal,
    null);
 
  context.Response.Write(tweets);
}

Adding the intermediate cache results in a tremendous performance improvement after the first request:

Screenshot of an initial uncached request to Twitter and then the subsequent, cached requests

With the server able to immediately serve requests within the five minute caching window, subsequent $.getJSON requests are an order of magnitude faster!

Perhaps even more importantly in the case of Twitter, these four refreshes only counted as one API call against my hourly rate-limit.

Conclusion

Using HttpHandlers as server-side proxies turns out to be a simple way to solve the pesky cross-domain restrictions that we’ve all run into from time to time. All said and done, using an HttpHandler to proxy third-party requests takes few lines of code, but offers nearly unlimited flexibility.

In addition to the obvious benefit of getting around the cross-domain restriction, bouncing requests through your own server potentially has a range of other benefits, including:

  • Error handling – This approach not only passes unhandled exceptions on the WebClient request back through to the client-side, but it also gives you the ability to enhance the error handling with your own sanity checks and constraints.
  • Caching – As shown in this post’s final example, you can very easily interject your own caching layer for requests passing through the HttpHandler proxy. That’s especially useful when working against rate limited or potentially slow/flaky APIs (like Twitter’s).
  • Security – When you’re accustomed to server-side programming, the revealing nature of client-side JavaScript can be unnerving. Learning to appropriately partition sensitive algorithms and data between client and server is key to mitigating that issue. Along those lines, moving the remote request to code running on your server is one way to keep sensitive information like API keys and passwords safely hidden from view-source and client-side developer tools.
  • Reliability – One of JSONP’s less obvious drawbacks is the fact that it relies on injecting a third-party script. However, your users may be using something like NoScript to purposely block third-party scripts, effectively shutting down your ability to use JSONP. Even if you prefer JSONP in most cases, a local server-side proxy can be helpful as a fallback in case of unexpected JSONP failures.

That’s not to say that there’s no downsides to this approach. When you’re using an HttpHandler proxy, it’s important to keep in mind that it can be slower since you’re making a series of two connections instead of a single, direct one. You also lose the ability to request content with the user’s third-party cookies attached to the request, which is helpful in some cases.

Overall, using server-side proxies is a very useful item to have in your toolbox. I hope this post has served to introduce you to the approach and/or given you better insight into how you can use HttpHandlers to your advantage.

Get the source

If you’d like to browse through a complete working example of what’s been covered in this post, take a look at the companion project at GitHub. Or, if you’d like to download the entire project and run it in Visual Studio to see it in action yourself, grab the ZIP archive.

HttpHandler-Proxy on GitHubHttpHandler-Proxy.zip

Related posts:

  1. AJAX, file downloads, and IFRAMEs
  2. The easiest way to break ASP.NET AJAX pages
  3. Why ASP.NET AJAX UpdatePanels are dangerous

You’ve been reading Use ASP.NET’s HttpHandler to bridge the cross-domain gap, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you’ve got any feedback, please click through and leave a comment; I’d love to hear from you. You can click here to jump directly to the comment section of this post.

Use ASP.NET’s HttpHandler to bridge the cross-domain gap

When you’re developing client-side applications, a problem you’ll almost inevitably have to deal with is how to work with services that reside outside your website’s domain. Though many modern APIs do support JSONP, which is a clever workaround to somewhat mitigate the cross-domain problem, JSONP has its own problems.

Worse, if you encounter an API with no JSONP support, the cross-domain barrier can quickly become a formidable one. CORS is slowly becoming a viable alternative, but it requires that the remote service support it via special HTTP headers and browser support for CORS is still not ubiquitous.

Until CORS is more broadly supported, an alternative solution is to bounce cross-domain requests through the web server that hosts your website. In ASP.NET, the best tool for implementing that sort of middleman endpoint is the HttpHandler.

In this post, I’ll show you how to create an HttpHandler to service cross-domain requests, how to use jQuery to communicate with the handler, and an example of one improvement that this approach makes possible.

An example remote API

To focus on an example that’s already familiar to many, I’m going to use Twitter. Twitter’s API does support JSONP, which is a viable alternative for consuming it across domains. In fact, the Twitter status that you see in my sidebar to the right was retrieved from Twitter’s API via JSONP.

However, not every service supports JSONP, its third-party script injection mechanism is sometimes problematic, and using JSONP robs us of niceties like local caching. So, for the sake of a good example, let’s find a way to use the Twitter API on the client-side without resorting to JSONP.

Specifically, I’m interested in querying the service for my last few status updates. The Twitter API request to accomplish that looks like this:

Twitter will respond to that with a JSON array of objects representing my (or your) last 20 tweets, which is exactly what we’re after.

The best tool for the job: HttpHandler

If you’re accustomed to using ASP.NET’s page methods and ScriptServices to facilitate communication between client and server, those tools begin to look like a hammer that matches every JSON-shaped nail in sight. However, when simply relaying an external API’s JSON through to the client, they often add unnecessary overhead and complexity.

Rather, a lower-level tool is more appropriate in this case.

HttpHandlers are one of ASP.NET’s most under-utilized tools. They’re simple to implement and allow you to handle requests closer to the metal than WebForms pages or MVC controller actions.

One place in particular where HttpHandlers shine is where you would otherwise consider writing Response.Write statements in a WebForms page’s code-behind. This anti-pattern of using ASPX’s code-behind to get closer to the metal looks similar to approaches that you’ll see on some other platforms, such as PHP, but is not equivalent.

Unfortunately, even if you don’t use WebForms controls or ASPX markup at all, executing that low-level code from an ASPX page’s code-behind requires that every request filter through the full page life cycle. That means even the simplest request still has to percolate all the way from PreInit to Unload, adding needless overhead.

Instead, the HttpHandler is where you should write that sort of code that ultimately boils down to Response.Write calls.

Choosing the right handler type

A tricky issue when you’re writing your first HttpHandler is that Visual Studio presents you with two templates, “ASP.NET Handler” and “Generic Handler”:

The add item dialog presents two choices of HttpHandler templates

Both are similar, but the “ASP.NET Handler” template’s approach requires modifying your web.config to configure which URL your handler accepts requests at. Mucking around in the web.config isn’t terribly difficult, but it’s extra friction which makes the process less approachable.

In the spirit of keeping things simple, let’s stick with the more traditionally file-based “Generic Handler”.

Getting started with your first HttpHandler

After choosing that template, specifying a name, and adding the new file to your site, you’ll end up with a bit of boilerplate code that includes this method:

public void ProcessRequest(HttpContext context) {
  context.Response.ContentType = "text/plain";
  context.Response.Write("Hello World");
}

If you start the site up in Visual Studio and then request your newly-created HttpHandler in a browser, Handler1.ashx if you accept the default name, you will see “Hello World” as you might expect.

That’s not very impressive yet, but the response you saw made its way to your browser without touching WebForms’ page life cycle or filtering through ASP.NET MVC’s routing engine and action filters. While those things are worthwhile niceties for the majority of your application, they’re unwanted overhead when all you need is to efficiently relay some content through the server.

Bouncing a request to Twitter through the HttpHandler

To adapt an HttpHandler for relaying requests to the Twitter API, we can use .NET’s handy WebClient class to make the request to Twitter’s API, and then return the result back through as the handler’s response:

public void ProcessRequest(HttpContext context) {
  WebClient twitter = new WebClient();
 
  // The base URL for Twitter API requests.
  string baseUrl = "http://api.twitter.com/1/";
 
  // The specific API call that we're interested in.
  string request = "statuses/user_timeline.json?id=Encosia";
 
  // Make a request to the API and capture its result.
  string response = twitter.DownloadString(baseUrl + request);
 
  // Set the content-type so that libraries like jQuery can 
  //  automatically parse the result.
  context.Response.ContentType = "application/json";
 
  // Relay the API response back down to the client.
  context.Response.Write(response);
}

That code simply makes an HTTP request to the Twitter API and blindly bounces the result back through as the HttpHandler’s response. For the time being, everything is hard-coded, but we’ll improve on that soon enough.

Using the handler proxy on the client-side

With our web server doing the heavy lifting, using this server-side proxy to make a remote request is trivial:

$.getJSON('TwitterProxy.ashx', function(tweets) {
  // Call a magical function that does all the presentational work.
  displayTweets(tweets);
});

The jQuery code here is actually identical what you’d use when requesting the API via JSONP. Whether that response is truly being fulfilled by the specified URL or it’s being relayed through our HttpHandler, it’s all the same to the jQuery code on the client-side.

As you’ll see when we add caching, this can easily be exploited for good.

Mixing things up with QueryString parameters

The hard-coded approach works well enough, but what if we wanted to be able to query any Twitter account’s recent updates instead of being limited to just that boring Encosia character?

Since HttpHandlers receive an instance of the current HttpContext as the parameter to their ProcessRequest method, it’s easy to access QueryString parameters and react accordingly. For example, this would allow us to request any Twitter account’s timeline by via an id parameter on the QueryString:

public void ProcessRequest(HttpContext context) {
  WebClient twitter = new WebClient();
 
  string baseUrl = "http://api.twitter.com/1/";
 
  // Extract the desired account ID from the QueryString.
  string id = context.Request.QueryString["id"];
 
  // Make a request to the API for the specified id.
  string request = "statuses/user_timeline.json?id=" + id;
 
  // Same as before, from here on out:
  string response = twitter.DownloadString(baseUrl + request);
 
  context.Response.ContentType = "application/json";
  context.Response.Write(response);
}

Now it works exactly the same way as before, but we can choose which Twitter account’s timeline is requested. For example, this URL would request Scott Guthrie‘s latest tweets:

TwitterProxy.ashx?id=ScottGu

Supplying parameters with $.getJSON

To pass this new parameter in from the client-side, you could handcraft the entire URL including the appropriate QueryString. Even better though, $.getJSON has an optional “data” argument that accepts a JavaScript object and converts it to QueryString parameters:

$.getJSON('TwitterProxy.ashx', { id: 'ScottGu' }, function(tweets) {
  displayTweets(tweets);
});

jQuery will automatically URLEncode the parameters you specify in the “data” argument and properly assemble them into the final URL to be requested:

Screenshot of the HttpHandler request generated by the jQuery code above.

Which is exactly what we need it to do.

Using a configuration object like this is cleaner than manually concatenating a string together and makes it easier to vary the parameter at runtime.

Improving performance with server-side caching

An advantage the HttpHandler proxy has over CORS and JSONP is that you can perform any arbitrary server-side processing that you wish, both before and after the remote service repsonds. A great way to take advantage of that is adding a server-side caching layer.

Server-side caching will reduce how often requests actually trigger API calls and can significantly improve performance for requests that are already cached. A caching middleman like this is especially valuable when dealing with rate-limited APIs like Twitter’s.

Let’s say that we wanted to cache Twitter responses for up to five minutes, for example:

public void ProcessRequest(HttpContext context) {
  // This will be the case whether there's a cache hit or not.
  context.Response.ContentType = "application/json";
 
  // Check to see if the twitter status is already cached,
  //   then retrieve and return the cached value if so.
  // 8/3/11: Updated with more robust test, thanks to ctolkien.
  object tweetsCache = context.Cache["tweets-" + id];
 
  if (tweetsCache != null) {
    string cachedTweets = tweetsCache.ToString();
 
    context.Response.Write(cachedTweets);
 
    // We're done here.
    return;
  }
 
  WebClient twitter = new WebClient();
 
  // Move along; nothing to see here. The concatenation is just
  //  to avoid horizontal scrolling within the meager 492
  //  pixels I have to work with here.
  string url = "http://api.twitter.com/1/statuses/" +
               "user_timeline.json?id=Encosia";
 
  string tweets = twitter.DownloadString(url);
 
  // This monstrosity essentially just caches the WebClient result
  //  with a maximum lifetime of 5 minutes from now.
  // If you don't care about the expiration, this can be a simple
  //  context.Cache["tweets"] = tweets; instead.
  context.Cache.Add("tweets", tweets,
    null, DateTime.Now.AddMinutes(5),
    System.Web.Caching.Cache.NoSlidingExpiration,
    System.Web.Caching.CacheItemPriority.Normal,
    null);
 
  context.Response.Write(tweets);
}

Adding the intermediate cache results in a tremendous performance improvement after the first request:

Screenshot of an initial uncached request to Twitter and then the subsequent, cached requests

With the server able to immediately serve requests within the five minute caching window, subsequent $.getJSON requests are an order of magnitude faster!

Perhaps even more importantly in the case of Twitter, these four refreshes only counted as one API call against my hourly rate-limit.

Conclusion

Using HttpHandlers as server-side proxies turns out to be a simple way to solve the pesky cross-domain restrictions that we’ve all run into from time to time. All said and done, using an HttpHandler to proxy third-party requests takes few lines of code, but offers nearly unlimited flexibility.

In addition to the obvious benefit of getting around the cross-domain restriction, bouncing requests through your own server potentially has a range of other benefits, including:

  • Error handling – This approach not only passes unhandled exceptions on the WebClient request back through to the client-side, but it also gives you the ability to enhance the error handling with your own sanity checks and constraints.
  • Caching – As shown in this post’s final example, you can very easily interject your own caching layer for requests passing through the HttpHandler proxy. That’s especially useful when working against rate limited or potentially slow/flaky APIs (like Twitter’s).
  • Security – When you’re accustomed to server-side programming, the revealing nature of client-side JavaScript can be unnerving. Learning to appropriately partition sensitive algorithms and data between client and server is key to mitigating that issue. Along those lines, moving the remote request to code running on your server is one way to keep sensitive information like API keys and passwords safely hidden from view-source and client-side developer tools.
  • Reliability – One of JSONP’s less obvious drawbacks is the fact that it relies on injecting a third-party script. However, your users may be using something like NoScript to purposely block third-party scripts, effectively shutting down your ability to use JSONP. Even if you prefer JSONP in most cases, a local server-side proxy can be helpful as a fallback in case of unexpected JSONP failures.

That’s not to say that there’s no downsides to this approach. When you’re using an HttpHandler proxy, it’s important to keep in mind that it can be slower since you’re making a series of two connections instead of a single, direct one. You also lose the ability to request content with the user’s third-party cookies attached to the request, which is helpful in some cases.

Overall, using server-side proxies is a very useful item to have in your toolbox. I hope this post has served to introduce you to the approach and/or given you better insight into how you can use HttpHandlers to your advantage.

Get the source

If you’d like to browse through a complete working example of what’s been covered in this post, take a look at the companion project at GitHub. Or, if you’d like to download the entire project and run it in Visual Studio to see it in action yourself, grab the ZIP archive.

HttpHandler-Proxy on GitHubHttpHandler-Proxy.zip

Related posts:

  1. Save yourself some typing when you call ASP.NET services
  2. 3 mistakes to avoid when using jQuery with ASP.NET AJAX
  3. jQuery 1.5?s AJAX rewrite and ASP.NET services: All is well

You’ve been reading Use ASP.NET’s HttpHandler to bridge the cross-domain gap, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.

If you’ve got any feedback, please click through and leave a comment; I’d love to hear from you. You can click here to jump directly to the comment section of this post.

The Prototype Pattern – Techniques, Strategies and Patterns for Structuring JavaScript Code

Using the JavaScript Prototype Pattern

This is the 2nd post in a series on techniques, strategies and patterns for writing JavaScript code. In my previous post I introduced what I call “function spaghetti code” and explained some of the problems it introduces. I also talked about the impact of global variables and how closures add a much needed solution. In this post I’ll introduce the Prototype Pattern and show how it relies on built-in functionality in the JavaScript language.

I’ve worked through some of the patterns I’m covering in this series with my good friend John Papa over Skype and we’ve talked about pros and cons of different approaches. For example, he initially recommended defining multiple variables using a single var based on JSLint suggestions (that was covered in the previous post) and I agreed that it was a better approach than using var for every variable. It’s interesting how code evolves with feedback from multiple people. John and I have definitely come to enjoy working with a few different patterns and although the Prototype Pattern isn’t in my favorites list, I’ve always felt that it’s good to understand and know the different options out there. That’s why I decided to include it in this series.

The Prototype Pattern can be broken out into two main sections including a constructor section and a prototype section. Prototyping allows functions and properties to be associated with objects. However, instead of each object instance getting a copy of all functions/properties each time an object is created, only one set of functions/properties exists across all objects resulting in less memory consumption. In other words, functions and properties are defined once per prototype rather than once per object.

As a quick review, I showed the following code in a previous post. The code simply lists all functions directly with no encapsulation and defines several global variables. While the code works fine this way, I’ll examine how we can restructure it to follow the Prototype Pattern.

window.onload = function () {
    eqCtl = document.getElementById('eq');
    currNumberCtl = document.getElementById('currNumber');
};

var eqCtl,
    currNumberCtl,
    operator,
    operatorSet = false,
    equalsPressed = false,
    lastNumber = null;

function add(x,y) {
    return x + y;
}

function subtract(x, y) {
    return x - y;
}

function multiply(x, y) {
    return x * y;
}

function divide(x, y) {
    if (y == 0) {
        alert("Can't divide by 0");
        return 0;
    }
    return x / y;
}

function setVal(val) {
    currNumberCtl.innerHTML = val;
}

function setEquation(val) {
    eqCtl.innerHTML = val;
}

function clearNumbers() {
    lastNumber = null;
    equalsPressed = operatorSet = false;
    setVal('0');
    setEquation('');
}

function setOperator(newOperator) {
    if (newOperator == '=') {
        equalsPressed = true;
        calculate();
        setEquation('');
        return;
    }

    //Handle case where = was pressed
    //followed by an operator (+, -, *, /)
    if (!equalsPressed) calculate();
    equalsPressed = false;
    operator = newOperator;
    operatorSet = true;
    lastNumber = parseFloat(currNumberCtl.innerHTML);
    var eqText = (eqCtl.innerHTML == '') ?
        lastNumber + ' ' + operator + ' ' :
        eqCtl.innerHTML + ' ' + operator + ' ';
    setEquation(eqText);
}

function numberClick(e) {
    var button = (e.target) ? e.target : e.srcElement;
    if (operatorSet == true || currNumberCtl.innerHTML == '0') {
        setVal('');
        operatorSet = false;
    }
    setVal(currNumberCtl.innerHTML + button.innerHTML);
    setEquation(eqCtl.innerHTML + button.innerHTML);
}

function calculate() {
    if (!operator || lastNumber == null) return;
    var currNumber = parseFloat(currNumberCtl.innerHTML),
        newVal = 0;
    //eval() would've made this a whole lot simpler
    //but didn't want to use it in favor of a more
    //"robust" set of methods to demo patterns
    switch (operator) {
        case '+':
            newVal = add(lastNumber, currNumber);
            break;
        case '-':
            newVal = subtract(lastNumber, currNumber);
            break;
        case '*':
            newVal = multiply(lastNumber, currNumber);
            break;
        case '/':
            newVal = divide(lastNumber, currNumber);
            break;
    }
    setVal(newVal);
    lastNumber = newVal;
}

 

To start using the Prototype Pattern you need to first create a constructor as shown next. The constructor can accept one or more parameters and define any variables that the object needs. Note that the variables are scoped to the object rather than to the global scope.

var Calculator = function (tb, eq) {
    this.eqCtl = document.getElementById(eq);
    this.currNumberCtl = document.getElementById(tb);
    this.operator = null;
    this.operatorSet = false;
    this.equalsPressed = false;
    this.lastNumber = null;
};


Once the constructor is defined a prototype can be created using the prototype keyword. Although you can create a prototype for each function, it’s more convenient (and less typing) to take advantage of JSON-style syntax where the function name represents the JSON property name and the value represents the function. An example of defining two functions in a prototype is shown next. Notice that each function is separated with a comma just as you would separate properties defined in a normal JSON object. It’s officially called a JavaScript object literal, but if you’re familiar with JSON it uses the same standard syntax (thanks to Craig Stuntz for clarifying that):

Calculator.prototype = {

    add: function (x, y) {
        return x + y;
    },

    subtract: function (x, y) {
        return x - y;
    }
}


The original function-based calculator code shown earlier can be refactored to follow the Prototype Pattern as shown shown next. A prototype is created for the Calculator object and functions/properties are defined within the prototype using JavaScript object literal syntax.

Calculator.prototype = {

    add: function (x, y) {
        return x + y;
    },

    subtract: function (x, y) {
        return x - y;
    },

    multiply: function (x, y) {
        return x * y;
    },

    divide: function (x, y) {
        if (y == 0) {
            alert("Can't divide by 0");
        }
        return x / y;
    },

    setVal: function(val) {
        this.currNumberCtl.innerHTML = val;
    },

    setEquation: function (val) {
        this.eqCtl.innerHTML = val;
    },

    clearNumbers: function () {
        this.lastNumber = null;
        this.equalsPressed = this.operatorSet = false;
        this.setVal('0');
        this.setEquation('');
    },

    setOperator: function (newOperator) {
        if (newOperator == '=') {
            this.equalsPressed = true;
            this.calculate();
            this.setEquation('');
            return;
        }

        //Handle case where = was pressed
        //followed by an operator (+, -, *, /)
        if (!this.equalsPressed) this.calculate();
        this.equalsPressed = false;
        this.operator = newOperator;
        this.operatorSet = true;
        this.lastNumber = parseFloat(this.currNumberCtl.innerHTML);
        var eqText = (this.eqCtl.innerHTML == '') ?
            this.lastNumber + ' ' + this.operator + ' ' :
            this.eqCtl.innerHTML + ' ' + this.operator + ' ';
        this.setEquation(eqText);
    },

    numberClick: function () {
        var button = (event.target) ? event.target : event.srcElement;
        if (this.operatorSet == true || this.currNumberCtl.innerHTML == '0') {
            this.setVal('');
            this.operatorSet = false;
        }
        this.setVal(this.currNumberCtl.innerHTML + button.innerHTML);
        this.setEquation(this.eqCtl.innerHTML + button.innerHTML);
    },

    calculate: function () {
        if (!this.operator || this.lastNumber == null) return;
        var displayedNumber = parseFloat(this.currNumberCtl.innerHTML)
            newVal = 0;
        //eval() would've made this a whole lot simpler
        //but didn't want to use it in favor of a more
        //"robust" set of methods to demo patterns
        switch (this.operator) {
            case '+':
                newVal = this.add(this.lastNumber, displayedNumber);
                break;
            case '-':
                newVal = this.subtract(this.lastNumber, displayedNumber);
                break;
            case '*':
                newVal = this.multiply(this.lastNumber, displayedNumber);
                break;
            case '/':
                newVal = this.divide(this.lastNumber, displayedNumber);
                break;
        }
        this.setVal(newVal);
        this.lastNumber = newVal;
    }
};


To use the Calculator object, create a new instance and pass the names of the HTML container objects into the constructor (the container objects identify the IDs of controls used to display calculations – see the HTML code below):

var calc = null;
window.onload = function () {
    calc = new Calculator('currNumber', 'eq');
};


The HTML used to render the calculator can reference the calc object created when the page loads. The following code demonstrates how this can be done to handle events as different div elements are clicked. I normally prefer to wire-up events to event handlers using jQuery in “real-world” applications to keep the HTML clean but wanted to focus on JavaScript patterns and avoid introducing additional libraries for this post. I’m not a big fan of defining onclick and other event handlers directly on HTML elements but let it slide for this post.

<div class="Calculator">
    <div class="CalculatorHead">
        <div id="eq" class="Equation"></div>
        <div id="currNumber" class="CurrentNumber">0</div>
    </div>
    <div>
        <div class="Button" onclick="calc.numberClick(event);">7</div>
        <div class="Button" onclick="calc.numberClick(event);">8</div>
        <div class="Button" onclick="calc.numberClick(event);">9</div>
        <div class="Button" onclick="calc.setOperator('/');">/</div>
        <div class="Button rowspan2" onclick="calc.clearNumbers();">C</div>
    </div>
    <div>
        <div class="Button" onclick="calc.numberClick(event);">4</div>
        <div class="Button" onclick="calc.numberClick(event);">5</div>
        <div class="Button" onclick="calc.numberClick(event);">6</div>
        <div class="Button" onclick="calc.setOperator('*');">*</div>
    </div>
    <div>
        <div class="Button" onclick="calc.numberClick(event);">1</div>
        <div class="Button" onclick="calc.numberClick(event);">2</div>
        <div class="Button" onclick="calc.numberClick(event);">3</div>
        <div class="Button" onclick="calc.setOperator('-')">-</div>
        <div class="Button rowspan2" onclick="calc.setOperator('=');">=</div>
    </div>
    <div>
        <div class="Button colspan2" onclick="calc.numberClick(event);">0</div>
        <div class="Button" onclick="calc.numberClick();">.</div>
        <div class="Button" onclick="calc.setOperator('+');">+</div>
    </div>
</div>

 

The Prototype Pattern provides a nice way to structure JavaScript code but there are several other roads you can travel if desired. In this next post I’ll talk about the Revealing Module Pattern and explain how it can be used.

Demos of all the patterns covered in this series can be downloaded below.

Download Code

Deserializing ReCaptcha JSON with C#

Turning a ReCaptcha request into a strongly-typed C# object on the fly

When requesting a ReCaptcha image, you send out this request:

www.google.com/recaptcha/api/challenge?k=your_public_key

You then receive this in return:

var RecaptchaState = {
    site : 'your_public_key',
    challenge : 'returned_challenge_key',
    is_incorrect : false,
    programming_error : '',
    error_message : '',
    server : 'http://www.google.com/recaptcha/api/',
    timeout : 18000
};

document.write('<scr'+'ipt type="text/javascript"
    s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js">
    </scr'+'ipt>');

Looking at that, you can pull the information you need into this object:

[Serializable]
public class ReCaptchaState
{
    [DataMember]
    public string site { get; set; }

    [DataMember]
    public string challenge { get; set; }

    [DataMember]
    public bool is_correct { get; set; }

    [DataMember]
    public string programming_error { get; set; }

    [DataMember]
    public string error_message { get; set; }

    [DataMember]
    public string server { get; set; }

    [DataMember]
    public int timeout { get; set; }
}

By using this code:

WebClient client = new WebClient();
string ret = client.DownloadString(google_url);
int start = ret.IndexOf('{');
int length = ret.IndexOf('}') - start + 1;
string json = ret.Substring(start, length);

ReCaptchaState state = new JavaScriptSerializer()
    .Deserialize<ReCaptchaState>(json);

Now you have a ReCaptchaState .net object you can use the values from; simple.

How and when to reset your Mac’s PRAM and SMC

There are times when your Mac will just start misbehaving. Video settings getting reset, fans start running at full speed, keyboard lights don’t come on when they should.  This is most likely to happen following a hardware upgrade, extended power outage or even a major software upgrade (like Lion). In those cases, sometimes you need to reset your Mac’s parameter random access memory (PRAM) or system management controller (SMC) to get things running smoothly again.

Try this first

There are some good best practices to perform before running off and resetting your Mac at the first sign of strange behavior. This isn’t a step-by-step list; try each and all of the below separately when you’re having trouble:

  • Quit (Command+Q) or even Force Quit (Command+Option+Esc) any and all running applications.
  • Log off and then log back on to any and all logged on user accounts.
  • Put the Mac to sleep and wake it up again.
  • Restart the Mac.
  • Shut down and unplug the Mac (and remove any battery if you have access) for at least thirty seconds before powering back on.

You may even have to press and hold the power button several seconds in extreme cases when your Mac is truly not responding or refuses to shut down and power off. But if you have tried all of this to no avail, then perhaps you do need to either reset your PRAM or your SMC.

Parameter random access memory

PRAM is used by OS X to store certain information that the system can access quickly. Macs will store settings like which startup drive to boot from, various display and video settings, startup speaker volume and even the DVD’s region settings. If you feel that you need to reset your Mac’s PRAM because of the issues you’re having, do the following:

  1. Turn off your Mac. Don’t worry about disconnecting the power or removing the battery.
  2. Turn on your Mac and hold down the Command, Option, P, and R keys all at the same time (all four keys).
  3. Keep holding down all four keys until you hear the startup sound for a second time.

If you do not hear the startup sound twice, then you most likely have not reset the PRAM.  If you find that your Mac is not retaining the information that is stored in PRAM when you perform a shutdown, then it might be time to replace your Mac’s main logic board battery.  This is sometimes referred to as the PRAM or Clock Battery. I hardly ever fully shut down and power off any of my Macs, and have yet to replace this battery on any Mac I have owned, so that should only be the culprit in very extreme cases.

System management controller

The SMC is an Intel-only feature.  There are so many symptoms that can potentially be solved by resetting the SMC that you’d think you would need to do this sort of reset all of the time. These include fans running out of control, lights not displaying correctly, the Mac does not sleep or wake properly, and just generally poor performance and high CPU cycles for no good reason. There are three ways to reset your SMC, based on what sort of Intel-based Mac you have:
Portable Macs with removable batteries

  1. Shut down the Mac, unplug and remove the battery.
  2. Press and hold the power button for five seconds before releasing.
  3. Replace the battery (just put it back in), plug in the Mac and turn it back on.

Portable Macs without removable batteries

  • Shut down the Mac.
  • Ensure that the Mac is plugged into a power source.
  • While the Mac is turned off, press and hold the Shift, Control and Option keys, as well as the Power button.
  • Release all four keys at the same time (note: the Mac should not power on when performing this task).
  • Press the power button to turn the Mac back on.

Desktop Mac Pros, iMacs and Mac minis

  • Shut down and unplug the Mac.
  • Keep the Mac unplugged for at least fifteen seconds.
  • Plug the Mac back in and do not turn it back on for at least five seconds.
  • Press the power button to turn the Mac back on.

This shouldn’t be considered a routine operation, like fixing file permissions in Disk Utility. It’s just something to keep in mind as a possible last resort solution to weird behaviors that your Mac starts to develop, which can often happen when you perform upgrades like installing OS X Lion, especially on older hardware.

Related research and analysis from GigaOM Pro:
Subscriber content. Sign up for a free trial.

iPad Usability Study Reveals What We Do and Don’t Like In Apps

iPad users aren’t stingy with their devices, according to a new usability report by the Nielsen Norman Group focusing on Apple’s tablet. In fact, iPad owners who lived with one or more individuals reported that they shared their iPads freely, unlike the iPhone. The report also illuminated many things we like and don’t like about the apps we use on our iPads.

For example, the study found that users aren’t crazy about using their iPad devices to deal with complicated forms that require lots of user input, especially if those forms are found in non-optimized websites, rather than housed in an app. Users would skip registrations processes rather than deal with inputting information in many cases. The solution to such a problem would be to make forms simpler, requiring less information, and reduce the need for repeat entry of information (so apps that offer to remember login details are better, for example).

iPad users also aren’t as able to decipher non-obvious control systems as some developers might think. In cases where it wasn’t made clear what tapping an item that wasn’t obviously a button (i.e., a logo) would do, users often missed the functionality. Examples cited in the report include the logo in the top left of The Daily app, which returns users to the app’s home screen. USA Today  originally used a similar mechanism, but changed their logo to include a “Sections” label to tell users that it was in fact designed to be tapped and tied to a function.

Likewise, gestures in apps can sometimes cause trouble when there are no visual cues to provide information about how they work. Don’t think that placing an instructional video or graphic at the beginning of the app will solve the problem, either. Many users don’t read instructions, though visual instructions that are incredibly obvious, like those used by Bing for iPad, tested well with those participating in the study, since users couldn’t avoid grasping their meaning even when they quickly dismissed them. Nielsen Norman Group advises developers that they’re much better off including visual markers throughout, indicating that swipes and other gestures can be used. For example, magazine apps like Wired include arrows that show the direction a user should swipe to unveil more content.

Another alternative is to provide explicit tips in the form of dialog boxes, like Adobe Photoshop Express does. The iPad Photoshop app uses gestures to control effects like “soft focus,” and pops up notifications to alert users of what to do. Tips can be hidden at any time, so they won’t become annoying.

What users find very annoying according to the report are splash or loading screens. No matter how clever, or how easy on the eye, splash screens and animations become annoying very quickly. Startup sounds, in particular, are singled out as especially bad, because of the potential they have for unpleasantly surprising people who open apps in surroundings where noise might not be appreciated.

Also, almost universally, apps will benefit from having back buttons on nearly every page, and should aim for a simple homepage-like table of contents over more complicated navigation schemes. Users prefer a home base from which to operate without having to hunt through carousels or wade through long columns of thumbnails, and they always want the option to go one step back from their current position, because of accidental taps or to refer back to something they just saw.

As mentioned above, iPads tend to be communal devices, at least within the household. But the report also highlighted some other interesting points regarding how we use the Apple tablet. Generally, we use it for gaming, checking email and communicating via social networking, watching videos/movies and reading news. We also tend to shop, but the participants in the study generally preferred shopping on their desktops, and some even perceived iPad shopping to be more risky from a security perspective. iPads also tend to be carried around by many users, or at least taken along for the ride when long waits or trips are expected.

Now that the iPad is more than a year old, it’s interesting to see how people are using it, and what is and isn’t working when it comes to app usability design. No doubt there’s still plenty of innovation left in iPad app interface design, but this report illustrates that some things never go out of style when it comes to user experience.

How does your experience with the iPad either agree or disagree with the findings described above?

Related content from GigaOM Pro (subscription req’d):

Creating a Line Chart using the HTML 5 Canvas

The HTML 5 canvas is capable of rendering lines, shapes, images, text and more without relying on a plugin. Although the canvas element isn’t supported by older browsers, the latest version of all major browsers (IE, Safari, Chrome, Firefox and Opera) now support the canvas making it an option for rendering charts, graphs and other types of visual data. In cases where a browser doesn’t support the canvas, a fallback can be provided that renders data using Silverlight, Flash or another type of plugin.

In a previous post I walked through the fundamentals of using the HTML 5 canvas to render different types of shapes. In this post I’ll discuss how the canvas can be used to render a line chart using JavaScript. An example of the chart that will be discussed is shown next:

 

To render the chart a JavaScript object named CanvasChart was created that handles rendering all of the lines, shapes and text shown above. An example of defining CanvasChart settings and calling its render() function is show next. The render() function accepts the canvas element ID as well as a JSON object that defines chart properties and data to be used in the rendering process.

<!DOCTYPE html>
<html>
<head>
    <title>Canvas Chart Demo</title>
    <script src="Scripts/jquery-1.6.min.js" type="text/javascript"></script>
    <script src="Scripts/canvasChart.js" type="text/javascript"></script>
    <script type="text/javascript">

        $(document).ready(function () {
            var dataDef = { title: "US Population Chart",
                            xLabel: 'Year',
                            yLabel: 'Population (millions)',
                            labelFont: '19pt Arial',
                            dataPointFont: '10pt Arial',
                            renderTypes: [CanvasChart.renderType.lines, CanvasChart.renderType.points],
                            dataPoints: [{ x: '1790', y: 3.9 },
                                         { x: '1810', y: 7.2 },
                                         { x: '1830', y: 12.8 },
                                         { x: '1850', y: 23.1 },
                                         { x: '1870', y: 36.5 },
                                         { x: '1890', y: 62.9 },
                                         { x: '1910', y: 92.2 },
                                         { x: '1930', y: 123.2 },
                                         { x: '1950', y: 151.3 },
                                         { x: '1970', y: 203.2 },
                                         { x: '1990', y: 248.7 },
                                         { x: '2010', y: 308.7}]
                           };
            CanvasChart.render('canvas', dataDef);
        });

    </script>
</head>
<body style="margin-left:50px;margin-top:50px;">
    <canvas id="canvas" width="800" height="600"></canvas>
</body>
</html>


While the CanvasChart object is only a prototype at this point, it demonstrates several key features of the canvas element that can be used in applications including rendering lines, shapes, gradients, text and even transformed text. Let’s take a look at how the CanvasChart object was created.

Rendering Gradients and Text

The code for the CanvasChart object is located in a file named canvasChart.js. The code starts by defining a CanvasChart object that exposes two members named renderType and render. renderType is used to define what will be rendered on the chart (currently it supports rendering lines and points) while render() is used to render the data on the canvas as well as the associated labels for the x and y axes. The skeleton code for CanvasObject is shown next:

var CanvasChart = function () {
    var ctx;
    var margin = { top: 40, left: 75, right: 0, bottom: 75 };
    var chartHeight, chartWidth, yMax, xMax, data;
    var maxYValue = 0;
    var ratio = 0;
    var renderType = { lines: 'lines', points: 'points' };

    return {
        renderType: renderType,
        render: render
    };
} ();

 

The render() function accepts the canvas ID within the page as well as a JSON object that defines details about labels, font sizes, data points and more:

var render = function(canvasId, dataObj) {
    data = dataObj;
    getMaxDataYValue();
    var canvas = document.getElementById(canvasId);
    chartHeight = canvas.attr('height');
    chartWidth = canvas.attr('width');
    xMax = chartWidth - (margin.left + margin.right);
    yMax = chartHeight - (margin.top + margin.bottom);
    ratio = yMax / maxYValue;
    ctx = canvas.getContext("2d");
    renderChart();
}

 

The function starts by assigning the dataObj parameter to a variable within the CanvasChart object and then calls an internal function named getMaxDataYValue(). The getMaxDataYValue() function determines the maximum Y value for the data points. From there, the render() function locates the target canvas element within the page, calculates width and height values, and accesses the canvas’s 2D context that will be used to draw. Finally, a call is made to renderChart() to start the rendering process.

The renderChart() function orchestrates different drawing functions and handles rendering the background, lines, labels and data by calling the respective functions:

var renderChart = function () {
    renderBackground();
    renderText();
    renderLinesAndLabels();

    //render data based upon type of renderType(s) that client supplies
    if (data.renderTypes == undefined || data.renderTypes == null) data.renderTypes = [renderType.lines];
    for (var i = 0; i < data.renderTypes.length; i++) {
        renderData(data.renderTypes[i]);
    }
}

 

Different canvas features are used such as gradients and transforms in the CanvasChart object. For example, the renderBackground() function shows how linear gradients can be created:

var renderBackground = function () {
    var lingrad = ctx.createLinearGradient(margin.left, margin.top, xMax - margin.right, yMax);
    lingrad.addColorStop(0.0, '#D4D4D4');
    lingrad.addColorStop(0.2, '#fff');
    lingrad.addColorStop(0.8, '#fff');
    lingrad.addColorStop(1, '#D4D4D4');
    ctx.fillStyle = lingrad;
    ctx.fillRect(margin.left, margin.top, xMax - margin.left, yMax - margin.top);
    ctx.fillStyle = 'black';
}

 

The renderBackground() function uses the 2D context’s createLinearGradient() function to define a gradient that has 4 gradient stops. Once the gradient is defined it is assigned to the fillStyle property and then rendered to a rectangular area using the fillRect() function.

CanvasChart also demonstrates how text can be manipulated using transforms. The text displayed on the Y axis is rotated so that it displays vertically:

 

image

 

This is accomplished by using the canvas element’s rotate transform functionality which is found in the renderText() function:

var renderText = function renderText() {
    var labelFont = (data.labelFont != null) ? data.labelFont : '20pt Arial';
    ctx.font = labelFont;
    ctx.textAlign = "center";

    //Title
    var txtSize = ctx.measureText(data.title);
    ctx.fillText(data.title, (chartWidth / 2), (margin.top / 2));

    //X-axis text
    txtSize = ctx.measureText(data.xLabel);
    ctx.fillText(data.xLabel, margin.left + (xMax / 2) - (txtSize.width / 2), yMax + (margin.bottom / 1.2));

    //Y-axis text
    ctx.save();
    ctx.rotate(-Math.PI / 2);
    ctx.font = labelFont;
    ctx.fillText(data.yLabel, (yMax / 2) * -1, margin.left / 4);
    ctx.restore();
}

 

The key section of this code is the call to ctx.save() (toward the bottom of the function shown above) which saves the current state of the canvas so that it can be restored. This is necessary so that the entire canvas isn’t rotated. Once the current canvas state is saved, a call to the rotate() function is made to rotate the canvas. The text is then drawn for the vertical axis using the fillText() function. Once the rotated text is rendered the canvas is restored back to its saved state (the state before the rotate transform was applied and the text was rendered).

After the x and y axis text is rendered, the CanvasChart object makes a call to renderLinesAndLabels() to handle rendering the horizontal and vertical lines.

var renderLinesAndLabels = function renderLinesAndLabels() {
    //Vertical guide lines
    var yInc = yMax / data.dataPoints.length;
    var yPos = 0;
    var yLabelInc = (maxYValue * ratio) / data.dataPoints.length;
    var xInc = getXInc();
    var xPos = margin.left;
    for (var i = 0; i < data.dataPoints.length; i++) {
        yPos += (i == 0) ? margin.top : yInc;
        //Draw horizontal lines
        drawLine(margin.left, yPos, xMax, yPos, '#E8E8E8');

        //y axis labels
        ctx.font = (data.dataPointFont != null) ? data.dataPointFont : '10pt Calibri';
        var txt = Math.round(maxYValue - ((i == 0) ? 0 : yPos / ratio));
        var txtSize = ctx.measureText(txt);
        ctx.fillText(txt, margin.left - ((txtSize.width >= 14)?txtSize.width:10) - 7, yPos + 4);

        //x axis labels
        txt = data.dataPoints[i].x;
        txtSize = ctx.measureText(txt);
        ctx.fillText(txt, xPos, yMax + (margin.bottom / 3));
        xPos += xInc;
    }

    //Vertical line
    drawLine(margin.left, margin.top, margin.left, yMax, 'black');

    //Horizontal Line
    drawLine(margin.left, yMax, xMax, yMax, 'black');
}

 

Lines are normally drawn using the 2D context’s moveTo() and lineTo() functions which I wrapped in a function named drawLine() to simplify the process:

var drawLine = function drawLine(startX, startY, endX, endY, strokeStyle, lineWidth) {
    if (strokeStyle != null) ctx.strokeStyle = strokeStyle;
    if (lineWidth != null) ctx.lineWidth = lineWidth;
    ctx.beginPath();
    ctx.moveTo(startX, startY);
    ctx.lineTo(endX, endY);
    ctx.stroke();
    ctx.closePath();
}


At this point the canvas looks like the following:

image

Rendering Data

Once the labels and lines are rendered, CanvasChart handles rendering the data points by calling a function named renderData(). This function handles iterating through the JSON   data points and drawing lines, points or both depending upon the settings passed to CanvasChart’s render() function. Lines are drawn to connect the different data points through calls to the drawLine() function shown earlier while circles are drawn for specific data points by making calls to the 2D context’s arc() function. The circles that are rendered have a radial gradient applied to them using the createRadialGradient() function:

 

var renderData = function renderData(type) {
    var xInc = getXInc();
    var prevX, prevY = 0;

    for (var i = 0; i < data.dataPoints.length; i++) {
        var pt = data.dataPoints[i];
        var ptY = (maxYValue - pt.y) * ratio;
        if (ptY < margin.top) ptY = margin.top;
        var ptX = (i * xInc) + margin.left;

        if (i > 0 && type == renderType.lines) {
            //Draw connecting lines
            drawLine(ptX, ptY, prevX, prevY, 'black', 2);
        }

        if (type == renderType.points) {
            var radgrad = ctx.createRadialGradient(ptX, ptY, 8, ptX - 5, ptY - 5, 0);
            radgrad.addColorStop(0, 'Green');
            radgrad.addColorStop(0.9, 'White');
            ctx.beginPath();
            ctx.fillStyle = radgrad;
            //Render circle
            ctx.arc(ptX, ptY, 8, 0, 2 * Math.PI, false)
            ctx.fill();
            ctx.lineWidth = 1;
            ctx.strokeStyle = '#000';
            ctx.stroke();
            ctx.closePath();
        }

        prevX = ptX;
        prevY = ptY;
    }
}

 

Once the data points are rendered the chart looks like the following:

 

Conclusion

You can see that there’s a fair amount of JavaScript code required to use the canvas object. However, once the different API functions are understood it’s simply a process of calling the appropriate functions to render lines, text or shapes. Although the CanvasChart object shown here is only a prototype at this point, I hope it provides insight into what the HTML 5 canvas is capable of rendering and how some of the features it provides can be used.

Download Canvas Demo

Create an Apple ID in iTunes Account Without a Credit Card [ITunes]

iTunes: People often get confused when they go to create an Apple ID in iTunes, only to find that a credit card is required to proceed (even if they weren’t planning on purchasing any apps). Oddly enough, whether or not iTunes will give the option to choose “None” for a credit card will depend on how the account is created. More »







WP Like Button Plugin by Free WordPress Templates