Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Ajax Patterns And Best Practices (2006)

.pdf
Скачиваний:
39
Добавлен:
17.08.2013
Размер:
15.94 Mб
Скачать

C H A P T E R 6 D E C O U P L E D N A V I G A T I O N P A T T E R N

189

<tr>

<td width="100%" bgcolor="#FFFFFF" style="padding:4px" colspan="2">

<!-- PUT YOUR CONTENT BETWEEN HERE --> Testing 1 2 3

<!-- END YOUR CONTENT HERE -->

</td>

</tr>

</table>

</td>

</tr>

</table>

</div>

</body>

After you look at the HTML source code, your first impression might be, “Okay, so what does this actually do?” The answer is, “No idea,” and it is not really necessary to know. What you need to know is where to put the content, and that has been shown in bold. The place is marked, and if the table cell had an identifier attribute, the contents of the pop-up box could be injected. This is good because it means for the Presentation functionality you don’t need to know how the HTML component works.4 What you need to know is how to tweak the components, and specifically what you want to know are the following attributes:

How to tweak the look and feel (for example, change font, background color, and so on)

How to inject content and read content from the HTML component

How to display, hide, and position the HTML component

The strategy of the Presentation functionality is to consider the HTML code as a component that is fit into the Decoupled Navigation pattern by using the Adapter pattern. Figure 6-18 illustrates this strategy.

Figure 6-18 shows two web browser snapshots. The upper snapshot shows the browser before clicking the button, and the lower snapshot shows it after clicking the button. All around the snapshots are oodles of balloons to indicate the calling sequence of making a remote call to a server that will generate a pop-up box. All balloons except three should be familiar, because they have already been explained in Figure 6-16.

The new callouts—5) PopupDialogBox, 7) Show Dialog, and Pop-up Box Component—are the Adapter implementation of the HTML component. The function PopupDialogBox implements the Presentation functionality and provides the adapter between the InjectHTML and pop-up box HTML component. The function PopupDialogBox redirects InjectHTML to inject HTML into a table row.

4.For a more detailed analysis of how Dynamic HTML components work, please refer to JavaScript and DHTML Cookbook by Danny Goodman (O’Reilly Media, 2003).

190

C H A P T E R 6 D E C O U P L E D N A V I G A T I O N P A T T E R N

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 6-18. A more complicated user interface that involves a pop-up box

If you take a good look at Figure 6-18, what should be very apparent is the lack of changes necessary to switch the look and feel of the HTML content. The look of Figure 6-16 is entirely different from that of Figure 6-18, yet the same event structure is used, with a small change in the Presentation functionality. This is the real effectiveness of the Decoupled Navigation pattern, which decouples the various pieces of functionality.

As a thought experiment, imagine the conversion of the button click to a mouse event that pops up the dialog on an onmousemove event. It would not be a difficult change and would only require replacing the onclick event with the onmousemove event.

The following HTML code uses bold to show the pattern integration tweaks that need to be made to the pop-up box illustrated in Figure 6-17:

<body>

<input type="button" value="Appear" onclick="return nav.call( event, OnClick,

ConvertToUpperCase, PopupDialogbox)"/>

<div id="showimage" style="position:absolute;width:250px;left:250px;

top:250px;visibility:hidden;"> <table border="0" width="250" bgcolor="#000080"

cellspacing="0" cellpadding="2">

C H A P T E R 6 D E C O U P L E D N A V I G A T I O N P A T T E R N

191

<tr>

<td width="100%">

<table border="0" width="100%" cellspacing="0" cellpadding="0" height="36px">

<tr>

<td id="dragbar" style="cursor:hand; cursor:pointer" width="100%"onMousedown="initializedrag(event)">

<ilayer width="100%" onSelectStart="return false"> <layer width="100%"

onMouseover="dragswitch=1;if (ns4) drag_dropns(showimage)" onMouseout="dragswitch=0">

<font face="Verdana" color="#FFFFFF"><strong>

<small id="title">Announcement Box</small> </strong></font>

</layer>

</ilayer>

</td>

<td style="cursor:hand">

<a href="#" onClick="hidebox();return false"> <img src="close.gif" width="16px"

height="14px" border="0"></a></td>

</tr>

<tr>

<td width="100%" bgcolor="#FFFFFF" style="padding:4px" colspan="2"

id="destContent">

<!-- PUT YOUR CONTENT BETWEEN HERE --> Testing 1 2 3

<!-- END YOUR CONTENT HERE --> </td>

</tr>

</table>

</td>

</tr>

</table>

</div>

</body>

This HTML code has very few changes. The additional HTML element input is used to pop up the pop-up box defined by the div element. The div element is predefined, and the only real changes to it are to make the div element hidden (visibility=hidden), and to identify the HTML injection points for the pop-up box title bar (title) and pop-up box content (destContent).

192

C H A P T E R 6 D E C O U P L E D N A V I G A T I O N P A T T E R N

For the event call nav.call, the new function is PopupDialogbox and it is defined as follows:

function PopupDialogbox( common, state) { InjectHTML( common, state);

document.getElementById( "showimage").style.visibility = "visible"; document.getElementById( "title").innerHTML = state.title;

}

The function PopupDialogbox is an adapter of the predefined pop-up box component. By using the function InjectHTML, you inject the text in the table cell destination, destContent. The first getElementById references the property visibility and is used to make the div HTML element appear. The second getElementById references the innerHTML property and is used to assign the title of the pop-up box. The title would be assigned in the common.complete function implementation.

In the example, PopupDialogbox is a function defined in the HTML page itself. But there is no reason why the function could not be reused in different contexts whenever a pop-up box is necessary. Additionally, the PopupDialogbox function needs other cosmetic changes, such as orientation and size of the pop-up box, that are not illustrated. The changes are not illustrated because they are application specific and do not help explain the Decoupled Navigation pattern.

Using HTML Components

When I was writing the details of this pattern, I was reluctant to repeat content that was written in great detail in other books or websites. After all, providing a bunch of widgets and their explanations without going into great detail is a very bad idea. However, I also knew that the Presentation functionality requires the explanation of HTML components.

My original idea was to spend pages and pages explaining some basic HTML components such as pop-up boxes, menus, and pop-up windows. So off I went to explore how other people were building these HTML components. During my exploration, I hit upon the website http:// www.dynamicdrive.com. At first I thought, interesting site and neat components. It did not have everything, but it was good. It was not until I had to start explaining how to create HTML components that I realized the brilliance of this website.

I thought I would have to spend hours integrating a pop-up box into the Decoupled Navigation pattern, when in fact it required only 20 minutes. At that point, it hit me that the best way to explain the Presentation functionality was to explain how to integrate HTML components. But as my exploration continued, I learned that there were good HTML components and bad HTML components. So as part of the implementation of the Decoupled Navigation pattern, I want to explain a good HTML component site so that when you are exploring for your own HTML components, you will be able to gauge a good or bad HTML component. After all, you do not want to write your own pop-up box. It has been done often enough.

Figure 6-19 is a snapshot of the http://www.dynamicdrive.com website, which lists the available HTML components for dynamic content.

C H A P T E R 6 D E C O U P L E D N A V I G A T I O N P A T T E R N

193

Figure 6-19. Example HTML components for dynamic content

Let’s illustrate how to integrate the pop-up box HTML content and inspect the related HTML page (see Figure 6-20).

Figure 6-20 shows two text boxes that have been highlighted. The upper text box contains the common code that can be stored in a separate JavaScript file. The lower text box contains the user example code that is created as a prototype of how to invoke the common code. When implementing the Presentation functionality, the common code is not touched and is treated as its own module. What is touched and modified is the user example code.

The clear separation of the common code and the code used to invoke the common code is a very good HTML component. Such a definition of an HTML component indicates that the HTML component has been decoupled and can be plugged into an unrelated infrastructure.

One of my pet peeves with many web application and Ajax frameworks is that they are not decoupled. Often the client-side technology relies on server-side technologies, and the client is coupled with other pieces on the HTML page. The result is a monolithic application that happens to function as a web application and Ajax application. However, these applications miss the main thrust of the Ajax and REST philosophies.

194

C H A P T E R 6 D E C O U P L E D N A V I G A T I O N P A T T E R N

Figure 6-20. Pop-up box HTML component details

Pattern Highlights

Based on its description in the “Architecture” section, the Decoupled Navigation pattern might seem unnecessary. However, the usefulness of this pattern became obvious in the “Implementation” section. With Ajax, complex web applications are going to be written that navigate very sophisticated data. Navigating the content means using some type of link, and logic on the client side, and that is the heart of the Decoupled Navigation pattern in that it aims to organize and decouple the various pieces of the logic. All of this was illustrated by an example that became progressively more complex.

The essence of this pattern is to focus on the client side and to break apart the pieces of an HTML application so that maintenance, extensibility, and coding are simpler and can be overseen. The fact is that many HTML applications are complicated, and maintaining oversight of these applications is imperative.

For each of the functionalities, there are some rules of thumb. For the Action functionality, the following rules are defined:

Use the id property to uniquely identify all HTML elements that will be used in the application.

The HTML event object instance should be abstracted for simplicity and robustness.

C H A P T E R 6 D E C O U P L E D N A V I G A T I O N P A T T E R N

195

Use HTML event bubbling to process multiple similar elements as a collection; otherwise, associate single events with single elements. When processing multiple elements, using the id property is imperative; otherwise, problems may occur.

Use HTML event bubbling to perform validation and verification, potentially stopping the sending of an HTML form. Note that not all events can be canceled, and not all events bubble. When an event does not bubble, the event occurs only on the HTML element responsible for the event.

For cross-browser compatibility, consider using only the events listed in Table 6-1.

Table 6-1. Cross-Browser Events and Their Bubble and Cancelable Status

Event

Bubbles

Cancel

onabort

No

No

onblur

No

No

onchange

Internet Explorer—No

Internet Explorer—Yes

 

Mozilla—Yes

Mozilla—No

onclick

Yes

Yes

ondblclick

Yes

Yes

onerror

No

Yes

onfocus

No

No

onkeydown

Yes

Yes

onkeypress

Yes

Yes

onkeyup

Yes

Yes

onload

No

No

onmousdown

Yes

Yes

onmousmove

Yes

No

onmouseout

Yes

Yes

onmouseover

Yes

Yes

onmouseup

Yes

Yes

onmove

Yes

No

onreset

No

Yes

onresize

Yes

No

onsubmit

Internet Explorer—No

Yes

 

Mozilla—Yes

 

onunload

No

No

 

 

 

196

C H A P T E R 6 D E C O U P L E D N A V I G A T I O N P A T T E R N

Here are some rules of thumb for defining URLs:

URLs are resources that represent components and should be treated as such.

URLs are general, and with each identifier appended to the URL, more details about the component are exposed.

Application logic is related to the URL, and orthogonal application logic is distinctly separated by using the URL.

As defined by the Permutations pattern, resource URLs exist until the end of time, or at least for a very long time, allowing a resource URL to be considered hard-coded.

Here are some rules of thumb about the Common Data functionality:

Implementing the Common Data functionality means defining a common state structure that is shared by the Action, Common Data (functions that is), and Presentation functionalities.

Implementing a common state structure is essential to decoupling the various functionalities from each other, making it possible to wire together predefined functionality.

The common state structure should be decoupled from the functionalities by using classes and functions.

Here are some rules of thumb about the Presentation functionality:

The Presentation functionality does not encompass all aspects of the user interface. For example, the details of creating and moving a pop-up box are managed by the routines of the pop-up box. The Presentation functionality is responsible for indicating what data to present and when to present that data.

All Presentation functionalities should be adapters for HTML components. You do not want to write your own pop-up boxes, menus, or other more sophisticated HTML user interface components. Intelligent individuals have already done a good job, and you should take advantage of their generosity and intelligence.

When implementing a function to generate the user interface, focus on creating general code that can be reused in multiple contexts.

C H A P T E R 7

■ ■ ■

Representation Morphing

Pattern

Intent

The Representation Morphing pattern is best described as a representation that implements a mini Model View Controller, where the model is a constant that can be substituted into other mini Model View Controllers. The uniqueness of this pattern is that the model, view, and controller are an all-in-one package. The result is a representation that is work-space oriented, allowing saving and reconstruction without having to use a large amount of JavaScript source code.

Motivation

The motivation for using this pattern relates to the desire to improve the usability of web applications. Web applications are not traditional client applications and require their own coding techniques. When implementing web applications, some will attempt to assign traditional client programming functionalities when the correct solution would be to concentrate on the Web and what it offers.

There are multiple types of web applications, two of which are informational and data gathering. Informational websites provide links and some HTML form elements to navigate the data. Search engines are an example of informational websites in which links and HTML form elements (for example, a text box) are used to navigate information. Figure 7-1 shows the Google search engine.

The Google search engine has multiple HTML form elements (text box, buttons, and radio buttons) illustrating sophisticated features in a simple-to-use representation. Most people probably do not use any of the HTML form elements except for the text box. Usually you enter your data into the text box, hit the Enter key, and get a listing of search results.

197

198

C H A P T E R 7 R E P R E S E N T A T I O N M O R P H I N G P A T T E R N

Figure 7-1. Example data gathering web application

A data-gathering web application is different in that the HTML elements are used to assemble data for reference purposes. Consider the data-gathering application illustrated in Figure 7-2.

In this data-gathering web application, all of the pieces of information are gathered by using HTML form elements. In Figure 7-2, all of the HTML elements are text boxes, which are compact and visually pleasing, but ill-suited for data entry. Two of the text boxes are incorrectly formatted and illustrate a fundamental problem. The topmost text box is too big for the task of entering the title of the message. The second text box, on the other hand, is completely undersized for entering the message that will be sent. If the message causes scroll bars to appear, the little room that is available becomes even less. For any larger amounts of text, a user needs to constantly scroll from side to side or up and down. Users would be better off writing the text in another application and then copying the text into the text box.