AJAX In Action [222]
Our initDocumentMouseHandler() method is an on-the-fly adaptation of the AjaxWindows.js library. It just overrides the document.onmouseup as before, but within Licensed to jonathan zheng Refactoring 457 our own codebase instead. Now our own method will perform the logic required to perform the adaptation within the portal’s handleMouseUp() method. This is shown in listing 11.14. Listing 11.14 Adaptation of the AjaxWindows.js mouse hander initDocumentMouseHandler: function() { var oThis = this; document.onmouseup = function() { oThis.handleMouseUp(); }; }, handleMouseUp: function() { bDrag = false; bResize = false; intLastX = -1; document.body.style.cursor = "default"; if ( elemWin && bHasMoved ) this.saveWindowProperties(elemWin.id); bHasMoved = false; }, This solution is much better, but we could take it one step further. If the AjaxWindows.js library defined the mouseup handler within a named function rather than anonymous, we could save the handler under a different name and invoke it from our own handler. This would have the benefit of not duplicating the logic already defined in the AjaxWindows.js library. This approach is illustrated in the following code: function ajaxWindowsMouseUpHandler() { // logic here... } document.onmouseup = ajaxWindowsMouseUpHandler; ajaxWindowsMouseUpHandler() is a callback defined by the AjaxWindows.js external library. Using it would allow us to save the definition of the method and use it later, as shown here: initDocumentMouseHandler: function() { this.ajaxWindowsMouseUpHandler = ajaxWindowsMouseUpHandler; b Store our own reference var oThis = this; document.onmouseup = function() { oThis.handleMouseUp(); }; }, Licensed to jonathan zheng 458 CHAPTER 11 The enhanced Ajax web portal handleMouseUp: function() { this.ajaxWindowsMouseUpHandler(); c Call library function if ( elemWin && bHasMoved ) this.saveWindowProperties(elemWin.id); d Add our functionality }, Now our handleMouseUp() method doesn’t have to duplicate the AjaxWindows.js library functionality. We just invoke the functionality c through our saved reference b and then add our own functionality d. And if the mouseup handler of AjaxWindows changes in the future, we pick up the changes without requiring any code modifications. This is a much more palatable change-management situation. Of course, it does assume that the implied contract with the library doesn’t change—the contract being two global variables named elemWin and bHasMoved. Given that the library currently defines the mouseup handler as an anonymous function, we could still save a reference to the existing mouseup functionality with a line of code such as this.ajaxWindowsMouseUpHandler = this.document.onmouseup; This would achieve the same thing, but it’s a slightly more brittle proposition, since the contract in this situation is much looser. This solution relies on the fact that we’ve included our script libraries in the appropriate order and that the AjaxWindows.js library has already executed the code that placed the mouseup handler on the document. It also assumes no other library has placed a different mouseup handler on the document or has performed some other wrapping technique just as we’ve done. That’s probably about as much as we can hope to do with the library adaptation. Let’s move on to the portal API. The handleMouseUp() method reveals one of the three portal commands that the portal component has to accommodate. When the mouse button is released, the saveWindowProperties() method is called to save the size and position of the current window. The following discussion will detail that along with the other portal command APIs. 11.6.3 Specifying the portal commands As already discussed, our portal component is primarily a sender of commands. The commands that are sent are Ajax requests to a server-side portal management system.