CSC/ECE 517 Fall 2009/wiki2 2 rv

From Expertiza_Wiki
Revision as of 23:02, 8 October 2009 by Rrajase (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

AJAX implementation in MVC environments of in Ruby , Java , PHP , ASP.NET

MVC Enviorment

AJAX

AJAX is an efficient way for a web application to handle user interactions with a web page -- a way that reduces the need to do a page refresh or full page reload for every user interaction. This enables rich behavior (similar to that of a desktop application or plug-in-based web application) using a browser. AJAX interactions are handled asynchronously in the background. As this happens, a user can continue working with the page. AJAX Interactions are initiated by the JavaScript in the web page. When the AJAX interaction is complete, JavaScript updates the HTML source of the page. The changes are made immediately without requiring a page refresh. AJAX interactions can be used to do things such as validate form entries (while the user is entering them) using server-side logic, retrieve detailed data from the server, dynamically update data on a page, and submit partial forms from the page.

What is particularly attractive about this is that AJAX applications do not require a separate plug-in, and are platform and browser-neutral. That said, AJAX is not supported as well in older browsers. Care needs to be taken in writing client-side script that accounts for the differences between browsers.

AJAX Implemetaions

AJAX in Ruby

Basically used in View and controller How to Use Ajax in Our Web Application

The hard way to use Ajax in your web app is to write your own custom JavaScript that directly uses the XMLHttpRequest object's API. By doing this, we have to deal with the idiosyncrasies of each browser.

An easier way is to use one of several JavaScript libraries that provide higher-level Ajax services and hide the differences between browsers. Libraries such as DWR, Prototype, Sajax, and Ajax.NET are all good choices.

The easiest way of all is to use the built-in Ajax facilities of Ruby on Rails. In fact, Rails makes Ajax so easy that for typical cases it's no harder to use Ajax than it is not to! How Rails Implements Ajax

Rails has a simple, consistent model for how it implements Ajax operations.

Once the browser has rendered and displayed the initial web page, different user actions cause it to display a new web page (like any traditional web app) or trigger an Ajax operation:

  • A trigger action occurs. This could be the user clicking on a button or link, the user making changes to the data on a form or in a field, or just a periodic trigger (based on a timer).
  • Data associated with the trigger (a field or an entire form) is sent asynchronously to an action handler on the server via XMLHttpRequest.
  • The server-side action handler takes some action (that's why it is an action handler) based on the data, and returns an HTML fragment as its response.
  • The client-side JavaScript (created automatically by Rails) receives the HTML fragment and uses it to update a specified part of the current page's HTML, often the content of a
    tag.


Steps to implement Ajax in Ruby:

  • Using a link_to_remote tag in the HTML
     <%= link_to_remote( "Register",
                        :update => "new_user",
                        :url =>{ :action => "allusers" }) %>
   This tag tells that the name of the link is "Register", it will render the new response inside div named as "new_user" and it will call "allusers" action from controller.

  • After this allusers action will render in a partial template like this:
       render :parti => "allusers"
  • This call will go to a "_allusers" file where response will be populated and result will come inside div tag "new_user".


AJAX in Java

Implementing autocomplete in a search field is something that can be performed using AJAX. To do it, we need to provide code on the client and on the server.

On the Client

First, the user specifies the URL of a page that is loaded by the browser. For this example let's assume the page is an HTML page that is generated by a JSF component, servlet, or JSP page. The page contains a form text field that has an attribute onkeyup with the name of a JavaScript function doCompletion(). This function is called each time a key is pressed in the form text field. <input type="text" size="20" autocomplete="off" id="complete-field" name="id" onkeyup="doCompletion();">

Let's assume that a user types in an "M" character in the form text field. In response, the doCompletion() function is called which, in turn, initializes an XMLHttpRequest object:

  function initRequest() {
      if (window.XMLHttpRequest) {
          return new XMLHttpRequest();
      } else if (window.ActiveXObject) {
          isIE = true;
          return new ActiveXObject("Microsoft.XMLHTTP");
      }
  }
  function doCompletion() {
      if (completeField.value == "") {
          clearTable();
      } else {
          var url = "autocomplete?action=complete&id=" + 
                  escape(completeField.value);
          var req = initRequest();
          req.onreadystatechange = function() {
              if (req.readyState == 4) {
                  if (req.status == 200) {
                      parseMessages(req.responseXML);
                  } else if (req.status == 204){
                      clearTable();
                  }
              }
          };
          req.open("GET", url, true);
          req.send(null);
      }
  }

The XMLHttpRequest object is not currently part of standard JavaScript (efforts are underway to standardize it), but is a de facto standard and is the heart of AJAX. This object is responsible for interacting over HTTP with a server-side component (in this case, a servlet).

Three parameters are specified when you create an XMLHttpRequest object: a URL, the HTTP method (GET or POST), and whether or not the interaction is asynchronous. In the XMLHttpRequest example, the parameters are:

  • The URL autocomplete, and the text from the complete-field (an M character):
                var url = "autocomplete?action=complete&id=" + 
                        escape(completeField.value);
  • GET, signifying the HTTP interactions uses the GET method, and true, signifying that the interaction is asynchronous:
                req.open("GET", url, true); 

A callback function needs to be set when you use asynchronous calls. This callback function is called asynchronously at specific points during HTTP interaction when the readyState property on the XMLHttpRequest changes. In the example the callback function is processRequest(). It's set as the XMLHttpRequest.onreadystatechange property to a function. Notice the call to the parseMessages function when the readState is "4". The XMLHttpRequest.readyState of "4" signifies the successful completion of the HTTP interaction.

The HTTP interaction begins when XMLHttpRequest.send() is called. If the interaction is asynchronous, the browser continues to process events in the page.

On the Server

The XMLHttpRequest makes an HTTP GET request to the URL autocomplete, which is mapped to a servlet called AutoComplete. The doGet() method of the AutoComplete servlet is called. Here is what the doGet() method looks like:

  public void doGet(HttpServletRequest request, 
          HttpServletResponse response) 
       throws IOException, ServletException { 
      ... 
      String targetId = request.getParameter("id");
      if (targetId != null) targetId = targetId.trim().toLowerCase();
      Iterator it = employees.keySet().iterator();
      while (it.hasNext()) {
          EmployeeBean e = (EmployeeBean)employees.get(
                  (String)it.next());
          if ((targetId != null) &&
             (e.getFirstName().toLowerCase ().startsWith(targetId) ||
             e.getLastName().toLowerCase().startsWith(targetId))
             && !targetId.equals("")) {
             sb.append("<employee>"); 
             sb.append("<id>" + e.getId() + "</id>"); 
             sb.append("<firstName>" + e.getFirstName() + 
                     "</firstName>"); 
             sb.append("<lastName>" + e.getLastName() + 
                     "</lastName>"); 
             sb.append("</employee>"); 
             namesAdded = true; 
          } 
      } 
      if (namesAdded) { 
          response.setContentType("text/xml"); 
          response.setHeader("Cache-Control", "no-cache"); 
          response.getWriter().write("<employees>" + 
                  sb.toString() + "</employees>"); 
      } else { 
          response.setStatus(HttpServletResponse.SC_NO_CONTENT); 
      } 
   }

As you can see in this servlet, there is nothing really new you need to learn to write server-side code for AJAX processing. The response content type needs to be set to text/xml for cases where you want to exchange XML documents. With AJAX, you can also exchange plain text or even snippets of JavaScript which may be evaluated or executed by the callback function on the client. Note too that some browsers might cache the results, and so it might be necessary to set the Cache-Control HTTP header to no-cache. In this example, the servlet generates an XML document that contains all employees with a first or last name beginning with the character M. Here is an example of an XML document that is returned to the XMLHttpRequest object that made the call: <employees> <employee> <id>3</id> <firstName>George</firstName> <lastName>Murphy</lastName> </employee> <employee> <id>2</id> <firstName>Greg</firstName> <lastName>Murphy</lastName> </employee> <employee> <id>11</id><firstName>Cindy</firstName> <lastName>Murphy</lastName> </employee> <employee> <id>4</id> <firstName>George</firstName> <lastName>Murray</lastName> </employee> <employee> <id>1</id> <firstName>Greg</firstName> <lastName>Murray</lastName> </employee> </employees>

Returning to the Client

When the XMLHttpRequest object that made the initial call receives the response, it calls the parseMessages() function (see the initialization of the XMLHttpRequest earlier in this example for more details). Here is what the parseMessages() function looks like:

  function parseMessages(responseXML) {
      clearTable();
          var employees = responseXML.getElementsByTagName(
                  "employees")[0];
      if (employees.childNodes.length > 0) {
          completeTable.setAttribute("bordercolor", "black");
          completeTable.setAttribute("border", "1");
      } else {
          clearTable();
      }
   
      for (loop = 0; loop < employees.childNodes.length; loop++) {
          var employee = employees.childNodes[loop];
          var firstName = employee.getElementsByTagName(
                  "firstName")[0];
          var lastName = employee.getElementsByTagName(
                  "lastName")[0];
          var employeeId = employee.getElementsByTagName(
                  "id")[0];
          appendEmployee(
                  firstName.childNodes[0].nodeValue,
                  lastName.childNodes[0].nodeValue, 
                  employeeId.childNodes[0].nodeValue);
      }
  }

The parseMessages() function receives as a parameter an object representation of the XML document returned by the AutoComplete servlet. The function programmatically traverses the XML document, and then uses the results to update the contents of the HTML page. This is done by injecting into a element whose id is "menu-popup" the HTML source for the names in the XML document: