AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1291&pId=-1
Extending the ImageMap HTML Control with AJAX 1.0 Extensions
page
by Bilal Haidar
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 37660/ 55

Introduction

This is the third article in my series of articles that are targeting the new AJAX 1.0 extensions in ASP.NET 2.0.

In this article we are going to show how to easily integrate an HTML Image Map control with AJAX 1.0 extensions using the coolest feature of AJAX 1.0 which is AJAX Services. What we will show in this article is very handy and useful. For instance, you can have a facility on your applications to show a map with clickable areas in such a way, when an area is clicked, a popup window will show more detailed information about the clicked area. Without the use of AJAX, the user would have to wait for the page to post back to the server, get the data and then show them! However, this is unfeasible and makes user experiences very poor. Another option would be when the page loads, it loads all related data for all clickable areas on the page, but this has its own performance weaknesses and also is not a preferred way for solving such an issue.

The above discussion shows the importance of using AJAX to populate the popup window with the related data from the server by utilizing the new features of AJAX and mainly AJAX Service.

A snapshot of what you are expecting from this article can be shown in Figure 1

Figure 1: Expected Ajaxified ImageMap HTML control

As you can see above, a map of Lebanon (author’s mother country) is shown and a hover over of the word Lebanon on the image caused a tiny and elegant popup window to show up giving more details about the area hovered over. In this example the popup will only echo the text in the hovered over area.

Configuring the HTML ImageMap control with clickable hot spots

To start with, you need to create a new AJAX enabled web site from inside Visual Studio 2005. Creating a new website based on this template makes sure that the website is properly configured to run with AJAX. If you have any problems in creating such a website, please make sure you check one of the last two articles about AJAX that included a detailed section on how to create such a website.

Add a new ASPX page and add the following HTML tags:

Listing 1

<map name="ImageMap">
<area shape="rect" alt="" coords="0,0,85,20"
  onmouseover="javascript:GetAreaInfo(event, 'Lebanon');"
onmouseout="javascript:HidePopup();" />
<area shape="rect" alt="" coords="135,60,185,75"
 onmouseover="javascript:GetAreaInfo(event, 'Tripoli');"
onmouseout="javascript:HidePopup();" />
<area shape="rect" alt="" coords="120,105,160,120"
 onmouseover="javascript:GetAreaInfo(event, 'Byblos');"
onmouseout="javascript:HidePopup();" />                
<area shape="rect" alt="" coords="93,140,140,160"
 onmouseover="javascript:GetAreaInfo(event, 'Beirut');"
onmouseout="javascript:HidePopup();" />
<area shape="rect" alt=""  coords="70,240,105,260"
 onmouseover="javascript:GetAreaInfo(event, 'Tyre');"
onmouseout="javascript:HidePopup();" />
<area shape="rect" alt="" coords="140,175,205,190"
 onmouseover="javascript:GetAreaInfo(event, 'Beiteddine');"
onmouseout="javascript:HidePopup();" />
<area shape="rect" alt="" coords="200,85,245,100"
 onmouseover="javascript:GetAreaInfo(event, 'Bcharre');"
onmouseout="javascript:HidePopup();" />
<area shape="rect" alt="" coords="180,155,225,165"
 onmouseover="javascript:GetAreaInfo(event, 'Zahle');"
onmouseout="javascript:HidePopup();" />
<area shape="rect" alt="" coords="220,120,270,140"
 onmouseover="javascript:GetAreaInfo(event, 'Ballbak');"
onmouseout="javascript:HidePopup();" />
</map>
<img src="images/lebanon.gif" border="0" alt="" usemap="#ImageMap" />

What we have done in the above HTML tags is added a new image with several hot spots representing the major cities in Lebanon. If you notice, each hot spot has a onmouseover and onmouseout JavaScript functions calls. We will discuss these functions in a later section in this article. For the time being just note that each hot spot will fire some JavaScript functions whenever you place your mouse over the area or when you remove your mouse.

Creating an AJAX Service

Logically speaking, we will need to create a new Web service that will handle retrieving data related to the clickable hot spots. AJAX Services are no different from normal ASP.NET Web services. To get a better understanding of how to create and manipulate AJAX Services, make sure you go through the links in the References section at the end of this article.

Let us create this new Web service by following the Figure 2

Figure 2: Creating a Web service

The above Web service will contain a single web method that will get the information from the data store you have.

To enable your ASP.NET Web service to be callable from the client side in an asynchronous style, i.e. converting it to an AJAX Service, you will need to add the ScriptService attribute to the class declaration as follows:

Listing 2

[ScriptService()]
public class LocationService : System.Web.Services.WebService
{

The ScriptService attribute is the only configuration you would need to add so that your Web service is script-accessible.

Now let us add a Web method that will be called from the client side:

Listing 3

[WebMethod]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
public string GetAreaInfo(string area)
{
  return area;
}

There is nothing different when declaring Web methods. You would add the WebMethod attribute as you would do with any other normal ASP.NET Web service. If you leave your Web service like that, it will work like a charm! However, you have an optional attribute you can add which is the ScriptMethod attribute. You can configure whether the Web method will be accessed using the HttpGet or HttpPost verb. Also, you can configure the format in which the data will be returned, whether in XML or JSON, by default it is JSON.

By default every Web method you create that is AJAX enabled, uses the HttpPost and JSON for the UseHttpGet and ResponseFormat properties of the ScriptMethod attribute.

The method we have defined is the GetAreaInfo method that takes as input a single parameter of type string. To make life easy, the method will simply return the same value of the input parameter, in your case you would need to do a database call to retrieve some data and send them back to the calling side.

That is everything you need to do concerning the new Web service. In a later section you will see how to configure the page that AJAX-enabled to make calls to this Web service. We have just created a new AJAX Service!!

Configuring the ASPX page with the AJAX Service

Up to this point, we have created the Web service that we will use later on to show detailed information on the clickable areas on the image map we are developing. However, for the client side script to be able to make successful calls for the Web service, we need to add a new ScriptManager on the page and add the Web service in the Service Reference section.

The code below shows how the ScriptManager is configured by a Service Reference entry:

Listing 4

<asp:ScriptManager ID="ScriptManager1" runat="server">
<services>
  <asp:servicereference path="~/LocationService.asmx" />
</services>
</asp:ScriptManager> 

All that is need to do to enable script-service calls in an asynchronous fashion, is simply add a new service reference entry into the ScriptManager control as shown in the code above.

What does the above Service Reference entry do?

The configuration above would add something like this to the rendered page:

Listing 5

<script src="LocationService.asmx/jsdebug" type="text/javascript"></script>

As you can see a new script entry has been added to the rendered page. The script tag refers to a JavaScript file named LocationService.asmx/jsdebug. This is called the Web Service Proxy class. The way AJAX works is by creating client-side proxy classes so that client-side functions can call the server-side Web service by utilizing this proxy class.

If you simply copy the path shown above into the browser, you would see a JavaScript file that is generated at run time by the AJAX environment to make script-service calls available. We will not delve into more details of explaining the proxy class since this is out of the scope of this article, but checking the above articles that were mentioned in a previous section would make more sense to you about what we are discussing here.

Up to this point, the page is ready to make script-service calls successfully!

Encapsulating functionalities in a Client Side class

With the introduction of AJAX and mainly AJAX Client Libraries, dealing with JavaScript for a non-professional JavaScript developer is not a nightmare anymore! Now you can create your own client templates or classes based on the prototype design pattern, add inheritance concepts, create Interfaces, and Enums in an easy manner.

In this article, we will develop a client side class that will encapsulate all of the functionalities needed by the application we are developing. You could live without creating such a class, however, it is recommended to go this way!

Let us first explain the concept of the class and why it is needed. To be able to show a popup window on the page showing the information coming from the server, we need a client side function that is capable of accessing the AJAX Service and retrieve the required data, update and show the popup window on the page, a function to hide the popup window, and a function to run in case an error occurred during the processing of the AJAX Service call. Therefore, the class we will be developing shall include all these functions.

Again, in this article we are not going to cover all of the details on the AJAX Client Side Libraries. We will only explain what is required and needed by this article. However, if you are interested in covering this topic in detail, we recommend you check the series of MSDN web casts on AJAX Client Libraries presented by Rob Bagby (Microsoft Developer Evangelist). You can have a look at this post from Rob that lists all the web casts he has delivered and those coming soon!

The first thing to do is to add a new JavaScript file. We will go step by step in explaining the code you would need to add:

Listing 6

Type.registerNamespace("MyServices");

We start by defining a new Namespace called MyServices. This namespace will include the client side class we are developing. As you can see the Namespace feature has been added to the JavaScript world!!

Then we need to define the constructor of the client side class:

Listing 7

MyServices.Location = function (uiElement, uiBody) {
MyServices.Location.initializeBase(this);    
this._uiElement = uiElement;
this._uiBody = uiBody;
this._xAxis = 0;
this._yAxis = 0;
}

The constructor of the template or class is nothing but a normal JavaScript function as shown above. The constructor takes as input two parameters:

uiElement

uiBody

Both parameters represent the popup window that will be displayed on the page. In addition, two other private members are declared that represent the position where the popup window shall be shown. Notice that it is recommended to declare all your private members in the constructor of the client side class.

Now that the constructor is defined, we will define the functions and properties included in the class using the prototype design pattern:

Listing 8

MyServices.Location.prototype =
{
  get_uiElement: function()
  {
    return this._uiElement;
  }
  , set_uiElement: function(value)
  {
    this._uiElement = value;
  }
  ,
 
  get_uiBody: function()
  {
    return this._uiBody;
  }
  , set_uiBody: function(value)
  {
    this._uiBody = value;
  }
  ,

The first things we define are public properties for the UI elements in the class. The GET and SET properties are defined as two separate functions in JavaScript.

Next, we will define the function that will do the service call from inside the client-side:

Listing 9

ShowPopupinfo: function(event, areaName)
{
  MyServices.LocationService.GetAreaInfo(areaName,
  Function.createDelegate(this, this.OnCompleted),
  this.OnError,  // Failure Callback
  this.OnTimeOut); // TimeOut Callback
  this._xAxis = event.clientX;
  this._yAxis = event.clientY;
}

The first line of the function above makes a call to the GetAreaInfo function by utilizing a class named MyServices.LocationService and accessing its method called GetAreaInfo. A very important note here to mention is that, this method is not the one shown above in the ASMX Web service we created above. This function call belongs to the Web Service Proxy class that was created at run time as a client side proxy to access the ASMX Web service on the server. Don’t mix both! To understand what we are talking above, please follow the instructions mentioned above on how to get more information on the Web Service Proxy class.

The MyServices.LocationService.GetAreaInfo function takes as input the parameter required by the server side GetAreaInfo method, a reference to a callback function that will be fired when the response is received from the server, a reference to a callback function that will be fired when an error occurs during the processing of the service asynchronous request, a reference to a callback function that will be fired when a time-out happens.

Notice that the success callback function is covered by Function.createDelegate(). The reason we have added this statement is to make the AJAX environment call the success callback function on the same instance of the class that fired the call to the Web service. This is mainly helpful, when you need to reference properties and functions of the client side class, which did the asynchronous service call to the server, inside the callback functions. So to sum it up, adding the above statement would make accessing properties and functions from the instance of the client side class that did the call to the Web service safe and accurate. Without this, the instance of the client side class that did the asynchronous call would be null, since the response of the Web service will be executing in a different context than the one used to send the request asynchronously to the Web service. This is a very important hint I owe it to Rob Bagby who explained it to me in details. Thank you Rob!!

Going back to the ShowPopupInfo function, the last two lines are simply setting the value of the two private members, xAxis and yAxis, using the event input parameter that contains among other useful information the position of the mouse where it was clicked on the page. The goal here is to show the popup window as close as possible to the location where the user has clicked his/her mouse.

The next function to discuss is the callback function that will be called when the response is received successfully from the server:

Listing 10

OnCompleted: function(result, userContext, methodName)
{
  var uiElement = $get(this.get_uiElement());
  var uiBody = $get(this.get_uiBody());
 
  if (uiBody != null)
  {
    var textNode = uiBody.firstChild;
    if (!textNode)
    {
      textNode = document.createTextNode(result);
      uiBody.appendChild(textNode);
    }
    else
    {
      textNode.nodeValue = result;
    }
    if (uiElement != null)
    {
      uiElement.style.visibility = "visible";
      uiElement.style.display = "inline";
      uiElement.style.left = this._xAxis + "px";
      uiElement.style.top = this._yAxis + "px";
    }
  }
}
,

The sole idea behind the above function is simply, set the data returned from the server into the popup window area and then make sure the popup window is now shown on the page.

The other functions in the client side class will not be discussed here due to the fact that they are too simple to discuss.

Once you have written the above client side class, you need to tell the AJAX environment to register the class on the client side to be accessible by client-side functions and the way to do so is simply adding this line of JavaScript code:

Listing 11

MyServices.Location.registerClass("MyServices.Location");

Up to this point, the client side class MyServices.Location is successfully defined. We will add few utility methods that will be called by controls on the ASPX page. These methods can be easily placed on the page itself inside a Script block, however, it is recommended to place all your JavaScript code in one place and then configure the ScriptManager on the ASPX page with a Script Reference so that when the page is rendered it will include a script tag referencing the JavaScript file including all user-defined functionalities.

First of all, we need to define a new instance of the client side class whenever the page loads. To do so, we will use the pageLoad function that is part of the Application class added newly to the AJAX environment.

Listing 12

var location = null;
function pageLoad(sender, args) {
location = new MyServices.Location("modal""modalBody");
location.HidePopupInfo();
}

The code above, simply creates a new instance of the MyServices.Location class and calls a function that is part of the client side class to hide the popup window on the page. The reason why we created the instance of the client side class in the pageLoad function is that, when the AJAX environment reaches the pageLoad function, all the AJAX client side and user defined JavaScript code has been successfully loaded, so at this stage it is safe to access any user or system defined JavaScript code.

Another function will be created is the GetAreaInfo function. We could have made the clickable hot spots directly call the ShowPopupInfo function defined on the MyServices.Location class, but to make the HTML part of the page independent of the class instance name, we have added this function that will be called by the hot spots on the page, passing the event argument and the text representing the area hovered over! The function simply makes a call to the ShowPopupInfo function on the defined instance of the MyServices.Location class.

If you have reached this stage, this means that you have finished developing your AJAX-enabled HTML ImageMap control and ready to browse the ASPX page and hover over the image displayed.

References
Downloads
Conclusion

In this article, we have shown you how to create new AJAX Services, create your own client side classes, and finally extend the HTML ImageMap control with AJAX calls to show additional information on some clickable areas on the image itself. A brief explanation was given on most of the code that was used and additional references were presented to grasp in depth all the ideas and new features you need to know in AJAX.

Happy Ajaxified Dot Netting!!



©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-28 11:42:41 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search