The power of ajaxed.callback. Get the insights!    AJAX

ajaxed.callback, this JavaScript function is our god when it comes to AJAX usage. It's usage can be simple but also very complex. A detailed explanation of its parameters and the usage follows below.

If you are starting to use ajaxed, please refer to the beginners tutorials first. This article requires advanced ajaxed and JavaScript knowledge.

First of all you should know that ajaxed.callback has to be used if you want to use ajaxed Page Parts or want to call server side functions. It's the communication node between client side and server side.

Now let's take a look at the method signature:

ajaxed.callback(action, onReturn, [params, onCompleted, url])


Okay, thats the theoretical part. Lets get some examples done. I want to demonstrate all the different usage scenarios. Read carefully as it can get a bit tricky sometimes.

Using the action

The action is being used to identify the callback on the server side. This allows you to add as many callback as you want. Basically every action is piped into our callback procedure unless it finds a procedure with the same name and prefixed with pagepart_. In this case it calls the procedure directly and returns its response back to the client


<%
sub callback(a)
  if a = "one" then
    'NEVER REACHED! because there is a
    'sub called pagePart_one
    page.return "foo"
  elseif a = "two" then
    'will be reached
    page.return "foo"
  end if
end sub

sub pagePart_one
  str.write("<strong>some html response</strong>")
end sub
%>
<script>
  ajaxed.callback("one", function(r) {
    //do something
  });
  ajaxed.callback("two", function(r) {
    //do something
  });
</script>


Using the onReturn

The function passed to the onReturn parameter will be invoked once the callback has been finished successfully. It's NEVER called if something fails as opposed to the onComplete function.

Be sure to provide one parameter for it. This parameter will hold the response back from the server. In case of a callback it contains all the variables sent with AjaxedPage.return() or AjaxedPage.returnValue(). In case of a page part call it contains a string which holds the XHTML produced by the page part.


<%
sub callback(a)
  if a = "actionOne" then
    page.return "wow!"
  end if
end sub

sub pagePart_partOne %>
  <strong>hi</strong>
<% end sub %>
<script>
  //you can create functions and reuse them
  function myHandler(r) {
    alert(r);
  }

  //will alert "<strong>hi</strong>"
  ajaxed.callback('partOne', myHandler);
  
  //will alert "wow!"
  ajaxed.callback('actionOne', myHandler);

  //you can write the function inline as well
  //will alert "wow!"
  ajaxed.callback('actionOne', function(r) {
    alert(r)
  });
</script>


And because we want to make life easier for developers you can also pass a string in case of a page part. Then the string is treated as the ID of the target element. This element will be updated with the page part response then.


<% sub pagePart_partOne %>
  <strong>hi</strong>
<% end sub %>

<script>
  ajaxed.callback('partOne', 'destination');

  //same, but not rapid :)
  ajaxed.callback('partOne', function(r) {
    $('destination').update(r)
  });
</script>

<div id="destination"></div>


Using parameters

The third parameter of ajaxed.callback can be used to pass parameters to our server side action. By default it checks if there is a form with an ID frm. If there is one it grabs all its form fields and passes those values as parameters to your action. If ther is no form called frm then no parameters are being sent unless you specify them manually. You can always provide the parameters by yourself regardless of an existing form or not. Those parameters must be provided as a Hash then (name value pairs in JSON notation). All parameters are available via the request.form collection on the server side afterwards.


<script>
  //#1
  //will automatically pass the param1 value
  //to the server side (because the page contains
  //a form with the ID 'frm'
  ajaxed.callback('check', function(r) {
    //do something
  });

  //#2
  //provide parameters manually
  ajaxed.callback('check', function(r) {
    //do something
  }, {someParam1: "foo", anotherParam: "foo"});

  //#3
  //take parameter from form and add an own (1st)
  ajaxed.callback('check', function(r) {
    //do something
  }, {pName: $F("pID"), anotherParam: "foo"});

  //#4
  //take parameter from form and add an own
  //automatically grab all fields from the form
  ajaxed.callback('check', function(r) {
    //do something
  }, $("frm").serialize(true).set(anotherParam, "foo"));
</script>

<form id="frm">
  <input type="text" id="pID" name="pName" value="foo"/>
</form>

<%
'our server side handler
sub callback(a)
  if a <> "check" then exit sub
  
  'will contain "foo" when calling with #1, #2, #4
  'will contain no value when caling with #3
  pName = page.RF("pname")

  'will contain value only when calling with #3
  someParam1 = page.RF("someParam1")

  'will always contain "foo" unless on #1 call
  anotherParam = page.RF("anotherParam")
end sub
%>


All this applies to page parts and callbacks.
Remember: The fields NAME is being used as the parameter name.
Not the fields ID (see in example #3)!

You can pass parameters the same way to a page part. You can access the parameter afterwards within the page part. Check the following example:

<!--#include virtual="/ajaxed/ajaxed.asp"-->
<%
set page = new AjaxedPage
page.draw()

sub main() %>
  <div id="output"><% pagePart_one %></div>
  
  <form id="frm" onsubmit="ajaxed.callback('one', 'output'); return false">
    <input type="text" name="value">
    <input type="submit" value="send">
  </form>
<% end sub %>

<% sub pagePart_one %>

  You typed: <%= page.RF("value") %>

<% end sub %>
Run this code — pagepart_param.asp


Using onCompleted

The onCompleted parameter can hold a reference to a JavaScript function which is invoked after the callback has completed (its being passed the XMLHttpRequest object). Very useful to do clean up work. Check the following example. It demonstrated how to disable a button on callback and enable it back again when it finished.


<%
sub callback(a)
  if a = "myAction" then page.return "something"
end sub
%>

<script>
  function doFoo(sender) {
    //first we disable our element which invokes
    //the function. So he cannot call it again as
    //as its already running
    Field.disable(sender);
    ajaxed.callback('myAction', function(r) {
      //do something
    }, null, function(t) {
      //when the callback completes we enable it back
      Field.enable(sender)
    })
  }
</script>

<button type="button" onclick="doFoo()">Do</button>


You have to place the enable code into the onComplete as it would never enable the button when the action failed.

Using the url parameter

This parameter tells us where the server side code is located. By default its the current executing page and this is the most needed case. But sometimes (when it gets tough) you might want to call code within another page (try to avoid it as it reduces readability and maintainability!) or you want to expose a public interface for your application. Read on :)

Important: You need to specify the URL parameter when using ajaxed.callback on a default page of a folder. This is due to a bug within IIS. It does not return the default page when being called (with POST) without the filename.

E.g. Lets say /pages/default.asp is the default page of the /pages/ folder. In that case the ajaxed.callback wont work with only on /pages/
You need to specify default.asp as the url here. Don't forget the querystring if required.

Being able to specify the URL for the callback you could realize something like services for your application. Every application could expose a file with possible actions and other applications (clients) could call those function and get structured data back (even from outside through the internet). Check this example.

App 1 - file: service.asp

<%
sub callback(a)
  'gets the total sales for a given year
  if a = "getTotalSales" then
    'calculate the total sales somehow
    page.return getTotals(page.RFP("yr", 0))
  end if
end sub
%>


App 2 - can request the sales from App 1

<script>
  ajaxed.callback('getTotalSales', function(r) {
    $('sales').update(r);
  }, {yr: <%= year(now) %>>);
</script>

Sales this year:
<div id="sales"></div>


Do you see the benefit? You could write complete APIs for your applications. As these calls return JSON it would be possible for other systems (PHP, Java, Ruby, etc.) to consume those APIs. Use your imagination :)

Closing words

As you can see ajaxed.callback is really powerful and allows you to do all kind of tricky calls. To use all its power be sure to understand the basics first. After that you will see how easy it is to hook up AJAX functionality into your apps.

Have fun
Michal

Posted in AJAX 5629 days ago

Version 2.1.1 Released3962 days ago