TO SET THE DELETE BUTTON’S EVENT HANDLER?

Một phần của tài liệu 917 foundations of ajax (Trang 136 - 143)

You may have noticed the method by which the Delete button’s event handler is set. You probably expected that the code to set the Delete button’s onclickevent handler would look something like this:

deleteButton.setAttribute("onclick", "deleteEmployee('" + unique_id + "');");

Indeed, this code is technically correct, follows W3C standards, and works in most modern browsers with the notable exception of Internet Explorer. Fortunately, a workaround is available for Internet Explorer and also works in Firefox, Opera, Safari, and Konqueror.

The workaround consists of referencing the Delete button’s onclickevent handler using dot notation and then setting the event handler using an anonymous function that calls the deleteEmployeefunction.

Figure 4-14 shows the dynamic update example in action.

Accessing Web Services

Web Services are the latest attempt to solve an age-old software engineering problem: calling services or methods on one machine from another machine, even when the machines use com- pletely different hardware or software. A few years ago a lot of hype surrounded Web Services, as some considered them the Holy Grail of distributed software development. Since then much of the sheen has worn off, and Web Services have settled into a comfortable niche as a useful tool for enabling disparate computer systems to interoperate with one another.

Web Services are typically used as the communication pipeline between computer systems, much like Common Object Request Broker Architecture (CORBA), Remote Method Invocation (RMI), or Distributed Component Object Model (DCOM). The difference is that Web Services are vendor neutral and can be implemented by a wide variety of programming tools and platforms.

To enable a high level of interoperability, Web Services are a text-based protocol often imple- mented over HTTP. Since they are a text-based protocol, Web Services almost always use XML in some variety.

The most well-known Web Services implementation is Simple Object Access Protocol (SOAP). SOAP is a specification managed by the W3C. It is an XML protocol that provides a definition of how to call remote procedures.

A Web Services Description Language (WSDL) document is an XML document that describes how to create a client to a Web Service. By providing a WSDL document, a Web Service provider simplifies the task of creating client-side code for potential clients. WSDL and SOAP are often used together, but this is not necessary, as the two specifications are maintained separately.

Figure 4-14.Each name is dynamically added to the list each time the Add button is clicked, without refreshing the page each time.

Despite the efforts made to simplify SOAP implementations, SOAP remains a difficult technology to employ, and thus its use has often been relegated to situations where cross- platform interoperability is truly an important requirement. A simpler approach to Web Services called REpresentational State Transfer (REST) is gaining popularity with developers who want 80 percent of SOAP’s benefits at only 20 percent of the cost.

Yahoo! has chosen REST as the protocol for its public Web Services. Yahoo! believes that REST-based services are easy to understand and likes REST’s accessibility from most modern programming languages. In fact, Yahoo! believes REST has a lower barrier of entry and is eas- ier to use than SOAP.

Using REST, you can form a request by starting with a service entry URL and then appending search parameters to the query string. The results are returned by the service as an XML document. Does this pattern sound familiar? That’s right—it’s identical to the Ajax examples you’ve been working with throughout the book.

The XMLHttpRequest object is the perfect client for REST-based Web Services. Using the XMLHttpRequest object, you can asynchronously send a request to a Web Service and parse the resulting XML response. In the case of Yahoo! Web Services, the XMLHttpRequest object can send a request to Yahoo! to search for a specified term. Once Yahoo! returns a response, JavaScript DOM methods parse the response and dynamically render the result data to the page.

Listing 4-15 demonstrates how to use Ajax techniques to access Yahoo! Web Services and render the results to the page. The text field on the page allows the user to specify the term on which to perform the search. The select box enables the user to specify how many results to display. Clicking the Submit button initiates the search.

But wait! In Chapter 3 you learned that the XMLHttpRequest object could access resources only within the same domain from which the containing document originated. Attempting to access a resource from another domain may fail because of security restrictions imposed by the browser. How do you get around that?

You have a few options. As you learned in Chapter 3, browsers implement the security sandbox differently. Internet Explorer will ask the user if it’s OK to access a resource at a differ- ent domain. Firefox will automatically fail with an error, although you can avoid this with Firefox-specific JavaScript code.

Another option, and the option used in this example, is to create a gateway to Yahoo! that lives in the same domain as the XMLHttpRequest script. The gateway accepts the request from the XMLHttpRequest object and forwards it to Yahoo! Web Services. When Yahoo! responds with the results, the gateway simply routes the results to the browser. By using this approach, you avoid having to use browser-specific JavaScript. Additionally, this approach is more robust, because you could extend the gateway to include other Web Service providers.

Listing 4-15.yahooSearch.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>Yahoo! Search Web Services</title>

<script type="text/javascript">

var xmlHttp;

function createXMLHttpRequest() { if (window.ActiveXObject) {

xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");

}

else if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest();

} }

function doSearch() {

var url = "YahooSearchGateway?" + createQueryString()

+ "&ts=" + new Date().getTime();

createXMLHttpRequest();

xmlHttp.onreadystatechange = handleStateChange;

xmlHttp.open("GET", url, true);

xmlHttp.send(null);

}

function createQueryString() {

var searchString = document.getElementById("searchString").value;

searchString = escape(searchString);

var maxResultsCount = document.getElementById("maxResultCount").value;

var queryString = "query=" + searchString + "&results=" + maxResultsCount;

return queryString;

}

function handleStateChange() { if(xmlHttp.readyState == 4) {

if(xmlHttp.status == 200) { parseSearchResults();

} else {

alert("Error accessing Yahoo! search");

} } }

function parseSearchResults() {

var resultsDiv = document.getElementById("results");

while(resultsDiv.childNodes.length > 0) {

resultsDiv.removeChild(resultsDiv.childNodes[0]);

}

var allResults = xmlHttp.responseXML.getElementsByTagName("Result");

var result = null;

for(var i = 0; i < allResults.length; i++) { result = allResults[i];

parseResult(result);

} }

function parseResult(result) {

var resultDiv = document.createElement("div");

var title = document.createElement("h3");

title.appendChild(document.createTextNode(

getChildElementText(result, "Title")));

resultDiv.appendChild(title);

var summary = document.createTextNode(getChildElementText(result, "Summary"));

resultDiv.appendChild(summary);

resultDiv.appendChild(document.createElement("br"));

var clickHere = document.createElement("a");

clickHere.setAttribute("href", getChildElementText(result, "ClickUrl"));

clickHere.appendChild(document.createTextNode

(getChildElementText(result, "Url")));

resultDiv.appendChild(clickHere);

document.getElementById("results").appendChild(resultDiv);

}

function getChildElementText(parentNode, childTagName) {

var childTag = parentNode.getElementsByTagName(childTagName);

return childTag[0].firstChild.nodeValue;

}

</script>

</head>

<body>

<h1>Web Search Using Yahoo! Search Web Services</h1>

<form action="#">

Search String: <input type="text" id="searchString"/>

<br/><br/>

Max Number of Results:

<select id="maxResultCount">

<option value="1">1</option>

<option value="10">10</option>

<option value="25">25</option>

<option value="50">50</option>

</select>

<br/><br/>

<input type="button" value="Submit" onclick="doSearch();"/>

</form>

<h2>Results:</h2>

<div id="results"/>

</body>

</html>

Clicking the Submit button on the page calls the doSearchfunction. This function creates the target URL by using the createQueryStringfunction that is responsible for placing the search term and maximum desired results into the query string. Note that the names of the parameters, queryand results, are defined by the Yahoo! Search API.

The query string created by createQueryStringis sent to the Yahoo! Search gateway. In this example, the gateway is implemented as a Java servlet named YahooSearchGatewayServlet (see Listing 4-16). The premise of this servlet is simple: forward all requests to the Yahoo! Search URL and stream the results to the browser. Certainly this gateway could be implemented in lan- guages other than Java. The gateway is simple but solves the problem of the XMLHttpRequest object needing to access resources in another domain.

Listing 4-16.YahooSearchGatewayServlet.java package ajaxbook.chap4;

import java.io.*;

import java.net.HttpURLConnection;

import java.net.URL;

import javax.servlet.*;

import javax.servlet.http.*;

public class YahooSearchGatewayServlet extends HttpServlet { private static final String YAHOO_SEARCH_URL =

"http://api.search.yahoo.com/WebSearchService/V1/webSearch?"

+ "appid=your_app_id" + "&type=all";

protected void processRequest(HttpServletRequest request

, HttpServletResponse response) throws ServletException, IOException {

String url = YAHOO_SEARCH_URL + "&" + request.getQueryString();

HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection();

con.setDoInput(true);

con.setDoOutput(true);

con.setRequestMethod("GET");

//Send back the response to the browser response.setStatus(con.getResponseCode());

response.setContentType("text/xml");

BufferedReader reader =

new BufferedReader(new InputStreamReader(con.getInputStream()));

String input = null;

OutputStream responseOutput = response.getOutputStream();

while((input = reader.readLine()) != null) { responseOutput.write(input.getBytes());

} }

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

processRequest(request, response);

} }

Once Yahoo! Search returns the results to the gateway and the gateway forwards the results to the browser, the parseSearchResultsfunction is called. This function retrieves the resulting XML document from the XMLHttpRequest object and looks for all elements with a tag name of Result.

Each Resultelement is passed to the parseResultfunction. This function creates the content that is added to the page using the Title,Summary,ClickUrl, and Urlelements that are children of the Resultelement.

As you can see, Ajax techniques are quite powerful when combined with REST-based Web Services. If you want to access Web Services within your own domain, then you can do all this work with JavaScript. Otherwise, you should create some sort of gateway to the external resource to avoid browser security sandbox issues when trying to access a resource in another domain.

Figure 4-15 shows the results of using Yahoo! Search Web Services with Ajax.

Một phần của tài liệu 917 foundations of ajax (Trang 136 - 143)

Tải bản đầy đủ (PDF)

(297 trang)