• No results found

Implementing a Decoupled Library

In document Ajax Patterns And Best Practices pdf (Page 197-200)

The core of the Common Data functionality is a decoupled library, which is responsible for managing and processing the state. The decoupled library is called DecoupledNavigation and is defined as follows: function DecoupledNavigation() { } DecoupledNavigation.prototype.call = DecoupledNavigation_call; DecoupledNavigation.prototype.initializeRemote = DecoupledNavigation_InitializeRemote;

The definition of DecoupledNavigation has no properties and two methods. There are no properties because the common state object instance is defined in the implementation of the DecoupledNavigation methods. The method DecoupledNavigation_call is used to make a Decoupled Navigation pattern call as illustrated in the example Call( OnClick...). The method

DecoupledNavigation_initializeRemote is used when the Common Data functionality wants to make a call to a remote server.

The function DecoupledNavigation_call, exposed as DecoupledNavigation.call, wires together the Action, Common Data, and Presentation functionalities as illustrated by the following implementation:

function DecoupledNavigation_call( evt, action, data, presentation) { evt = (evt) ? evt : ((event) ? event : null);

if ( evt) {

var elem = (evt.target) ? evt.target :

((evt.srcElement) ? evt.srcElement : null); if ( elem) {

var obj = new Object(); obj.event = evt; obj.parent = this; obj.element = elem; obj.state = new Object(); obj.presentation = presentation; if ( (action) != null) {

if ( action( obj) != true) { return false;

} }

obj.isRemote = false; if ( (data) != null) {

if ( data( obj) != true) { return false; } } if( obj.isRemote) { return true; } if (presentation != null) {

if ( presentation( obj, obj.state) != true) { return false; } } return true; } } return true; }

The implementation of DecoupledNavigation_call has four parameters. The first param- eter, evt, is the event object. Whether the first parameter has a valid value goes back to the event problem outlined in the “Event Bubbling” section. The second parameter, action, is a function reference to an Action functionality (for example, OnClick). The third parameter, data, represents the function reference that performs a state manipulation. The fourth parameter,

presentation, is a function reference to a Presentation functionality, which usually is some HTML control. All of the lines up to if( elem) were outlined in the “Event Bubbling” section and are used to extract the HTML event and HTML source element.

The lines thereafter are the important lines and represent the technical details of the Common Data functionality. These lines represent the state as an object instead of a series of

parameters, as illustrated by the example that had the OnClick function call either InjectHTML

or InjectTextbox. So let’s look at those lines in more detail:

var obj = new Object(); obj.event = evt; obj.parent = this; obj.element = elem; obj.state = new Object(); obj.presentation = presentation;

The variable obj is the common object that is shared by the action, data, and presentation

function references. The idea is to convert the parameters gathered by the example function

OnClick and to convert them into an object instance. Based on that idea, the action function implementation manipulates obj and assigns the state. The state is then manipulated and processed by the data function reference. The state structures can be anything, and most likely will partially resemble the parameters used to call the example InjectHTML or InjectTextbox

functions. It is essential that the action, data, and presentation function implementations know what the structure of the state is. The advantage of manipulating an object structure is that the calling code as illustrated by OnClick does not need to be modified. Only the functions that modify the object structure need to be modified, preserving a proven and testing naviga- tion structure.

Getting back to the explanation of the obj properties, event and element reference the HTML event and source HTML element, respectively. The property state is the state that is manipulated by the various functionalities. The reason for using the state property is to provide an entry point for the common state that will not conflict with the other properties of

obj. And the reference obj.presentation is required if a remote call is made; this need will be illustrated in a little bit.

Going back a bit further in the example source code, let’s look at the implementation of

DecoupledNavigation_call. After obj has been instantiated, the calling of the action function reference is called, as illustrated again here:

if( (action) != null) {

if( action( obj) != true) { return false;

} }

Before the action function reference can be called, a decision is made that ensures that the

action variable is not null. If the action variable is null, there is no implementation for the Action functionality. This is useful, for example, if you’re creating a splash screen and you don’t need to generate a state but only some presentation information when the document has finished loading.

If the action variable is not null, the action function reference is called, where the param- eter is the common object obj. The action function implementation can query and manipulate

obj, and then return either a true or false. If the action function implementation is successful,

true is returned. Returning false indicates a failure, which will cause DecoupledNavigation_ local to return false, causing the event bubbling to quit, if applicable.

After the Action functionality has been executed, the property obj.state will be assigned and will be ready to be processed by the data function reference. The details of using the data function reference are illustrated again here:

obj.isRemote = false; if ( (data) != null) {

if ( data( obj) != true) { return false; } } if( obj.isRemote) { return true; }

The calling sequence of the data function reference is identical to the calling sequence of the action function reference. What is different is the assignment of the property obj.isRemote = false. The difference is due to the ability of the data function reference to process the state locally or remotely. If the data function reference processes the state remotely, an asynchro- nous call is made and further processing can continue only after the remote server has sent a response. The DecoupledNavigation_call function cannot continue and must return control to the web browser. The property assignment is used to indicate whether a remote server call is made. If a remote call is made, the presentation function reference cannot be called, and the function DecoupledNavigation_call returns a value of true.

This raises the question of whether a true or false value should be returned if the obj. isRemote property has a true value. Returning a value of true means that the event will continue to bubble, and depending on the context that might not be the best plan of action. The best plan of action depends on the context, and there is room for improvement in how the return value of the data function reference is handled.

If the data is processed locally, the Presentation functionality can be called. The calling sequence is illustrated as follows:

if( presentation != null) {

if( presentation( obj, obj.state) != true) { return false;

} }

The calling of the Presentation functionality is identical to the Action and Data functional- ities. The additional parameter obj.state is the state, and its presence makes it possible to recursively chain together multiple presentation functionalities, as illustrated in Figure 6-13.

Figure 6-13 illustrates how the function MyPresentation acts as a front processor for the functions InjectHTML and InjectTextbox. Because the state is a parameter, the front processor can filter out the appropriate state structure and then pass that state structure to the other Presentation functionalities. If state were not a parameter, the front processor would have to reassign the state property of the common variable.

The implementation of the function DecoupledNavigation_InitializeRemote has been delegated until a remote server call example is made. For now, the focus is on using the

In document Ajax Patterns And Best Practices pdf (Page 197-200)