- •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
524CHAPTER 13
Building stand-alone applications with Ajax
Figure 13.8
The preloader is loading file 2 of 4 as indicated by the status message with no errors.
13.4 Adding a rich transition effect
The code that we have written so far has loaded the files into an array. We now have to take the data stored in an array and build a slideshow. The slideshow is based on DHTML. By changing the content within divs by using innerHTML, we can display the different articles that our preloader has loaded. Changing CSS classes of the elements and altering the z-Index of layers allows us to create fading transition effects with the divs. By placing all of the steps together, we are going to create a dynamic fading slideshow.
13.4.1Cross-browser opacity rules
When we are creating the fading effect, we need to change the opacity of the top layer. Changing the opacity of the layer lets the content underneath show through. With an opacity level of 0 percent, we are allowing all of the content to show through. An opacity level of 100 percent blocks anything on the layer underneath from showing through.
Now, as always, we have issues with Internet Explorer and Mozilla-based browsers. Both browsers view opacity differently, so in our stylesheet rules we must account for the differences. Mozilla uses opacity, whereas Internet Explorer uses a filter specifying the alpha opacity, as listing 13.11 shows.
Adding a rich transition effect |
525 |
|
|
Listing 13.11 CSS Opacity filter classes
.opac0{opacity: .0;filter: alpha(opacity=0);}
.opac1{opacity: .2;filter: alpha(opacity=20);}
.opac2{opacity: .4;filter: alpha(opacity=40);}
.opac3{opacity: .6;filter: alpha(opacity=60);}
.opac4{opacity: .8;filter: alpha(opacity=80);}
Listing 13.11 shows that we created a series of style rules that have different opacity levels. Using CSS rules instead of using JavaScript to manipulate the values is a matter of preference. By using CSS rules, we can change other properties; maybe we want the colors to change as the fading occurs, or maybe we want to increase the text size. Using CSS classes allows us to do that without adding any extra JavaScript code, and it also encapsulates the cross-browser differences in a single place.
Now that we have created our classes, we can start the process of loading the RSS feed information into our divs.
13.4.2Implementing the fading transition
In section 13.3.2, we received an error message when testing the code since we had not created the function ChangeView(). ChangeView() initiates the process of the fading in and out of the content divs. For the fading process to work correctly, we alter the CSS classes and position the divs on different z-Index levels. Listing 13.12 shows how this is implemented.
Listing 13.12 ChangeView() function
function ChangeView(){ b
strDisplay = "<span class='RSSFeed'>" + arrayMessage[currentMessage][0] + "</span>: "
strDisplay += "<span class='itemTitle'>" + arrayMessage[currentMessage][1] + "</span><hr>";
strDisplay += arrayMessage[currentMessage][3] + "<hr>";
strDisplay += "<a href='" + arrayMessage[currentMessage][2] +
"' title='View Page'>View Page</a>"; document.getElementById("spanCount").innerHTML =
"Message " + (currentMessage+1) + " of " + arrayMessage.length;
var objDiv1 = document.getElementById("divNews1"); var objDiv2 = document.getElementById("divNews2"); if(layerFront == 1){
objDiv2.className = "opac0";
c |
Display RSS title |
d |
Show element title |
e Insert item description
f Output feed’s URL
g Change feed status
h Prepare transition
526CHAPTER 13
Building stand-alone applications with Ajax
objDiv1.style.zIndex = 1; objDiv2.style.zIndex = 2; objDiv2.innerHTML = strDisplay; layerFront = 2;
}
else{
objDiv1.className = "opac0"; objDiv2.style.zIndex = 1; objDiv1.style.zIndex = 2; objDiv1.innerHTML = strDisplay; layerFront = 1;
}
SetClass(0); i Start transition
}
h Prepare
transition
The ChangeView() bfunction has two major roles. The first is to build the HTML to display our data obtained from the RSS feeds. The second role is to prepare our divs for the fading in. Building the HTML is simple since we are using a basic layout. The hardest part is making sure that we keep track of quotes and apostrophes so we do not encounter any errors.
The first line of text we want to display is the RSS channel’s title c, which we stored in the first index of the array, arrayMessage. We need to surround the title with a span and assign a CSS class name of RSSFeed. The next step is to display the item element’s title dby referencing the second index of the array. By surrounding the title with a span and assigning a CSS class of itemTitle to the span, we are able to apply a separate style to our titles. To allow for a separation between the title and the message body, a horizontal rule is inserted.
The item description ewas stored in the fourth index of the arrayMessage. We divide the description from our next section, which holds the last item element we collected. The last item is the link f; we assign the value of the URL element to the link’s HREF attribute. The text that is visible to the user is “View Page,” which the user is able to click. The link sends the user to the RSS feed’s website.
We want to update the current message display counter that we built into our RSS header. To do this, we alter the innerHTML gof our span spanCount by using the arrayMessage length and our current message counter. We need to prepare the divs hfor the transition effect. We initialize the div by setting the zIndex so it is on top of the current one and set the class to our first CSS rule for opacity.
After we load the current message into our div, we start the process of fading the div into view. To do this, we need to create a function that loads the CSS classes in order; therefore, we call the function SetClass()i.
Adding a rich transition effect |
527 |
|
|
13.4.3Integrating JavaScript timers
The process of loading our div into view creates a smooth transition effect between messages instead of an abrupt change. Altering the opacity level of the layer with the CSS classes we created earlier creates the effect. The opacity level allows the layers underneath the div to show through, as if we were looking through a window that was tinted. We increase the opacity level in order to block out all the content that is below the div.
As mentioned in section 13.4.1, we are using five CSS classes to handle the fading in and out. The reason for using the classes is that in the future we can add colors to the fading or anything else that we would like to display in the transition effect. In this case, we loop through the classes. This is illustrated in listing 13.13.
Listing 13.13 JavaScript function to set CSS class and to execute the transition effect
function SetClass(xClass){ b Declare SetClass() |
|
|
|
||
if(xClass<5){ |
c Verify transition step |
|
|
d |
|
document.getElementById("divNews" + |
|
|
|||
|
|||||
layerFront).className = "opac" + xClass; |
|
|
e |
||
timerAmt = setTimeout("SetClass(" + |
|
|
|||
|
|||||
(xClass+1) + ")",timeColor); |
|
|
|
||
} |
|
|
|
|
|
else{ |
|
|
|
|
f |
document.getElementById("divNews" |
|
|
|
||
|
|
||||
+ layerFront).className = ""; |
|
|
|
|
|
currentMessage++; g Increment count |
|
|
|
h |
|
if(currentMessage>=arrayMessage.length) |
|
|
|||
currentMessage = 0; |
|
|
|
||
|
|
|
|
|
|
Set next className
Initiate fade timer
Remove CSS class
Verify next message
if(!bPaused) |
i Start viewer |
|
|
timerSwitch = setTimeout( |
timer |
"ChangeView()",flipLength); |
|
}
}
Listing 13.13 shows the function SetClass()b, which has a parameter, xClass, passed to it. This parameter allows us to track the current state of our transition effect without using another global variable. We call this function for every step of our transition to update the status until the fading transition is complete.
Since we are dealing with five CSS classes, we need to verify that the current step of our transition c has a value under five. If that’s the case, we know that there are still more CSS classes that need to be applied to our transition. If we are below five, we apply the next CSS class to the element. We reference the attribute className dand apply the next class to the element.