1. Trang chủ
  2. » Công Nghệ Thông Tin

build your own ajax web applications PHẦN 9 pptx

32 334 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 32
Dung lượng 465,65 KB

Nội dung

the solution’s “hackishness.” The end result will not work well with assistive technology like screen readers, and won’t work in Safari at all. In short, the fix works like this: ❑ Store the history position in the page’s address after the hash that’s usually reserved for internal page navigation (e.g., mypage.html#section1). ❑ Run a process on a timer that synchronizes the page state with what it sees in the page address. The Hash The part of a web address that appears after the pound or hash sign is known by many names. Here, we’ll refer to it as the hash. Using the Location Hash This solution works because the browser history tracks all changes to the page address, including changes to the hash. So if you set it up right, as you run your searches, the page URI displayed in the location bar will change like so: webservices2.html webservices2.html#0 webservices2.html#1 webservices2.html#2 webservices2.html#3 This allows users to click back and forth in the normal browser history and pull up the appropriate search history entry. Breaking Accessibility Because this fix co-opts the internal navigation hash to store the search-history position, internal links such as skip navigation links will break this technique. Setting Up the Fix Way back when we added the init method to our Search class, we set it up to call startHist when BROWSER_BACK was set to true. This startHist method sets up some of the IE-specific stuff for us, and activates the process we’ll be using 235 Using the Location Hash Licensed to siowchen@darke.biz to synchronize the history state to the one that’s indicated in the browser’s loca- tion bar. Here’s the code: File: webservices2.js (excerpt) this.startHist = function() { var self = Search; var href = ''; var ifr = null if (document.all) { ifr = document.createElement('iframe'); ifr.name = 'historyFrame'; ifr.id = 'historyFrame'; ifr.src = ''; ifr.style.display = 'none'; document.body.appendChild(ifr); } if (location.hash) { href = location.href.split('#')[0]; location = href; } setInterval(self.watchHist, 100); }; The first big chunk of code uses DOM methods to create the iframe that allows this hack to work in IE. Note that this means that our page must be declared as XHTML 1.0 (or HTML 4.01) Transitional, since iframe is not supported in Strict. Supporting Older Versions of IE If you want this solution to support versions of Internet Explorer that are older than version 6, you’ll either have to include your iframe in the initial markup for the page, or use document.write to insert it. This would mean sticking with HTML 4.01, since XHTML throws out support for document.write. I’ll explain more about why this iframe is necessary in the next section. Next, startHist removes any hash that appears in the page’s address, then uses setInterval to start up the process that synchronizes the page state with what’s reported in the page address. 236 Chapter 7: More Web Services and a Back Button Licensed to siowchen@darke.biz Setting the Hash Next, we need some code that will set the hash in the page address for each new search entry. Adding the hash to the page address creates the history trail through which users can page back and forth using the browser’s built-in Back and Forward buttons. In updateHistory, there’s a call to a method named setHash, which we use to append the search history index to the hash in the location. The code for setHash looks like this: File: webservices2.js (excerpt) this.setHash = function(val) { if (val == 0) { location.replace('#' + val); } else { location = '#' + val; } if (document.all) { document.getElementById('historyFrame').src = 'blank.txt?' + val; } }; In the top part of this code, you can see that it adds the new hash onto the current location. It’s just as if the user were clicking an internal navigation link on a web page, except that, in this case, instead of setting the location to something like #searchResults, we’re just setting it to a number, such as #2 or #37, to indicate the search history entry we’re looking at. The iframe Hack for IE Unfortunately, IE doesn’t make history entries for locations that reflect the page’s internal navigation, so although you can change the page’s address by adding a hash, IE won’t keep track of these changes in its history. To get this solution to work in IE, we need to resort to a hack. This is where things get a little ugly. It turns out that you can trick IE into making history entries by creating an invisible iframe andhaving it make requests to a dummy placeholder page. You stick the history index value onto the query string of the requested page (in this case, a blank text file) and use this, when you’re paging through the history, to know which entry to display. 237 Setting the Hash Licensed to siowchen@darke.biz As you perform searches, the following addresses will be loaded into the iframe: blank.txt?0 blank.txt?1 blank.txt?2 blank.txt?3 So, for IE, you’re making the actual AJAX request to the server to get the data, and, at the same time, you’re making a bogus request to a blank document on the server in order to have the browser store a history entry for that search. Watching the Hash At the very beginning of this solution, we started up a process with setInterval that calls the watchHist method in a tight loop; this method watches for changes in the location hash as the user clicks Back or Forward, and displays whatever search history entry the user has selected. The first half of the method contains all of the IE-specific code that pulls the history index out of the location in the iframe: File: webservices2.js (excerpt) this.watchHist = function() { var self = Search; var href = ''; var index = 0; var hash = ''; if (document.all) { href = frames['historyFrame'].document.location.href; hash = href.split('?')[1]; if (hash) { hash = '#' + hash; } else { hash = ''; } if (hash && location.hash && (hash != location.hash)) { location.replace(hash); } } The location of the iframe will change as users click back and forth through the history. The code looks at the current location of the iframe, pulls the number from the query string, and then compares it to the value on the hash in 238 Chapter 7: More Web Services and a Back Button Licensed to siowchen@darke.biz the location bar. If there’s been any change—that is, if the user has clicked Back or Forward since the last cycle through this method—the code synchronizes the hash in the location bar with the query string value using location.replace. Now that we have the correct history position loaded in the hash in the location bar, the code is the same for both browsers from this point forward: File: webservices2.js (excerpt) if (location.hash) { index = parseInt(location.hash.substr(1)); } else { index = -1; } if (index != self.histIndex) { self.goHistoryEntry(index); } }; This code pulls the search history index off the hash, and compares it with the value that’s set in the histIndex property of the Search object. Any time there’s a change—when the user clicks forward or backward through the history—it calls the goHistoryEntry method to go to that specific entry. Displaying the Entry The goHistoryEntry code looks like this: File: webservices2.js (excerpt) this.goHistoryEntry = function(val) { var self = Search; self.histIndex = val; self.showHistory(); }; This code is pretty simple—it just sets the histIndex property to the value that was passed in, then calls the showHistory method. At this point, we’re finally hooked into the normal code for displaying search-history entries. The rest of the history navigation process works exactly the same way 239 Displaying the Entry Licensed to siowchen@darke.biz Decisions, Decisions It is pretty cool to click the built-in Back and Forward buttons in your browser, and see your AJAX application change state to match, just as a normal series of web pages would. However, the weird coding acrobatics needed to produce this happy state of affairs definitely hark back to the bad old days before we had widespread support for web standards or AJAX; of course, the solution also isn’t cross-browser compatible and breaks screen reader support. Your decision about whether to work around the AJAX Back button problem by implementing your own set of buttons, or to do the coding gymnastics needed to make those built-in buttons behave properly, will depend on things like how easily your users take on and learn new things, which browsers you need to sup- port, the emphasis you place on accessibility, and your tolerance for having browser-specific hacks in your code. Search App Enhancements This search application is a nice start, but we could implement a few enhancements that would make it much nicer to use. Paging Currently, the application returns only the first page of results at the default page size set by the selected web service. Most of the web services allow you to specify within your query how many records you want per page, and how many pages you want to have in the results set. This allows you to create the same kind of pagination you’d see on Google, Amazon, eBay, and any number of other sites that allow searching. History Menu It would be fairly easy to extend the history code to include a history menu that would give the user easier access to previous searches. For instance, you could maintain a list of previous searches in a drop-down list or a div. 240 Chapter 7: More Web Services and a Back Button Licensed to siowchen@darke.biz Further Reading Here are some online resources for learning more about the techniques and con- cepts we’ve discussed in this chapter. Apache2 and OpenSSL on Linux http://www.devside.net/web/server/linux This is a step-by-step instruction guide to building a web server. http://www.debian-administration.org/articles/357 These documents explain setting up a LAMP server on Debian Sarge with Apache2, PHP5, MySQL5, phpMyAdmin, Smarty, and ADODB. The inform- ation covers installation and just enough sample code to let you test everything. http://www.tc.umn.edu/~brams006/selfsign.html This is a step-by-step guide to creating a self-signed server certificate with OpenSSL on Linux. http://czarism.com/debian-ubuntu-apache2-and-openssl-https This document explains the steps involved in enabling OpenSSL encryption using the available Apache2 package in the apt-get repositories (for Debian and Ubuntu Linux). Apache2 and OpenSSL on Windows http://www.devside.net/web/server/windows This provides step-by-step instructions for building a web server. http://raibledesigns.com/wiki/Wiki.jsp?page=ApacheSSL This document describes the installation of the Win32 version of Apache with the mod_ssl extension. WSDL http://www.w3schools.com/wsdl/default.asp This is the WSDL tutorial at the W3 Schools. 241 Further Reading Licensed to siowchen@darke.biz http://www.ibm.com/developerworks/library/ws-soap/index.html This tutorial explains the ins and outs of using WSDL in SOAP applica- tions—it’s a solid introduction to WSDL for SOAP programmers. http://www.w3.org/TR/wsdl This is a note published by the World Wide Web Consortium (for discussion purposes only). This draft represents the current thinking within Ariba, IBM, and Microsoft. Summary In this chapter, we built an accessible “ Web 2.0”-style application that searches multiple web services and displays the results in a single search interface. This app provides a good example of how AJAX makes things more convenient for the end user by reducing the need for page refreshes, but it also fails to meet user expectations about the way their browsers’ navigation should work. This issue, known as the Back button problem, can be fixed either by implementing your own history navigation within the application, or—if you’re willing to tolerate some hackishness in your code, and don’t want the app to be accessible to screen readers—you can hack the browser’s Back button to work as users think it should. 242 Chapter 7: More Web Services and a Back Button Licensed to siowchen@darke.biz Drag and Drop with AJAX Chess 8 I’m following your orders, Captain. Queen to queen’s level three. —Scott, Star Trek, The Original Series Episode 71: Whom Gods Destroy One of the biggest benefits that AJAX has brought to browser-based programming is that it gives us the ability to achieve within the user interface tasks that previ- ously could only be done in a traditional installed desktop application. This is where a lot of the hype around AJAX comes from: the idea that a web-based ap- plication can mimic—and sometimes even replace—an application that you would previously have had to install on your computer. One of the user interface features that’s very popular in both desktop and AJAX apps is drag-and-drop—the ability to click on UI elements and drag them around the screen. Drag-and-drop has been possible for some time in browsers that sup- port plain DHTML. However, marrying that functionality with the asynchronous connections that AJAX makes possible gives developers some very powerful pos- sibilities in terms of the new features we can build into web applications. AJAX Chess Games development has always been a forum that encouraged the creation of new functionality and features within the computer world. And though we won’t see browser-based versions of Unreal Tournament any time soon, a game is still Licensed to siowchen@darke.biz a very appropriate way to demonstrate what’s possible when you combine drag- and-drop with AJAX. In this chapter, we’re going to develop a multi-player-capable AJAX chess game. Figure 8.1 shows what the finished product will look like. Figure 8.1. AJAX Chess in action Problems to Solve The chess game will be the most sophisticated application in this book, and provides the chance to apply a lot of the techniques you’ve learned in previous chapters. It will also demonstrate real solutions to some of the thorniest problems that face AJAX application developers as their apps become more and more 244 Chapter 8: Drag and Drop with AJAX Chess Licensed to siowchen@darke.biz [...]... document.onmousedown, like so: File: chess.js (excerpt) document.onmousedown = Chess.mouseDownHandler; 2 59 Licensed to siowchen@darke.biz Chapter 8: Drag and Drop with AJAX Chess Now, every click of the mouse anywhere in the browser window will call the mouseDownHandler method of our Chess class Here’s the code for that method: File: chess.js (excerpt) this.mouseDownHandler = function(e) { var self = Chess; var id =... supported by the various DOM elements in your page Some examples of technique include the ubiquitous window.onload event we use to start up our applications, and element.onclick, which will handle a mouse click on just about any element Using DOM events like this makes it easy to have your browser-based UI respond to user input in lots of interesting ways However, as web applications become more complicated,... the json.js file, which you can download from the JSON web site.1 Using JSON in JavaScript is as simple as taking an object and converting it into a string using the JSON stringify method, like so: var cmd = new Command('load'); var str = JSON.stringify(cmd); Voila! Now str contains cmd as a string, and you can pass it around very easily—you can even pass it back to your web server to use it there To... to turn your JSON-encoded string back into an object for use with your back-end language of choice The JSON web site2 offers links to a large number of such libraries For our chess game’s PHP back end, we’re using Services_JSON, which, as I write this, is a proposed addition to PHP’s PEAR repository It’s not a full PEAR release yet, but it’s perfectly usable and is currently available for download... more to give users the responsive, interactive experience they expect from a modern web app And as the interface gets more complicated, it can become increasingly difficult to keep track of the event handlers you’re using, and what actually happens in your app when you click, double-click, or mouse over certain parts of your application’s user interface Going Global The solution to the handler tracking... the asynchronous world of AJAX programming, this is hugely helpful in managing your app’s complexity, and in debugging when things go wrong Handling Mouse Clicks Let’s start with the most basic example of an event dispatch: dispatching mouse clicks To create a mouse click dispatcher, we create a global event handler for mouse clicks by attaching a handler to document.onmousedown, like so: File: chess.js... the browser and the server in an AJAX web application JSON has become increasingly popular because it’s much more light-weight, and easier to work with in JavaScript, than XML Note that JSON does not handle complex data types like dates, but this isn’t a huge drawback for the kind of data interchange we’re completing here Encoding an Object with JSON To use JSON in your browser-side JavaScript code,...The Chess Class complicated Here’s a brief list of the functionality we’ll be building into this application: ❑ placing interface elements relative to browser window size while using absolute positioning ❑ allowing users to interact with lots of elements on the page without cluttering up your code with loads of event handlers ❑ implementing drag-and-drop capabilities within the boundaries... some initial properties and a constant: File: chess.js (excerpt) var REFRESH_INTERVAL = 5; var Chess = new function() { this .ajax = null; this.boardDiv = null; this.leftPos = 0; this.topPos = 0; this.squareSize = 56; 245 Licensed to siowchen@darke.biz Chapter 8: Drag and Drop with AJAX Chess this.boardSize = this.squareSize * 8; this.pieceOffset = 10; this.pieceSize = this.squareSize - (this.pieceOffset... valid JavaScript that will work just fine in all modern browsers 1 http://www.json.org/ 251 Licensed to siowchen@darke.biz Chapter 8: Drag and Drop with AJAX Chess On the other hand, if it’s possible that a third party could be inserting malicious code into your data, you can use the JSON parse method, which is slower, but much, much safer than eval This is how we could make our JSON string into an object: . right, as you run your searches, the page URI displayed in the location bar will change like so: webservices2.html webservices2.html#0 webservices2.html#1 webservices2.html#2 webservices2.html#3 This. asynchronous connections that AJAX makes possible gives developers some very powerful pos- sibilities in terms of the new features we can build into web applications. AJAX Chess Games development. or AJAX; of course, the solution also isn’t cross-browser compatible and breaks screen reader support. Your decision about whether to work around the AJAX Back button problem by implementing your

Ngày đăng: 12/08/2014, 09:21