YOUR FEEDBACK
andy.mulholland wrote: intriguing !!! We have full scale 'Mashup Factories' in Chicago USA and Utrec...
AJAXWorld RIA Conference
Early Bird Savings Expire Friday Register Today and SAVE !..

SYS-CON.TV

2008 East
DIAMOND SPONSOR:
Data Direct
Frontiers in Data Access: The Coming Wave in Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
Intel
Virtualization – Path to Predictive Enterprise
Green Hills
IT Security in a Hostile World
JBoss / freedom oss
Practical SOA Approach
GOLD SPONSORS:
Software AG
The Art & Science of SOA: How Governance Enables Adoption
PlateSpin
Effective Planning for Virtual Infrastructure Growth
Fujitsu
Automated Business Process Discovery & Virtualization Service
Ceedo
Workspace Virtualization
Click For 2007 West
Event Webcasts

2008 East
PLATINUM SPONSORS:
Appcelerator
Think Fast: Accelerate AJAX Development with Appcelerator
GOLD SPONSORS:
DreamFace Interactive
The Ultimate Framework for Creating Personalized Web 2.0 Mashups
ICEsoft
AJAX and Social Computing for the Enterprise
Kaazing
Enterprise Comet: Real–Time, Real–Time, or Real–Time Web 2.0?
Nexaweb
Now Playing: Desktop Apps in the Browser!
Sun
jMaki as an AJAX Mashup Framework
POWER PANELS:
The Business Value
of RIAs
What Lies Beyond AJAX?
KEYNOTES:
Douglas Crockford
Can We Fix the Web?
Anthony Franco
2008: The Year of the RIA
Click For 2007 Event Webcasts
TOP THREE LINKS YOU MUST CLICK ON


Real-World AJAX Book Preview: The Code
Real-World AJAX Book Preview: The Code

This content is reprinted from Real-World AJAX: Secrets of the Masters published by SYS-CON Books. To order the entire book now along with companion DVDs for the special pre-order price, click here for more information. Aimed at everyone from enterprise developers to self-taught scripters, Real-World AJAX: Secrets of the Masters is the perfect book for anyone who wants to start developing AJAX applications.

The Code
The AjaxWord client consists of JavaScript and HMTL code. The application's user interface is defined in HTML. Client-side logic written in JavaScript defi nes the behavior of the user interface by leveraging a generic JavaScript/DHTML toolkit that's built from scratch. From a Model-View-Controller perspective, the HTML files are "Views" and the JavaScript code acts as "Controllers."

The JavaScript/DHTML toolkit defi nes all the UI widgets. By separating UI widgets from the application, it's easier to develop and maintain the application code. Because of the level of richness required by AjaxWord and the limited availability of AJAX toolkits in the late 1990s, this entire toolkit was written from scratch. It would have been easier to build AjaxWord today by leveraging some of the available toolkits that have emerged in the last 12 months.

A Generic DHTML/JavaScript Toolkit
The AjaxWord DHTML/JavaScript toolkit is a generic toolkit that contains a list of rich user interface components, event management, and code for doing asynchronous communications.

In Figure 15.10, the left items are available with Web browsers. All other items aren't available in browsers and have to be built from scratch. In addition to UI elements, the toolkit provides a systematic way of managing UI events and doing asynchronous communications. When the application was written, the popular XmlHttpRequest object wasn't available in browsers, so AjaxWord actually uses hidden frames to asynchronously communicate.

Instead of elaborating on how each component is built, we will use the "window" object as an example. The window object that we are referring to is a draggable, resizable window that resides inside a standard browser window, giving the look-and-feel of a multiple document interface. It is a basic component for desktop application user interfaces, but isn't available for Web applications.

Creating a "Window" Widget

Figure 15.11 shows how an AjaxWord UI Toolkit window is running inside a browser alongside some HTML text. We'll explain how to define its view and its behavior below.

Defining the View
The view is defined using HTML. To mimic a window look, the view defines 14 different areas of a "window" user interface: the four corners, the four edges, the window content, the title bar, and the four window control areas (close, maximize, minimize, and the window icon). Figure 15.12 shows how a window user interface is split into 14 different regions.

Each window area is defined by a "DIV" tag. For the four corners and four edges, each DIV tag contains an image. Each of the four window controls also contain an image. When necessary, these images can be changed according to style requirements. Some of DIV tags have event handlers defined too so that the window can respond to events. The view definition code is shown in Listing 15.1.

Listing 15.1

<DIV ID="wctl" onmousedown=_nwWindowMouseDown(this)
   onselectstart="event.cancelBubble=true;return true;"
  STYLE="BACKGROUND-IMAGE: url(../images/corner-tl.gif); CLIP: rect(0px 16px 16px 0px);
CURSOR: move; HEIGHT: 16px; LEFT: 0px; POSITION: absolute; TOP: 0px; VISIBILITY: visible;
WIDTH: 16px; repeat: no"></DIV>
<DIV ID="wctr" onmousedown=_nwWindowMouseDown(this)
   onselectstart="event.cancelBubble=true;return true;"
   STYLE="BACKGROUND-IMAGE: url(../images/corner-tr.gif); CLIP: rect(0px 16px 16px 0px);
CURSOR: move; HEIGHT: 16px; LEFT: 284px; POSITION: absolute; TOP: 0px; VISIBILITY:
visible; WIDTH: 16px; repeat: no"></DIV>
<DIV ID="wcbl" onmousedown=_nwWindowMouseDown(this)
   onselectstart="event.cancelBubble=true;return true;"
   STYLE="BACKGROUND-IMAGE: url(../images/corner-bl.gif); CLIP: rect(0px 16px 16px 0px);
CURSOR: move; HEIGHT: 16px; LEFT: 0px; POSITION: absolute; TOP: 184px; VISIBILITY:
visible; WIDTH: 16px; repeat: no"></DIV>
<DIV ID="wcbr" onmousedown=_nwWindowMouseDown(this)
   onselectstart="event.cancelBubble=true;return true;"
   STYLE="BACKGROUND-IMAGE: url(../images/corner-br.gif); CLIP: rect(0px 16px 16px 0px);
CURSOR: move; HEIGHT: 16px; LEFT: 284px; POSITION: absolute; TOP: 184px; VISIBILITY:
visible; WIDTH: 16px; repeat: no"></DIV>
<DIV ID="wEdgeLeft" onmousedown=_nwWindowMouseDown(this)
   onselectstart="event.cancelBubble=true;return true;"
   STYLE="BACKGROUND-IMAGE: url(../images/border-v.gif); CLIP: rect(0px 6px 168px 0px);
CURSOR: w-resize; HEIGHT: 168px; LEFT: 0px; POSITION: absolute; TOP: 16px; VISIBILITY:
visible; WIDTH: 6px; repeat: yes"></DIV>
<DIV ID="wEdgeTop" onmousedown=_nwWindowMouseDown(this)
   onselectstart="event.cancelBubble=true;return true;"
   STYLE="BACKGROUND-IMAGE: url(../images/border-h.gif); CLIP: rect(0px 268px 6px 0px);
CURSOR: n-resize; HEIGHT: 6px; LEFT: 16px; POSITION: absolute; TOP: 0px; VISIBILITY:
visible; WIDTH: 268px; repeat: yes"></DIV>
<DIV ID="wEdgeBtm" onmousedown=_nwWindowMouseDown(this)
   onselectstart="event.cancelBubble=true;return true;"
   STYLE="BACKGROUND-IMAGE: url(../images/border-h.gif); CLIP: rect(0px 268px 6px 0px);
CURSOR: s-resize; HEIGHT: 6px; LEFT: 16px; POSITION: absolute; TOP: 194px; VISIBILITY:
visible; WIDTH: 268px; repeat: yes"></DIV>
<DIV ID="wEdgeRight" onmousedown=_nwWindowMouseDown(this)
   onselectstart="event.cancelBubble=true;return true;"
   STYLE="BACKGROUND-IMAGE: url(../images/border-v.gif); CLIP: rect(0px 6px 168px 0px);
CURSOR: e-resize; HEIGHT: 168px; LEFT: 294px; POSITION: absolute; TOP: 16px; VISIBILITY:
visible; WIDTH: 6px; repeat: yes"></DIV>
<iframe id="wContentFrame" NAME="wContentFrame"
   STYLE="BACKGROUND-COLOR: #76efb1; CLIP: rect(0px 288px 142px 0px); HEIGHT: 142px;
LEFT: 6px; POSITION: absolute; TOP: 31px; VISIBILITY: visible; WIDTH: 288px"
   SRC="about:blank"></iframe>
<DIV ID="wTitleBar"
   onselectstart="event.cancelBubble=true;return false;"
   STYLE="CLIP: rect(0px 288px 24px 0px); CURSOR: default; HEIGHT: 24px; LEFT: 6px; POSITION:
absolute; TOP: 6px; VISIBILITY: visible; WIDTH: 288px">
<DIV ID="wClose" onmouseup="_nwWindowMouseDown(this)"
   title="click here to close the window"
   STYLE="CLIP: rect(0px 20px 20px 0px); HEIGHT: 20px; LEFT: 268px; POSITION: absolute;
TOP: 0px; VISIBILITY: visible; WIDTH: 20px"><A
   href="JavaScript://"><IMG border=0 id=wCloseImg
   onselectstart="event.cancelBubble=true;return false;"
   src="../images/close0.gif" width="20" height="20"></img></a></DIV>
<DIV ID="wMax" onmouseup="_nwWindowMouseDown(this)"
   title="click here to maximize the window"
   STYLE="CLIP: rect(0px 20px 20px 0px); HEIGHT: 20px; LEFT: 248px; POSITION: absolute;
TOP: 0px; VISIBILITY: visible; WIDTH: 20px"><A
   href="JavaScript://"><IMG border=0 id=wMaxImg
   onselectstart="event.cancelBubble=true;return false;"
   src="../images/max0.gif" width="20" height="20"></a></DIV>
<DIV ID="wMin" onmouseup="_nwWindowMouseDown(this)"
   title="click here to minimize the window"
   STYLE="CLIP: rect(0px 20px 20px 0px); HEIGHT: 20px; LEFT: 228px; POSITION: absolute;
TOP: 0px; VISIBILITY: visible; WIDTH: 20px"><A
   href="JavaScript://"><IMG border=0 id=wMinImg
   onselectstart="event.cancelBubble=true;return false;"
   src="../images/min0.gif" width="20" height="20"></a></DIV>
<nobr>
<DIV ID="wTitle" onselectstart="event.cancelBubble=true;return false;"
   STYLE="CLIP: rect(0px 208px 24px 0px); FONT-FAMILY: Arial; FONT-SIZE: 14px; FONTWEIGHT:
bold; HEIGHT: 24px; LEFT: 20px; POSITION: absolute; TOP: 0px; VISIBILITY: visible;
WIDTH: 208px"> <SPAN
   ID="wTitleText" onselectstart="event.cancelBubble=true;return false;">Loading...</
SPAN></DIV>
</nobr>
<DIV ID="wIcon"
   STYLE="CLIP: rect(0px 20px 20px 0px); HEIGHT: 20px; LEFT: 0px; POSITION: absolute;
TOP: 0px; VISIBILITY: visible; WIDTH: 20px"><A
   href="JavaScript://"><IMG border=0 id=wIconImg
   onselectstart="event.cancelBubble=true;return false;"
   src="../images/icon.gif" width="20" height="20"></a></DIV>
</DIV>
<DIV ID="wTitleSep"
   STYLE="BACKGROUND-COLOR: #62659c; CLIP: rect(0px 288px 1px 0px); CURSOR: default;
HEIGHT: 1px; LEFT: 6px; POSITION: absolute; TOP: 30px; VISIBILITY: visible; WIDTH:
288px"></DIV>
<nobr>
<DIV ID="wStatus" onselectstart="event.cancelBubble=true;return false;"
   STYLE="BACKGROUND-COLOR: #e2e2e2; CLIP: rect(0px 288px 20px 0px); CURSOR: default;
FONT-FAMILY: Arial; FONT-SIZE: 12px; HEIGHT: 20px; LEFT: 6px; POSITION: absolute; TOP:
174px; VISIBILITY: visible; WIDTH: 288px"> <SPAN
   ID="wStatusText" onselectstart="event.cancelBubble=true;return false;">Status</SPAN></
DIV>
</nobr>
<DIV ID="wStatusSep"
   STYLE="BACKGROUND-COLOR: #62659c; CLIP: rect(0px 288px 1px 0px); HEIGHT: 1px; LEFT:
6px; POSITION: absolute; TOP: 173px; VISIBILITY: visible; WIDTH: 288px"></DIV>

Defining the Controller
The controller logic of a window widget is defined using JavaScript. The JavaScript file "NWindow.js" is one of the controllers that define the basic behavior of a window widget.

Window Initialization
When a window is created, "NWindow.js" initializes it by connecting the JavaScript object with the "view" object (HTML code), hooking up event handlers and initializing object properties. Here is the initialization code:

Listing 15.2

function NWindow(title,parentLayer,x,y,w,h,pwin,windowDefinitionFile)
{
   this.jPanel=JPanel;
   this.jPanel(parentLayer,x,y,w,h,null,true,null,true,true,pwin);
   objectManager.add(this);

   if(!windowDefinitionFile)
     windowDefinitionFile="../client_lib/windowTemplate.html";
   this.load(windowDefinitionFile);

   this.title=title;
   this.titleBarHeight=24;
   this.statusBarHeight=20;
   this.statusText="Copyright(C)1996-2005, Coach Wei (<a href='http://www.coachwei.
com'>blog</a>). Open Source licensed.";
   this.borderWidth=6;
   this.iconWidth=20;
   this.iconLength=200;
   this.iconized=false;
   this.winIcon="../images/icon.gif";
   this.corner=16;
   this.separator=1;
   this.color = new Object();
   this.color.titleUnfocused = '#cdceff';
   this.color.titleFocused='#00ffff';
   this.color.iconFocused='#aaffff';
   this.color.iconUnfocused="#bbbbbb";
   this.color.tileTextUnfocused="menu";
   this.color.titleTextFocused="highlighttext";
   this.className="NWindow";
   this.initWindow=_nWindowInitWindow;
   this.onMouseDown=_nwWindowMouseDown;
   this.onMouseUp=_nWindowOnMouseUp;
   this.onFocus=_nWindowOnFocus;
   this.onBlur=_nWindowOnBlur;
   this.repaintResize=_nWindowRePaintResize;
   this.addToTaskbar=_nWindowAddToTaskbar;
   this.startResize=_nwWindowStartResize;
   this.resize=_nWindowSetSize;
   this.iconize=_nWindowIconize;
   this.onClose=_nWindowOnClose;
   this.onMaximize=_nWindowOnMaximize;
   this.onMinimize=_nWindowOnMinimize;
   this.setTitle=_nWindowSetTitle;
   this.setIcon=_nWindowSetIcon;
   this.setStatus=_nWindowSetStatus;
   this.sizeContent=_nWindowSizeContent;
   this.loadContent=_nWindowLoad;
   this.getWindowSize=_getBrowserWindowSize;
}

function _nWindowInitWindow(win)
{
   if(!win||!win.document) return;
   this.doc=win.document;
   this.wctl=this.getJPanelFor("wctl",win);
   this.wctl.domObj.parentCtrl=this;
   this.wctr=this.getJPanelFor("wctr",win);
   this.wctr.domObj.parentCtrl=this;
   this.wcbr=this.getJPanelFor("wcbr",win);
   this.wcbr.domObj.parentCtrl=this;
   this.wcbl=this.getJPanelFor("wcbl",win);
   this.wcbl.domObj.parentCtrl=this;
   this.wEdgeTop=this.getJPanelFor("wEdgeTop",win);
   this.wEdgeTop.domObj.parentCtrl=this;
   this.wEdgeBtm=this.getJPanelFor("wEdgeBtm",win);
   this.wEdgeBtm.domObj.parentCtrl=this;
   this.wEdgeLeft=this.getJPanelFor("wEdgeLeft",win);
   this.wEdgeLeft.domObj.parentCtrl=this;
   this.wEdgeRight=this.getJPanelFor("wEdgeRight",win);
   this.wEdgeRight.domObj.parentCtrl=this;
   this.wTitleBar=this.getJPanelFor("wTitleBar",win);
   this.wTitleBar.domObj.parentCtrl=this;
   this.wIcon=this.getJPanelFor("wIcon",win);
   this.wTitle=this.getJPanelFor("wTitle",win);
   this.wTitle.domObj.parentCtrl=this;
   this.wClose=this.getJPanelFor("wClose",win);
   this.wClose.domObj.parentCtrl=this;
   this.wMax=this.getJPanelFor("wMax",win);
   this.wMax.domObj.parentCtrl=this;
   this.wMin=this.getJPanelFor("wMin",win);
   this.wMin.domObj.parentCtrl=this;
   this.wTitleSep=this.getJPanelFor("wTitleSep",win);
   this.wStatus=this.getJPanelFor("wStatus",win);
   this.wStatusSep=this.getJPanelFor("wStatusSep",win);
   this.wContent=this.getJPanelFor("wContentFrame",win,false,true);
   if(this.wContent.domObj) this.wContent.domObj.parentCtrl=this;
   this.wTitleText=win.document.all["wTitleText"];
   this.wStatusText=win.document.all["wStatusText"];
   this.wIconImg=win.document.all["wIconImg"];
   this.setDragable(true);
   top.dragManager.setGrab(this,this.borderWidth,this.borderWidth,this.getWidth()-
3*this.iconWidth-2*this.borderWidth,this.titleBarHeight);
   if(this.resize) this.resize(this.w,this.h);
   if(top._initSystemEvent)
   {
     top._initSystemEvent(win);
     top._initSystemEvent(this.wContent.iframe.frame);
   }
}

This content is reprinted from Real-World AJAX: Secrets of the Masters published by SYS-CON Books. To order the entire book now along with companion DVDs, click here to order.

About Coach Wei
Coach Wei is the Founder and Chairman of Nexaweb (www.nexaweb.com), developers of the leading software platform for building and deploying Web 2.0 and AJAX applications. Previously, he played a key role at EMC Corporation in the development of a new generation of storage network management software. Wei has his master's degree from MIT, holds several patents, is the author of several technology publications including JDJ, Web 2.0 Journal, and AJAXWorld Magazine, and is an industry advocate for the proliferation of open standards.

LATEST AJAXWORLD RIA STORIES
"Improve the user interface of old client-server applications and delight your users while reducing the TCO," says Curl Chief Strategy Officer Jnan Dash in this Exclusive Q&A with SYS-CON's AJAX & RIA Journal in the run-up to his session on October 20 at AJAX World RIA Conference...
"My mission has always been to bring excellence to the field of user interface engineering," says Bill Scott, Director of User Interface Engineering at Netflix, in this Exclusive Q&A with SYS-CON's AJAX & RIA Journal in the run-up to his session on October 20 at AJAX World RIA Co...
SYS-CON Events announced today that the leading global SOA technology provider WSO2 named "Silver Sponsor" of SYS-CON's upcoming SOA World Conference & Expo 2008 West, which will take place November 19-21, 2008, at the Fairmont Hotel in the heart of Silicon Valley, in San Jose, C...
'We're dedicated to building the largest open-source community dedicated to RIAs, breaking down the barriers between traditional preferred languages, programming models and solutions,' says the co-founder & CEO of Appcelerator, Jeff Haynie, in this Exclusive Q&A with Jeremy Geela...
'While the last decade was focused on the Web, the next phase in the evolution of our industry will be on the convergence of Web, mobile and desktop applications and the ability to extend existing applications with these new technologies for a consistent user experience regardles...
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON FEATURED WHITEPAPERS

ADS BY GOOGLE