Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ajax In Action (2006).pdf
Скачиваний:
63
Добавлен:
17.08.2013
Размер:
8.36 Mб
Скачать

Refactoring 541

provide extended metadata for future features. We could also define accessor methods for the attributes to provide a more formal contract for accessing them. For example, we could write a getTitle()/setTitle() method pair for accessing the title attribute. Since JavaScript doesn’t support visibility semantics like other object-oriented languages (for example, the private/protected keywords in Java), we didn’t bother. Now let’s take a gander at our View.

13.7.2RSS reader view

With our Model classes securely in place, we can now consider a View class. We could develop a View class for the RSSFeed, and another for the RSSItem, but because our RSSReader doesn’t really view a feed independently of an item, we’ll define a single View class called RSSItemView, which encapsulates the View for an RSSItem in the context of its parent RSSFeed. Since the View in this case is obviously HTML, our View class is really just responsible for the generation of HTML. Let’s start by looking at the constructor in listing 13.25.

Listing 13.25 The RSSItemView View class

RSSItemView = Class.create();

RSSItemView.prototype = {

initialize: function(rssItem, feedIndex, itemIndex, numFeeds) { this.rssItem = rssItem;

this.feedIndex = feedIndex + 1; this.itemIndex = itemIndex + 1; this.numFeeds = numFeeds;

},

}

Let’s take a moment to consider the parameters. The first parameter is an instance of an RSSItem. This tells the View what Model instance it’s providing a view for. Note that it’s not generally copasetic for the Model classes to have any knowledge of the View, but the View by necessity typically has intimate knowledge of the Model. The other parameters provide some supplemental context for the View. The feedIndex tells the View which feed number it’s in. The itemIndex tells the View where this item resides within its parent RSSFeed’s array of items. The numFeeds tells the View how many feeds there are. All of these index-based parameters are for the View to indicate its place in the world, so to speak. The View might want to display a context area that indicates, for example, “this is feed

542CHAPTER 13

Building stand-alone applications with Ajax

number 1 of 7 and article number 3 of 5.” These attributes could be embedded within the Model, but they’re not really attributes that the Model should typically care about, so this context that the View needs is passed into the View constructor by the client.

As mentioned previously, the responsibility of the View is to generate HTML. So our View class will need a single method that does precisely that. Let’s see what that might look like in listing 13.26.

Listing 13.26 The HTML generation method

toHTML: function() { var out = ""

out += '<span class="rssFeedTitlePrompt">RSS Feed '

out += '(' + this.feedIndex + ' of ' + this.numFeeds + ') : '; out += '</span>';

out += '<span class="rssFeedTitle">';

out += '<a href="' + this.rssItem.rssFeed.link + '">' + this.rssItem.rssFeed.title + '</a>';

out += '</span>'; out += '<br/>';

out += '<span class="rssFeedItemTitlePrompt">Article '; out += '(' + this.itemIndex + ' of ' +

this.rssItem.rssFeed.items.length + ') : ';

out += '</span>';

out += '<span class="rssFeedItemTitle">';

out += '<a href="' + this.rssItem.link + '">' + this.rssItem.title + '</a>';

out += '</span>';

out += '<div class="rssItemContent">'; out += this.rssItem.description;

out += '</div>';

return out;

},

The toHTML method produces the contextual elements of the display followed by the text of the article. The first portion of the code displays the RSS Feed (x of y) : RSS Feed Title. The link attribute of the rssFeed parent is used to generate the HREF of the anchor produced, and the title is used to generate the text of the anchor. A CSS class name is generated for each span, one for the prompt, and another for the anchor, allowing each to be styled independently. This is illustrated in figure 13.15.

Refactoring 543

RSS Feed (2 of 4) : Eric's weblog

var out = ""

out += '<span class="rssFeedTitlePrompt">Rss Feed '

out += '(' + this.feedIndex + ' of ' + this.nubFeeds + ') : '; out += '</span>';

out += '<span class="rssFeedTitle">';

out += '<a href="' + this.rssItem.rssFeed.link + '">'

+ this.rssItem.rssFeed.title + '</a>';

out += '</span>'; out += '<br/>';

Figure 13.15 RSS Feed (x of y) : RSS Feed Title

The next portion of code generates the Article (x of y) : RSS Item Title. The link attribute of the RSS item is used to generate the HREF of the anchor produced, and the title of the item is used to generate the text of the anchor. This code also provides CSS class names for both the prompt and the title, as illustrated in figure 13.16.

Article (1 of 3) :

Sending XML to the Server

out += '<span class="rssFeedItemTitlePrompt">Article '; out += '(' + this.itemIndex + ' of '

+ this.rssItem.rssFeed.items.length + ') : '; out += '</span>';

out += '<span class="rssFeedItemTitle">';

+ this.rssItem.title + '</a>';

out += '</span>';

Figure 13.16 Article (x of y) : RSS Item Title

The last few lines of the toHTML method generate a div element to hold the content of the RSSItem’s article (the description attribute). The code for this is as follows:

out += '<div class="rssItemContent">'; out += this.rssItem.description;

out += '</div>';

The CSS class name rssItemContent is generated for the article content. It should have a little bit of margin and padding in order for the content to visually reside within the display without touching any borders. It should also have a fixed height and overflow set to auto so that the content scrolls when needed—inde- pendently of the contextual information shown previously. A representative CSS definition for this class is shown here:

.rssItemContent {

border-top : 1px solid black;

width

:

590px;

height

:

350px;

544CHAPTER 13

Building stand-alone applications with Ajax

overflow

:

auto;

padding

:

5px;

margin-top : 2px;

}

Given the code and style shown in this code, the content area produced should look something like the sample shown in figure 13.17.

Putting it all together, the view generated by our RSSItemView class is shown in figure 13.18.

Before we leave the topic of our View, let’s add one more little method to the View to make its usage more convenient:

toString: function() { return this.toHTML();

}

The reason we give the View a toString method is that it allows us to use the View instance and the HTML string that it generates interchangeably. For example, we can assign the View to the innerHTML attribute of an element, and the string representation, which is the HTML that it generates, will be used. For instance, the following code would assign the generated HTML of a view to the innerHTML of a div with the ID contentDiv:

var rssItemView = new RSSItemView( anRSSFeed, 0, 0, 5 ); $('contentDiv'). innerHTML = rssItemView;

Figure 13.17 Article (x of y) : RSS Item Title