In the HTML code, any HTML element that will be used by the JavaScript code is identified by using the id attribute. This is important so that when manipulations do occur, the Java- Script does not need to hunt for the HTML elements. The JavaScript code declares the variable nav, which is the Decoupled Navigation pattern implementation. The nav variable is used in the onclickevent of the input HTML element. The action.local method call wires together the OnClick and ConvertToUpperCase functions with the undefined InjectHTML function. This means that when the button is clicked, the OnClick function is called to process the click, Go visit our java server pages services for a reliable, lowcost webhost to satisfy all your needs.
CHAPTER 6 DECOUPLED NAVIGATION PATTERN Figure 6-13. Chaining Presentation functionalities together Illustrating a Local Call Having defined the decoupled library, you can implement a simple example. Even though I have briefly mentioned the Presentation functionality, I haven t explained the details. Still, although the implementation may seem like we re jumping a bit ahead of ourselves, I am presenting it on purpose so that you understand the calling sequences. To illustrate the Decoupled Navigation pattern, I have illustrated the copying of the contents from a text box into an HTML div element. The copied contents will be converted into uppercase. From a GUI perspective, the HTML page looks like Figure 6-14. Figure 6-14. Example HTML page used to transfer the contents of the text box to the div element, where the contents are converted into uppercase This HTML page is elementary, and the HTML and JavaScript code behind it are as well. The text box contains the data that is injected into the HTML page and replaces the text Nothing Yet. Following is the code used to create Figure 6-14: We would like to recommend you tested and proved virtual web hosting services, which you will surely find to be of great quality.
178 CHAPTER 6 DECOUPLED NAVIGATION PATTERN 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 asynchronous 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 trueor 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 functionalities. 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 DecoupledNavigation class to perform a local call. We would like to recommend you tested and proved virtual web hosting services, which you will surely find to be of great quality.
CHAPTER 6 DECOUPLED NAVIGATION PATTERN parameters, as illustrated by the example that had the OnClickfunction 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 InjectHTMLor 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 navigation structure. Getting back to the explanation of the obj properties, event and element reference the HTML event and source HTML element, respectively. The property stateis 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 actionfunction 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 parameter 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. Note: If you are looking for cheap and reliable webhost to host and run your mysql application check mysql web server services.
176 CHAPTER 6 DECOUPLED NAVIGATION PATTERN 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 parameter, 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 You want to have a cheap webhost for your apache application, then check apache web hosting services.
CHAPTER 6 DECOUPLED NAVIGATION PATTERN Even though InjectTextbox and InjectHTML are similar, calling InjectTextbox requires a change in the logic of the OnClick function. The OnClick function has to make an additional decision of whether or not a conversion has to occur. You might say, Well, duh, the OnClick function has to change if the called function changes. But the reply is, Why must the OnClick function change? The purpose of the OnClick function is to gather the data necessary to call either the InjectHTMLor InjectTexbox function. The purpose of the OnClick function is not to make decisions, because decisions can change if a user interface does not, and vice versa. The data gathering and decisions made about the data need to be decoupled. In an ideal world where everything is decoupled, you would write the following source code: The modified source code has added the function Call, which has three parameters that are three function references. The first function reference, OnClick, is the Action functionality responsible for gathering the data into a state. The second function reference is either null or CallXMLHttpRequest and represents the Common Data functionality that is responsible for processing the state. And finally, the third function references, InjectHTMLand InjectTextbox, are responsible for displaying the state. The resulting calling sequence illustrates that the first button click event gathers the data, does not process the data, and displays the data. The second button click event gathers the data, calls a remotely located server, and displays the data. The OnClick functions used in either button click event are identical, meaning that the OnClick event is not dependent on whether the processing of the common data is local or remote. So now the functions are decoupled, as is the calling sequence. The exact details of this decoupling and the calling of the functions is the topic of the following sections. Implementing a Decoupled Library 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: In case you need affordable webhost to host your website, our recommendation is ecommerce web host services.
174 CHAPTER 6 DECOUPLED NAVIGATION PATTERN The solution is to decouple the steps of Figure 6-11, which was illustrated as a single piece of code, into two code pieces. The decoupled code would be as follows: function InjectHTML( elementId, text) { document.getElementById( elementId).innerHTML = text; } function OnClick( event) { InjectHTML( “myDiv”, “data”); } There are now two functions (InjectHTML and OnClick). The function InjectHTML requires an element identifier and some text, and will perform an HTML injection. The function InjectHTML is a business-logic-specific implementation that operates on an HTML element reference defined by the client. The function OnClick reacts to the event and is responsible for gathering the data used to call the InjectHTML function. Each function has its responsibilities and each function is decoupled from the other. The only shared information is the data gath ered by OnClick and processed by InjectHTML. Figure 6-11 has been implemented by using a decoupled solution, but now Figure 6-12 needs to be implemented. This means that an additional step of using the XMLHttpRequest object needs to be added. For simplicity, assume that the XMLHttpRequest object functionality is encapsulated in the function CallXMLHttpRequest, which accepts a single parameter. As the function CallXMLHttpRequest is used to gather information, the function is called by OnClick, and the returned data is passed to the InjectHTML function. The modified source code is as follows: function InjectHTML( elementId, text) { document.getElementById( elementId).innerHTML = text; } function OnClick( event) { InjectHTML( “myDiv”, CallXMLHttpRequest( “data”)); } In the modified source code, the second parameter of the CallXMLHttpRequest function has been replaced with the function CallXMLHttpRequest. Looking at the solution technically, you can see that the three steps have been decoupled from each other, and each can vary without affecting the other. What is still kludgy is how the data is gathered and passed to the function InjectHTML. This is the reason for creating Common Data functionality. The Common Data functionality replaces the kludgy calling of the functions with some common state. The problem at the moment is that the OnClickfunction relies on the functions InjectHTML and CallXMLHttpRequest. The reliance cannot be avoided, but what can be avoided is the calling convention. Imagine that instead of InjectHTML being used, the function InjectTextbox is used due to a business logic decision. And then imagine that InjectTextbox requires an extra parameter, as illustrated by the following source code: function InjectTextbox( convert, elementId, text) { // …. } function OnClick( event) { InjectTextbox( false, “myDiv”, CallXMLHttpRequest( “data”)); } If you are in need for cheap and reliable webhost to host your website, we recommend http web server services.
CHAPTER 6 DECOUPLED NAVIGATION PATTERN Let s continue building on this example. Imagine that the same user interface is used to make a remote call via the XMLHttpRequest object. Figure 6-12 illustrates the steps needed in the remote case. Figure 6-12. Steps resulting from clicking a button when using an extra XMLHttpRequest call Figure 6-12 shows an added step (step 2), in which a request is made by using the XMLHttpRequest object that then generates some data that is processed in step 3. Looking at Figures 6-11 and 6-12, you might be wondering where the need for the Common Data functionality is. The need arises because often an application is converted from the state depicted in Figure 6-11 to that in Figure 6-12, or vice versa. Implementing the conversion can require some major restructuring of the code, or a completely new implementation that needs to be tested and maintained. The Common Data functionality decouples the steps so that an application that executed as in Figure 6-11 could be converted without major surprises into an application that executes as in Figure 6-12. The intention is to decouple, allowing the fewest number of changes and yielding the largest user benefit. Consider the following code, which mimics the implementation of Figure 6-11: function OnClick( event) { document.getElementById( “myDiv”).innerHTML = “data”; } The code is a problem because what was defined as two steps in Figure 6-11 is one step in technical terms. The code is a function with an implementation. The problems of the function OnClickare that the text identifier myDiv is hard-coded, and so is the assigned value data. Imagine that the assignment code is used in multiple places, and imagine that the text has to be converted to uppercase before doing the assignment. Then the code would have to be updated in multiple places. We recommend cheap and reliable webhost to host and run your web applications: Coldfusion Web Hosting services.
172 CHAPTER 6 DECOUPLED NAVIGATION PATTERN Of course, it goes without saying that a good programming practice in the implementation of MonitorLinks would be to test whether the evt variable is null. This is because when the events are wired together by using programmatic terms, the first parameter may or may not be the event. Defining and Implementing the Common Data Functionality As outlined earlier in this chapter, the Common Data functionality requires defining a state and potentially some function that processes the state. When processing the state, the data may be locally processed or may involve some remote processing. If the state is processed remotely, a URL is involved and the process requires URL design. Therefore, this section presents materials relating to URL design. The Purpose of the State and State Manipulations Some may perceive the Common Data functionality as unnecessary overhead. The Common Data functionality is a necessity, albeit (as described in the Applicability section) only when the Decoupled Navigation pattern is a necessity. The purpose of the Common Data functionality is to provide a wedge between the Action and Presentation functionalities, enabling a decoupling of functions. Consider Figure 6-11, which illustrates the steps that occur when an HTML button is clicked, generating an event that causes a JavaScript function to be called. Figure 6-11. Steps resulting from clicking a button Figure 6-11 represents the simple button click as two steps. The first step is the HTML event, which processes the mouse click. The second step is the content generation in the table row below the button. The content uses HTML injection by assigning the innerHTML property. From this simple example, there would be no need for the Common Data functionality because that would add an unnecessary layer. From our experience, we are can tell you that you can find a reliable and cheap webhost service at Java Web Hosting services.
CHAPTER 6 DECOUPLED NAVIGATION PATTERN is generated and the element captures it. Consider the following example that illustrates how to capture an event by using a property to wire the event: function DoAssociation() { (document.getElementById( “manualassociation”))[ ‘onclick’] = MonitorLinksId; document.getElementById( “manualassociation”).attachEvent( ‘onclick’, MonitorLinksId); }
In the example, the wiring of the methods to an HTML element should happen in the HTML element bodyonload event. It is important that only when the onload event is being fired that the events can be wired. If the wiring occurs before the document has been loaded, some HTML elements might not exist and cannot be referenced. The onload event ensures that the HTML content has been loaded and can be referenced. After the method DoAssociation is called, there are two ways to wire an event to an HTML element. In either way, it is important to call the document.getElementById method to retrieve an HTML element instance. The first way to assign an event is to assign the array index of the event that is to be wired. In the example, that means assigning the onclick array index. This assignment illustrates a fundamental feature of JavaScript: there are no differences made between properties, functions, and so on. The second way to assign an event is to use the method attachEvent (as illustrated) or addEventListener. When calling the methods attachEvent or addEventListener, you will need two parameters. The first parameter is the event to be captured, and the second parameter is the function to be associated with the event. In both cases, it is not necessary to use function variables or identifiers, because an anonymous function would be acceptable. You would use attachEvent with Microsoft Internet Explorer, and addEventListener when using a Mozillabased or Safari browser. The advantage of using the array index approach is that it works on all browsers without any special requirements. However, it works because it is a special case of how the JavaScript language is constructed. The official approved way would be to use either addEventListeneror attachEvent. After the events have been wired, they will function identically to the MonitorLinks function of previous examples. If you do not want to associate the event to the HTML element in the bodyonload event, it can be done after the element has been declared, as illustrated by the following source code: