AJAX In Action [223]
The commands that we’ve supported up to this point in our portal are logging in, loading settings, and saving settings. We’re going to throw in the ability to add Licensed to jonathan zheng Refactoring 459 and delete windows, which we alluded to although we didn’t show the full implementation. We can think of each of these in terms of a method of our portal. But before we start looking at code, let’s do a bit of prep work to help with the task of isolating change points. What we’re referring to is the names of the commands themselves. Let’s define symbols for each command name so that the rest of our components can use them. Consider the following set of symbols: Portal.LOGIN_ACTION = "login"; Portal.LOAD_SETTINGS_ACTION = "PageLoad"; Portal.SAVE_SETTINGS_ACTION = "UpdateDragWindow"; Portal.ADD_WINDOW_ACTION = "AddWindow"; Portal.DELETE_WINDOW_ACTION = "DeleteWindow"; Even though the language doesn’t really support constants, let’s assume that based on the uppercase naming convention, these values are intended to be constant values. We could lazily sprinkle these string literals throughout our code, but that’s a fairly sloppy approach. Using constants in this way keeps our “magic” strings in a single location. If the server contract changes, we can adapt. For example, imagine the ways in which the server contract could change, as shown in table 11.1. Table 11.1 Public contract changes Server Contract Change Action Required A command is renamed (e.g., PageLoad gets Change the right side of the assignment of the renamed to its verb-noun form LoadPage). LOAD_SETTINGS_ACTION constant to the new value. The rest of the code remains unaffected. The server no longer supports a command. Remove the constant, and do a global search for all references. Take appropriate action at each reference point. The server supports a new command. Add a constant for the command, and use its name within the code. Now that we can reference commands by these symbols, let’s look at a generic mechanism for issuing the commands to the portal management server. We need a helper method that generically sends Ajax-based portal commands to the server. Consider this usage contract: myPortal.issuePortalCommand( Portal.SAVE_SETTINGS_ACTION, "setting1=" + setting1Value, "setting2=" + setting2Value, ... ); In this scenario, we’re contemplating a method named issuePortalCommand() that takes the name of a command as its first argument (for example, one of our Licensed to jonathan zheng 460 CHAPTER 11 The enhanced Ajax web portal constants) and a variable number of arguments corresponding to the parameters the command expects/requires. The parameters are, quite intentionally, of the exact form as that required by the net.ContentLoader’s sendRequest() method. The issuePortalCommand() method we’ve defined could be implemented as follows: issuePortalCommand: function( commandName ) { var actionParam = this.options['actionParam']; b Get action parameter var urlSuffix = this.options['urlSuffix']; c Get URL suffix if (!urlSuffix) urlSuffix=""; var url = this.baseUrl; var callParms = []; if (actionParam){ callParms.push( actionParam + "=" + commandName d Apply action parameter ); }else{ url += "/" + commandName e Apply URL + urlSuffix; suffix } for ( var i = 1 ; i < arguments.length ; i++ ) callParms.push( arguments[i] ); var ajaxHelper = new net.ContentLoader( this, url, "POST", [] ); f Create ContentLoader ajaxHelper.sendRequest .apply( ajaxHelper, callParms ); g Send request }, This method builds a URL based on the configuration options that we discussed in section 11.6.1. If we have supplied a value for actionParam b, then it will be added to the parameters that are POSTed to the server d. If not, we will append the command to the URL path e, adding the URL suffix if we have supplied one in our options c.