AJAX In Action [242]
if ( this.xmlDocument == null || this.xslStyleSheet == null ) return;
this.updateView();
},
Once both responses have come back from the server, we are ready to update the UI. We know that both responses have come back when both the this.xmlDocument and the this.xslStyleSheet state variables are non-null. The updateView() method is shown in listing 12.15.
Listing 12.15 Updating the view
updateView: function () {
if ( ! XSLTHelper.isXSLTSupported() )
return;
if ( window.XMLHttpRequest && window.XSLTProcessor )
this.updateViewMozilla();
else if ( window.ActiveXObject )
this.updateViewIE();
},
As we’ve noted already, we require different implementations for each browser type being supported, so we’ve separated out the details. Let’s look at each implementation, beginning with the Mozilla implementation, shown in listing 12.16. Listing 12.16 Updating the view in Mozilla
updateViewMozilla: function() {
var xsltProcessor = new XSLTProcessor();
Initialize transformer
xsltProcessor.importStylesheet(this.xslStyleSheet);
var fragment = xsltProcessor.
TransformToFragment(
b Perform XSLT
this.xmlDocument,
transform
document);
this.container.innerHTML = "";
c Update
this.container.appendChild(fragment);
the UI
},
Licensed to jonathan zheng 496 CHAPTER 12 Live search using XSLT The specific update implementations, whether IE or Mozilla, perform two basic steps: b performing the XSLT transformation, and c updating the UI with the result. Recall that the result of the Mozilla transformation process is a document fragment that is added to an element via appendChild(), whereas the IE transformation results in a string that is added via the innerHTML property. So with that in mind, the updateViewIE() implementation is shown here: updateViewIE: function() { this.container.innerHTML = this.xmlDocument.transformNode(this.xslStyleSheet); }, The same two steps are performed in the IE implementation, which is a good deal more compact because the steps of applying the transformation and updating the UI are all done in a single line of code. As to which one is more efficient, we’ll let you decide. Our XSLTHelper is now complete, and we have a clean, simple, one-method API for performing XSLT transformations. Our helper should prove to be very useful and more than worth the relatively small amount of effort we have put into it. Now let’s refocus our efforts on the live search and contemplate a simple component design. 12.6.2 A live search component Now that we have some sweet XSLT help in our back pocket, let’s implement our live search script as a component that uses it. The component should satisfy the component requirements that we’ve discussed in detail in our other refactoring examples. These include such things as providing a clean API, being configurable while providing appropriate default values, being unobtrusive to the surrounding HTML, and being able to have multiple instantiations on a page. Let’s develop a clean object-oriented solution with the guiding principle that each responsibility should be encapsulated in a dedicated method. One responsibility, one method. With that in mind, let’s get started in the usual place—considering construction. From the perspective of component state, the live search component has to keep track of more “stuff ” than most other components we’ve written. It needs to know about an XML document source, an XSL document source, a field that initiates the search, and the URL of the page that it should use to support bookmarking. So, that means our constructor is going to be a little heavier in this example than in previous ones. However, it should still be quite manageable. Let’s take a stab at a live search constructor now: Licensed to jonathan zheng Refactoring 497 function LiveSearch( pageURL, lookupField, xmlURL, xsltURL, options ) { this.pageURL = pageURL; this.lookupField = lookupField; this.xmlURL = xmlURL;