- •preface
- •acknowledgments
- •about this book
- •Who should read this book?
- •Roadmap
- •Code conventions
- •Code downloads
- •Author Online
- •About the title
- •About the cover illustration
- •Rethinking the web application
- •A new design for the Web
- •1.1 Why Ajax rich clients?
- •1.1.1 Comparing the user experiences
- •1.1.2 Network latency
- •1.1.3 Asynchronous interactions
- •1.1.4 Sovereign and transient usage patterns
- •1.1.5 Unlearning the Web
- •1.2 The four defining principles of Ajax
- •1.2.1 The browser hosts an application, not content
- •1.2.2 The server delivers data, not content
- •1.2.3 User interaction with the application can be fluid and continuous
- •1.2.4 This is real coding and requires discipline
- •1.3 Ajax rich clients in the real world
- •1.3.1 Surveying the field
- •1.3.2 Google Maps
- •1.4 Alternatives to Ajax
- •1.4.2 Java Web Start and related technologies
- •1.5 Summary
- •1.6 Resources
- •First steps with Ajax
- •2.1 The key elements of Ajax
- •2.2 Orchestrating the user experience with JavaScript
- •2.3 Defining look and feel using CSS
- •2.3.1 CSS selectors
- •2.3.2 CSS style properties
- •2.3.3 A simple CSS example
- •2.4 Organizing the view using the DOM
- •2.4.1 Working with the DOM using JavaScript
- •2.4.2 Finding a DOM node
- •2.4.3 Creating a DOM node
- •2.4.4 Adding styles to your document
- •2.4.5 A shortcut: Using the innerHTML property
- •2.5 Loading data asynchronously using XML technologies
- •2.5.1 IFrames
- •2.5.2 XmlDocument and XMLHttpRequest objects
- •2.5.3 Sending a request to the server
- •2.5.4 Using callback functions to monitor the request
- •2.5.5 The full lifecycle
- •2.6 What sets Ajax apart
- •2.7 Summary
- •2.8 Resources
- •Introducing order to Ajax
- •3.1 Order out of chaos
- •3.1.1 Patterns: creating a common vocabulary
- •3.1.2 Refactoring and Ajax
- •3.1.3 Keeping a sense of proportion
- •3.1.4 Refactoring in action
- •3.2 Some small refactoring case studies
- •3.2.2 Managing event handlers: Observer pattern
- •3.2.3 Reusing user action handlers: Command pattern
- •3.2.4 Keeping only one reference to a resource: Singleton pattern
- •3.3 Model-View-Controller
- •3.4 Web server MVC
- •3.4.1 The Ajax web server tier without patterns
- •3.4.2 Refactoring the domain model
- •3.4.3 Separating content from presentation
- •3.5 Third-party libraries and frameworks
- •3.5.2 Widgets and widget suites
- •3.5.3 Application frameworks
- •3.6 Summary
- •3.7 Resources
- •Core techniques
- •The page as an application
- •4.1 A different kind of MVC
- •4.1.1 Repeating the pattern at different scales
- •4.1.2 Applying MVC in the browser
- •4.2 The View in an Ajax application
- •4.2.1 Keeping the logic out of the View
- •4.2.2 Keeping the View out of the logic
- •4.3 The Controller in an Ajax application
- •4.3.1 Classic JavaScript event handlers
- •4.3.2 The W3C event model
- •4.3.3 Implementing a flexible event model in JavaScript
- •4.4 Models in an Ajax application
- •4.4.1 Using JavaScript to model the business domain
- •4.4.2 Interacting with the server
- •4.5 Generating the View from the Model
- •4.5.1 Reflecting on a JavaScript object
- •4.5.2 Dealing with arrays and objects
- •4.5.3 Adding a Controller
- •4.6 Summary
- •4.7 Resources
- •The role of the server
- •5.1 Working with the server side
- •5.2 Coding the server side
- •5.2.1 Popular implementation languages
- •5.3 The big picture: common server-side designs
- •5.3.1 Naive web server coding without a framework
- •5.3.2 Working with Model2 workflow frameworks
- •5.4 The details: exchanging data
- •5.4.2 Introducing the planet browser example
- •5.5 Writing to the server
- •5.5.1 Using HTML forms
- •5.5.2 Using the XMLHttpRequest object
- •5.5.3 Managing user updates effectively
- •5.6 Summary
- •5.7 Resources
- •Professional Ajax
- •The user experience
- •6.1 Getting it right: building a quality application
- •6.1.1 Responsiveness
- •6.1.2 Robustness
- •6.1.3 Consistency
- •6.1.4 Simplicity
- •6.1.5 Making it work
- •6.2 Keeping the user informed
- •6.2.1 Handling responses to our own requests
- •6.2.2 Handling updates from other users
- •6.3 Designing a notification system for Ajax
- •6.3.1 Modeling notifications
- •6.3.2 Defining user interface requirements
- •6.4 Implementing a notification framework
- •6.4.1 Rendering status bar icons
- •6.4.2 Rendering detailed notifications
- •6.4.3 Putting the pieces together
- •6.5 Using the framework with network requests
- •6.6 Indicating freshness of data
- •6.6.1 Defining a simple highlighting style
- •6.6.2 Highlighting with the Scriptaculous Effects library
- •6.7 Summary
- •6.8 Resources
- •Security and Ajax
- •7.1 JavaScript and browser security
- •7.1.1 Introducing the “server of origin” policy
- •7.1.2 Considerations for Ajax
- •7.1.3 Problems with subdomains
- •7.2 Communicating with remote services
- •7.2.1 Proxying remote services
- •7.2.2 Working with web services
- •7.3 Protecting confidential data
- •7.3.1 The man in the middle
- •7.3.2 Using secure HTTP
- •7.3.3 Encrypting data over plain HTTP using JavaScript
- •7.4 Policing access to Ajax data streams
- •7.4.1 Designing a secure web tier
- •7.4.2 Restricting access to web data
- •7.5 Summary
- •7.6 Resources
- •Performance
- •8.1 What is performance?
- •8.2 JavaScript execution speed
- •8.2.1 Timing your application the hard way
- •8.2.2 Using the Venkman profiler
- •8.2.3 Optimizing execution speed for Ajax
- •8.3 JavaScript memory footprint
- •8.3.1 Avoiding memory leaks
- •8.3.2 Special considerations for Ajax
- •8.4 Designing for performance
- •8.4.1 Measuring memory footprint
- •8.4.2 A simple example
- •8.5 Summary
- •8.6 Resources
- •Ajax by example
- •Dynamic double combo
- •9.1 A double-combo script
- •9.2 The client-side architecture
- •9.2.1 Designing the form
- •9.2.2 Designing the client/server interactions
- •9.3 Implementing the server: VB .NET
- •9.3.1 Defining the XML response format
- •9.4 Presenting the results
- •9.4.1 Navigating the XML document
- •9.4.2 Applying Cascading Style Sheets
- •9.5 Advanced issues
- •9.5.2 Moving from a double combo to a triple combo
- •9.6 Refactoring
- •9.6.1 New and improved net.ContentLoader
- •9.7 Summary
- •Type-ahead suggest
- •10.1 Examining type-ahead applications
- •10.1.2 Google Suggest
- •10.2.1 The server and the database
- •10.3 The client-side framework
- •10.3.1 The HTML
- •10.3.2 The JavaScript
- •10.3.3 Accessing the server
- •10.5 Refactoring
- •10.5.1 Day 1: developing the TextSuggest component game plan
- •10.5.3 Day 3: Ajax enabled
- •10.5.4 Day 4: handling events
- •10.5.6 Refactor debriefing
- •10.6 Summary
- •11.1 The evolving portal
- •11.1.1 The classic portal
- •11.1.2 The rich user interface portal
- •11.2 The Ajax portal architecture using Java
- •11.3 The Ajax login
- •11.3.1 The user table
- •11.4 Implementing DHTML windows
- •11.4.1 The portal windows database
- •11.4.3 Adding the JS external library
- •11.5 Adding Ajax autosave functionality
- •11.5.1 Adapting the library
- •11.5.2 Autosaving the information to the database
- •11.6 Refactoring
- •11.6.1 Defining the constructor
- •11.6.2 Adapting the AjaxWindows.js library
- •11.6.3 Specifying the portal commands
- •11.6.4 Performing the Ajax processing
- •11.6.5 Refactoring debrief
- •11.7 Summary
- •Live search using XSLT
- •12.1 Understanding the search techniques
- •12.1.1 Looking at the classic search
- •12.1.3 Examining a live search with Ajax and XSLT
- •12.1.4 Sending the results back to the client
- •12.2 The client-side code
- •12.2.1 Setting up the client
- •12.2.2 Initiating the process
- •12.3 The server-side code: PHP
- •12.3.1 Building the XML document
- •12.3.2 Building the XSLT document
- •12.4 Combining the XSLT and XML documents
- •12.4.1 Working with Microsoft Internet Explorer
- •12.4.2 Working with Mozilla
- •12.5 Completing the search
- •12.5.1 Applying a Cascading Style Sheet
- •12.5.2 Improving the search
- •12.5.3 Deciding to use XSLT
- •12.5.4 Overcoming the Ajax bookmark pitfall
- •12.6 Refactoring
- •12.6.1 An XSLTHelper
- •12.6.2 A live search component
- •12.6.3 Refactoring debriefing
- •12.7 Summary
- •Building stand-alone applications with Ajax
- •13.1 Reading information from the outside world
- •13.1.1 Discovering XML feeds
- •13.1.2 Examining the RSS structure
- •13.2 Creating the rich user interface
- •13.2.1 The process
- •13.2.3 Compliant CSS formatting
- •13.3 Loading the RSS feeds
- •13.3.1 Global scope
- •13.3.2 Ajax preloading functionality
- •13.4 Adding a rich transition effect
- •13.4.2 Implementing the fading transition
- •13.4.3 Integrating JavaScript timers
- •13.5 Additional functionality
- •13.5.1 Inserting additional feeds
- •13.5.2 Integrating the skipping and pausing functionality
- •13.6 Avoiding the project’s restrictions
- •13.6.1 Overcoming Mozilla’s security restriction
- •13.6.2 Changing the application scope
- •13.7 Refactoring
- •13.7.1 RSS reader Model
- •13.7.2 RSS reader view
- •13.7.3 RSS reader Controller
- •13.7.4 Refactoring debrief
- •13.8 Summary
- •The Ajax craftsperson’s toolkit
- •A.1 Working smarter with the right toolset
- •A.1.1 Acquiring tools that fit
- •A.1.2 Building your own tools
- •A.1.3 Maintaining your toolkit
- •A.2 Editors and IDEs
- •A.2.1 What to look for in a code editor
- •A.2.2 Current offerings
- •A.3 Debuggers
- •A.3.1 Why we use a debugger
- •A.3.2 JavaScript debuggers
- •A.3.3 HTTP debuggers
- •A.3.4 Building your own cross-browser output console
- •A.4 DOM inspectors
- •A.4.1 Using the Mozilla DOM Inspector
- •A.4.2 DOM inspectors for Internet Explorer
- •A.4.3 The Safari DOM Inspector for Mac OS X
- •A.5 Installing Firefox extensions
- •A.6 Resources
- •JavaScript for object-oriented programmers
- •B.1 JavaScript is not Java
- •B.2 Objects in JavaScript
- •B.2.1 Building ad hoc objects
- •B.2.2 Constructor functions, classes, and prototypes
- •B.2.3 Extending built-in classes
- •B.2.4 Inheritance of prototypes
- •B.2.5 Reflecting on JavaScript objects
- •B.2.6 Interfaces and duck typing
- •B.3 Methods and functions
- •B.3.1 Functions as first-class citizens
- •B.3.2 Attaching functions to objects
- •B.3.3 Borrowing functions from other objects
- •B.3.4 Ajax event handling and function contexts
- •B.3.5 Closures in JavaScript
- •B.4 Conclusions
- •B.5 Resources
- •Ajax frameworks and libraries
- •Accesskey Underlining Library
- •ActiveWidgets
- •Ajax JavaServer Faces Framework
- •Ajax JSP Tag Library
- •Ajax.NET
- •AjaxAC
- •AjaxAspects
- •AjaxCaller
- •AjaxFaces
- •BackBase
- •Behaviour
- •Bindows
- •BlueShoes
- •CakePHP
- •CL-Ajax
- •ComfortASP.NET
- •Coolest DHTML Calendar
- •Dojo
- •DWR (Direct Web Remoting)
- •Echo 2
- •FCKEditor
- •Flash JavaScript Integration Kit
- •Google AjaxSLT
- •Guise
- •HTMLHttpRequest
- •Interactive Website Framework
- •Jackbe
- •JPSpan
- •jsolait
- •JSON
- •JSRS (JavaScript Remote Scripting)
- •LibXMLHttpRequest
- •Mochikit
- •netWindows
- •Oddpost
- •OpenRico
- •Pragmatic Objects
- •Prototype
- •Qooxdoo
- •RSLite
- •Ruby on Rails
- •Sack
- •SAJAX
- •Sarissa
- •Scriptaculous
- •SWATO…
- •Tibet
- •TinyMCE
- •TrimPath Templates
- •Walter Zorn’s DHTML Libraries
- •WebORB for .NET
- •WebORB for Java
- •XAJAX
- •x-Desktop
- •XHConn
- •index
- •Symbols
- •Numerics
362CHAPTER 10
Type-ahead suggest
Type-ahead suggest is one of the main applications of Ajax that has helped put Ajax into the mainstream world of programming. Google Suggest amazed people as they discovered a list of choosable suggestions appearing while they were typing (and even now, several months later, it still gives a buzz). It is as if a little helper is sitting next to you and telling you what you are looking for. Some people first thought they were storing values on the page, and others thought they were using a hidden IFrame to get the data. Google was actually using the XMLHttpRequest object to obtain the values for each keystroke.
In this chapter, you’ll learn how to send Ajax requests while the user is typing. We also examine the flaws of the available type-ahead suggest implementations and find ways to avoid these pitfalls in our application. At first we take a low-level approach that is easy to understand. After we get our application functioning, we reexamine it at a higher level, and use an object-oriented approach to gain more flexibility and usability. Before we build the application, though, let’s take a quick look at some of the typical type-ahead suggest features, and how we will design our application to use the best of those features.
10.1 Examining type-ahead applications
Since Ajax has become popular, the type-ahead suggest has been one of the most sought-after pieces of code. Many people have created different versions of the type-ahead suggest that handle the interaction with the server in many ways. A lot of the solutions out there have flaws, while others go way overboard. We first evaluate some of the functionality in many type-ahead suggest applications and then take a quick look at Google Suggest. After that, we'll design our application.
10.1.1Common type-ahead suggest features
Numerous type-ahead applications are available, from basic to advanced. Each of them does the same basic thing; some have fancy interfaces with fading transition effects. If you do a search for “type-ahead suggest Ajax,” you will find plenty of examples.
If you look at a few of them, you should see that they all perform the same type of actions:
1You type a character.
2The type-ahead makes a request to the server.
3It returns data to the client.
4The client takes that data and displays the results in the table, div, textbox, or some other format.
Examining type-ahead applications |
363 |
|
|
However, there are things that some of the scripts do not handle well. Developers need to take into consideration bandwidth, server capacity, and the client’s configuration. If you forget about these factors, Ajax may hurt your user’s experience instead of improving it.
The problems listed in table 10.1 are very common with Ajax applications.
Table 10.1 Problems with type-ahead suggest
Problem |
Result |
|
|
Posting back on every |
Large bandwidth consumption. Imagine the server-side bandwidth required |
keystroke |
for 1,000 users typing 10-characters words. |
|
|
Not caching data |
Requests are hitting the database each time even though they are return- |
|
ing a subset of data they already have. |
|
|
The 56K modem |
Yes, there are still people who dial in, and these users may see a lag in |
|
response time. |
|
|
Returning too many results |
Not limiting the results can send too much data to the client, slowing down |
|
response time. |
|
|
Too fancy an interface |
Fancy interfaces can be bad if they take a long time to render. |
|
|
Fast typists |
Some people can type fast. Certain type-ahead scripts have problems if |
|
the user is not a hunt-and-peck typist. |
|
|
Many developers tend to forget about bandwidth. Even one user who is filling in a simple word can post back a number of times. Combine this with a fast typist, and you can have more hits in a second than you normally would for the user’s entire session in a non-Ajax application.
Keeping the user interface responsive is also very important. The more time a control takes to render, the longer the user has to wait before seeing it, and the less effective the type-ahead suggest is. Delays can also be introduced by hitting the server too hard. If requests are made too frequently, or if they return too much data, the responsiveness of the user interface will suffer.
A good strategy for improving responsiveness is to cache the data on the client. (We can also cache data on the server, but that’s another issue, more familiar to developers of classic web apps.) A type-ahead suggest system will typically return fewer results as extra characters are typed, and these will often be a subset of earlier results. A simple implementation will discard previous requests and fetch all data from the server every time. A more intelligent solution might retain the results of the initial request and whittle away unwanted entries as the user types,
364CHAPTER 10
Type-ahead suggest
refreshing the user interface without going back to the server for every keystroke. This improves the application by increasing responsiveness and reducing the bandwidth. We’ll just be going through the result set that we have, making it quicker to pull the necessary information and eliminating the extra postbacks to the server.
That’s enough of the theory for now. In the next section, we’ll take a look at a production-ready implementation of the type-ahead suggest.
10.1.2Google Suggest
Some people consider Google Suggest to be the cream of the crop of the typeahead suggest applications. Google Suggest is fast and user-friendly and does its job efficiently. In figure 10.1, Google Suggest is giving suggestions for the letter e.
In figure 10.1, the result set for the letter e is limited to 10 results. Knowing the vast collection of data Google has, it could be billions of results. Google uses an algorithm to determine what should be displayed. Developers have dissected Google’s JavaScript code to figure out how it is accomplishing the task. Remember, JavaScript code cannot be completely hidden from view, although obfuscation can help.
One of the impressive things about Google Suggest is that it accounts for fast typists by using timers to limit multiple postbacks in a short span of time. This had to be one of Google’s biggest concerns since they have such a large user base. Lots of postbacks to their servers could lead to problems, and limiting the number of postbacks saves resources.
Figure 10.1 Google Suggest showing the available suggestions for the letter e
Examining type-ahead applications |
365 |
|
|
Google has inspired us (and many others). In the next section, we’ll incorporate the best of the features we’ve reviewed as we design our own type-ahead Ajax application.
10.1.3The Ajax in Action type-ahead
The type-ahead for this application will try to limit the impact on the server as much as possible. Smaller sites cannot handle the traffic that Google, Amazon, and Yahoo! can, since they do not have fancy load-balancing and multiple servers to handle the requests. Therefore, the more bandwidth that can be saved, the cheaper it is for the smaller websites in the long run.
To do this, we use the server only when we need new data. In this application, we use a script-centric interaction between the server and the client. The server formats the results as JavaScript statements that can be executed on the client. The data returned by the server contains only the text to display to the user and any identification field we want to relate with this data. This identification field can be compared to the value or an option tag. Most scripts do not allow us to send an ID; this one allows that. Then the browser handles the returned data, as JavaScript. With the data in the form of JavaScript variables, DHTML takes its turn in the process. You can see a diagram of this process in figure 10.2.
The Ajax portion of the script, as shown in figure 10.2, allows us to grab the data from the server. The server returns a text document containing a JavaScript statement to the client. The client processes the data contained in the JavaScript statement and checks to see if there are any results. If there are, the options are displayed for the user to choose.
The concept sounds easy until you realize that a large amount of JavaScript is involved. But with a number of small steps, the process of building a type-ahead script that minimizes the impact on the server is rather simple. The easiest part of this project is the server-side code, so that’s a good place to start.
Server
Query database and process results
|
Post form |
Return results |
|
|
|
Inputs |
Need data |
|
|
|
|
text |
|
|
|
||
Detect |
|
Limit |
Output |
|
|
|
|
|
|||
|
keystroke |
Have |
results |
results |
Figure 10.2 |
Browser |
data |
|
|
The system architecture for the |
|
|
|
|
type-ahead suggest |
||
|
|
|
|
|