Wednesday, May 6, 2009

Use of XML HTTP Request object to make server calls through javascript

We have a requirement that we need to show light box when you click on search results in search results page. When i was new to ASP.NET and know some what about ASP.NET AJAX i thought of using it, but it didn't work out well. Because search results returns large amount of data and if i put everything in UpdatePanel then it can't process the request because Ajax is meant for processing small amounts of data to and from server.

The main requirement is on search results page, we are showing a title, small description and read more link, when anyone clicks on the read more link, it will make a server call and get's the corresponding search results related data and show it up on the page in light box. It needs an ajax call. So, here ASP.NET Ajax won't work. After thought about 2 days i got a new idea and implemented that and working great. Everything was implemented with 15 lines of javascript code by using the XMLHttpRequest object.

How it works:
I have created an ASPX page, where it will return the HTML i need to show in the light box. From the XMLHttpRequest object, i will call that page, gets the response from it and show it in the light box. Very simple!!!
You can use handlers as well to do this. We can write some logic like depends on the querystring params, inside HTTPHandlers build HTML and return that html to browser. But for better styling and html formatting i used ASPX page instead of handlers. Finally, we will catch the response and bind it to the page.

ASPX CODE:




Explanation:
  1. I have taken a data list on my page, where it binds all the search results which matches the given keywords.
  2. I am using data bound event to bind the data on the server side, you can check that in the ASPX.CS section.
  3. I am using a ASP panel, to bind the response from the server and to show the light box. (This is tha panel we are using to bind the response from the server and show the light box.)
ASPX.CS:
protected void dlData_DataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Header || e.Item.ItemType == ListItemType.Footer) return;

Literal litTitle = e.Item.FindControl("litTitle") as Literal;
string anchorText = "<a href="javascript:void();" onclick="\"javascript:loadurl('{0}','{2}');return false;\">{1}</a>"; 
litTitle.Text = String.Format(anchorText, "Path of the page", "Title", panelLightBox.ClientID);
}
Note: "Path of page" is the actual page we need to call, and "Title" is the anchor text.


Explanation:
In this event, you can get the server object and bind the data to the controls declared in the item template of the data list. Example purpose, i am binding data to only litTitle control.

Here, if you observe i am creating a html anchor tag and binding that to the literal control, it's not a good way, rather you can create a html anchor control with runat="server" in Item template and bind the data to it, any thing works. I am using onclick event to make a call to the server, in the onclick event of the HTML anchor control i am calling a javascript function called, "loadurl", which will make a server request through XMLHttpRequest obejct.
So, the process is,
  1. From our code, when you click on the title, it will call the loadurl javascript function.
  2. In loadurl function, we will create a xml http request object and sends the request to server.
  3. We will get response from the server and we will catch the responseText from it, and bind it to the light box control.
You can check the loadurl function below.

JAVASCRIPT:
var xmlhttp;
function loadurl(dest, parentID) {
try {
xmlhttp = window.XMLHttpRequest?new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
}
xmlhttp.onreadystatechange = function(){triggered( parentID)};
//xmlhttp.setContentType("text/xml");
xmlhttp.open("GET", dest);
xmlhttp.send('');
}
var mainLightBoxDiv = null;
function triggered( parentID) {mainLightBoxDiv = parentID;
if ((xmlhttp.readyState == 4) && (xmlhttp.status == 200))
{
var div = document.getElementById(parentID);
div.innerHTML = xmlhttp.responseText.toString();

if (self.pageYOffset) {
yScroll = self.pageYOffset;
} else if (document.documentElement && document.documentElement.scrollTop){ // Explorer 6 Strict
yScroll = document.documentElement.scrollTop;
} else if (document.body) {// all other Explorers
yScroll = document.body.scrollTop;
}
var centerY = (yScroll + 170);
div.style.top = centerY+'px';
div.style.display="block";
}
}

function CloseDiv()
{
document.getElementById(mainLightBoxDiv).style.display = 'none';
}
Explanation:
  1. We are using two variables. One for the destination url, and one for the parentID which holds the id of the control for light box.
  2. We are creating an XMLHttpRequest object.
  3. When ready state changed, we are trigerring one event to process our request.
  4. Making the GET request to get the data from server.
  5. Binding the reponseText from the response to the parentID innerHTML.
  6. And some sort of logic to detect the y axis unit where we need to show light box, for this we are detecting the scrollbar position and setting the position of the division. i am doing some operation by adding/subtracting 170 - which is the minimum height of the light box in my scenario.
  7. We are using another function to close the light box.
These days, there are lot of technologies are coming and the best way of implement the above case is using JQuery. We cn use JTemplates to bind the search results data and make an ajax call to the page web method to get what we want. This is very simple and best.

For seeing it live or to test, you can see the page i developed for one of our client.

Very simple!!! Happy coding.

2 comments:

  1. wow, I love it.
    I have to do something similar like you and show the information in a JQuery dialog box.

    but don't you get the full html of the asp.net page? I rather have just the constant of the page without the Html header tags.

    I also visited your site, and I must say that I love your light box that you load when a user click on an ad...do you mind sharing how you got that to work? is it a div tag with a sytle sheet (I am using JQuery dialog box).

    In any case Love it man.
    thanks for the tip.

    ReplyDelete
  2. Hi there,
    If you are using JQuery, then no need of using this XMLHttpRequest object and implement the logic. It is very simple with JQuery. You can use Client proxy and write some page web methods to call it and send the response as a string and show it in JQuery dialog or light box. If you want to implement with javascript and asp.net [as what I did] then I did some small magic to get it other than what I posted. For me too the problem is html, head, body, form tags etc.... So, what I did was, I created an ASPX page which doesn't contain any html, head, body tags. It contains only the html I needed. i.e. only the controls like div, literals, panels etc. [Page more looks like user control except extension.] So, now page only respond me the html which doesn't have those html, head, body as I didn't place them on ASPX page. So, I will catch the response and show them on the light box.
    Note: Here you may think the implementation I have choose is wrong. No, It won't give any problems. And the way I have chosen is correct. Because I am not using that ASPX as complete page. That page is only for getting response from server and show it as light box.
    And another way you can do is, writing ashx files in your site.
    Please let me know, if you need any more help on this.

    ReplyDelete