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

226CHAPTER 6

The user experience

Figure 6.4 Higher-priority messages are shown in a pop-up dialog, in which messages are listed in order of priority.

wish for something more immediate. To this end, we will initially display only lowpriority messages in the status bar; default and high-priority messages will first appear in a pop-up dialog, as illustrated in figure 6.4, before being dismissed.

The dialog can be modal or nonmodal. In the case of modal dialogs, we use a semitransparent layer to block off the rest of the user interface until the user dismisses the dialog. When dismissed, the dialog is represented by an icon on the right side of the status bar. In the following two sections, we’ll look at implementations of these features.

6.4 Implementing a notification framework

We’ve defined two main parts to our user interface: the status bar and the pop-up dialog. Let’s have a look at implementing this functionality now. The full notification system is quite complicated, so we’ll break it down into stages. First, we’ll enhance our Message object so that it knows how to render a user interface for itself, both for when it is sitting in the status bar as an icon and when it is showing its full details, either in a tooltip or within the pop-up dialog. Let’s begin with the implementation of the status bar component.

6.4.1Rendering status bar icons

The status bar needs to render itself on the screen and contain the icons representing active messages. We delegate rendering of the individual icons to the

Implementing a notification framework

227

 

 

Message objects themselves. The Message will effectively implement a small-scale MVC pattern, with the rendering ability delivering a View, whose interactive features fulfill the role of Controller. Designing it this way could be problematic if we wished to add arbitrary alternative rendering mechanisms to our notifications framework. We don’t want to do that, however, because we want the notifications to be uniform across our application, for consistency’s sake. Listing 6.4 shows a rendering method for the Message object.

Listing 6.4 Message framework with user interface

msg.Message.prototype.render=function(el){ b Render message if (this.priority<=msg.PRIORITY_LOW.id){

this.renderSmall(el);

}else if (this.priority>=msg.PRIORITY_DEFAULT.id){ this.renderFull(el);

}

}

 

 

msg.Message.prototype.renderSmall=function(el){

c Render as icon with tooltip

this.icoTd=document.createElement("div");

 

var ico=document.createElement("img");

 

ico.src=this.icon;

 

 

ico.className="msg_small_icon";

 

 

this.icoTd.appendChild(ico);

 

 

this.icoTd.messageObj=this;

 

 

this.icoTd.onmouseover=msg.moverIconTooltip;

 

this.icoTd.onmouseout=msg.moutIconTooltip;

 

this.icoTd.onclick=msg.clickIconTooltip;

 

el.appendChild(this.icoTd);

 

 

}

 

 

msg.moverIconTooltip=function(e){

d Handle mouse-over events

var event=e || window.event;

 

 

var message=this.messageObj;

 

 

var popped=message.popped;

 

 

if (!popped){

 

 

message.showPopup(event,false);

 

 

}

 

 

}

e Handle mouse-out events

msg.moutIconTooltip=function(e){

var message=this.messageObj; var popped=message.popped; var pinned=message.pinned; if (popped && !pinned){

message.hidePopup();

}

}

228CHAPTER 6

The user experience

msg.clickIconTooltip=function(e){

f Handle mouse-click events

var event=e || window.event;

 

var message=this.messageObj;

 

var popped=message.popped;

 

var pinned=message.pinned;

 

var expired=message.expired;

 

if (popped && pinned){ message.hidePopup(); if (expired){

message.unrender();

}

}else{

message.showPopup(event,true);

}

}

msg.Message.prototype.showPopup=function(event,pinned){ g Display tooltip this.pinned=pinned;

if (!this.popup){ this.popup=document.createElement("div"); this.popup.className='popup'; this.renderFull(this.popup); document.body.appendChild(this.popup);

}

 

this.popup.style.display='block';

 

var popX=event.clientX;

 

var popY=event.clientY-xHeight(this.popup)-12;

 

xMoveTo(this.popup,popX,popY);

 

if (msg.popper && msg.popper!=this){

 

msg.popper.hidePopup();

 

}

 

this.popped=true;

 

msg.popper=this;

 

}

Hide tooltip

msg.Message.prototype.hidePopup=function(){

if (this.popped){ if (this.popup){

this.popup.style.display='none';

}

this.popped=false;

}

}

We’ve introduced the top-level rendering code for our Message object, and the specific details for the representation used in the status bar here. Let’s address the top-level code first. We provide a render() method b, which takes a DOM element as an argument. This delegates to either a renderSmall() c or renderFull() dmethod, based on the priority of the message. Messages being shown in

Implementing a notification framework

229

 

 

the status bar are always low priority, and will be displayed as an icon that presents a tooltip on mouseover (see figures 6.2 and 6.3).

renderSmall() renders the icon inside the DOM element and provides event handlers for displaying the pop-up tooltip.

Because this chapter is about adding professional polish to Ajax applications, the tooltip that we create for the icon has been implemented in a complete fashion, with three event handlers. It will appear when the mouse rolls over the icon e and disappear when the mouse moves off the icon f. If the icon is clicked, however, the tooltip becomes “pinned” g and will stay in place until either the icon is clicked again, the message expires, or another tooltip is selected (only one tooltip will be visible at any given time).

6.4.2Rendering detailed notifications

Messages in the dialog are either default or high priority, and will display an icon and a message alongside (see figure 6.4). We also need this type of display for the status-bar icons’ tooltips. When the tooltip is invoked in showPopup(), it calls the renderFull() method to present the full details of the message. The same method is reused to render messages in the dialog. This reuse saves us from duplicating unnecessary code and also ensures a high degree of visual consistency in the user interface. The renderFull() method is presented in listing 6.5.

Listing 6.5 renderFull() method

msg.Message.prototype.renderFull=function(el){ var inTable=(el.tagName=="TBODY");

var topEl=null; this.row=document.createElement("tr"); if (!inTable){

topEl=document.createElement("table"); var bod=document.createElement("tbody"); topEl.appendChild(bod); bod.appendChild(this.row);

}else{

topEl=this.row;

}

var icoTd=document.createElement("td"); icoTd.valign='center'; this.row.appendChild(icoTd);

var ico=document.createElement("img"); ico.src=this.icon; icoTd.className="msg_large_icon"; icoTd.appendChild(ico);