AJAX In Action [49]
var data=calculate();
showData(dataTable,data);
}
function ajaxOnloadHandler(){
var data=calculate();
Licensed to jonathan zheng Some small refactoring case studies 85 showData(otherDataTable,data); } function calculate(){ var data=new Array(); data[0]=6; data[1]=data[0]/3; data[2]=data[0]*data[1]+7; return data; } function showData(table,data){ var newRow=createTableRow(table); for (var i=0;i } } buttonDiv.onclick=buttonOnclickHandler; poller.onload=ajaxOnloadHandler; A lot of the common functionality has been abstracted out into the calculate() and showData() functions, and we’re only repeating ourselves a little in the onclick and onload handlers. We’ve achieved a much better separation between the business logic and the UI updates. Once again, we’ve stumbled upon a useful repeatable solution. This time it is known as the Command pattern. The Command object defines some activity of arbitrary complexity that can be passed around in code easily and swapped between UI elements easily. In the classic Command pattern for objectoriented languages, user interactions are wrapped up as Command objects, which typically derive from a base class or interface. We’ve solved the same problem in a slightly different way here. Because JavaScript functions are first-class objects, we can treat them as Command objects directly and still provide the same level of abstraction. Wrapping up everything that the user does as a Command might seem a little cumbersome, but it has a hidden payoff. When all our user actions are wrapped up in Command objects, we can easily associate other standard functionality with them. The most commonly discussed extension is to add an undo() method. When this is done, the foundations for a generic undo facility across an application are laid. In a more complex example, Commands could be recorded in a stack as they execute, and the user can use the undo button to work back up the stack, returning the application to previous states (figure 3.3). Each new command is placed on the top of the stack, which may be undone item by item. The user creates a document by a series of write actions. Then she selects the entire document and accidentally hits the delete button. When she invokes the undo function, the topmost item is popped from the stack, and its Licensed to jonathan zheng 86 CHAPTER 3 Introducing order to Ajax Command stack Delete selected Interactions Select all Delete selected Write para 2 Write para 1 Command stack Undo Document preview Select all Write para 2 Blah blah blah blah Write para 1 Blah blah blah blah rhubarb blah Document preview Figure 3.3 Using the Command pattern to implement a generic undo stack in a word processing application. All user interactions are represented as commands, which can be undone as well as executed. undo() method is called, returning the deleted text. A further undo would deselect the text, and so on. Of course, using Command to create an undo stack means some extra work for the developer, in ensuring that the combination of executing and undoing the command returns the system to its initial state. A working undo feature can be a strong differentiator between products, however, particularly for applications that enjoy heavy or prolonged use. As we discussed in chapter 1, that’s exactly the territory that Ajax is moving into. Command objects can also be useful when we need to pass information across boundaries between subsystems in an application. The network, of course, is just such a boundary, and we’ll revisit the Command pattern in chapter 5, when we discuss client/server interactions. Licensed to jonathan zheng Some small refactoring case studies 87 3.2.4 Keeping only one reference