Build a Message Box the AJAX Way: Part II

The Finishing Touches

Bipin Joshi

October 30, 2009

12 Min Read
ITPro Today logo

CodeTalk

LANGUAGES: C#

ASP.NETVERSIONS: 2.0 | 3.5

 

Build a Message Box the AJAX Way: Part II

The Finishing Touches

 

By Bipin Joshi

 

In Part I of this series we started developing the MessageBoxAJAX client control. The MessageBox client control displays message boxes withall the standard features (such as caption, icon, and buttons) of the Windowsmessage box. We developed various enumerations required by the MessageBoxcontrol, properties of the MessageBox class, and a few helper methods. This installmentbuilds on what we developed earlier. Specifically, we ll complete the helpermethods and various ShowXXXX methods, as well as package our control in anassembly for easy deployment.

 

Adding Buttons

One of the main functions of the MessageBox control is todisplay specific buttons as indicated by MessageBoxButtons enumerations. The_AddButtons private method accepts the message, the buttons to be displayed,and the default button. It then creates the required buttons on the fly andadds them to the message box panel. The _AddButtons method is shown in Figure1.

 

_AddButtons:function(msgbox,buttons,defaultbutton)

{

 if(buttons==BinaryIntellect.MessageBoxButtons.AbortRetryIgnore)

 {

   varptr=Function.createDelegate(this,this._HideMessageBox);

   var btnAbort =document.createElement('input');

   btnAbort.setAttribute('type',"button");

   btnAbort.setAttribute('value',"Abort");

   Sys.UI.DomElement.addCssClass(btnAbort,this._buttonCss);

   Sys.UI.DomEvent.addHandler(btnAbort,'click',ptr);

   var btnRetry =document.createElement('input');

   btnRetry.setAttribute('type',"button");

   btnRetry.setAttribute('value',"Retry");

   Sys.UI.DomElement.addCssClass(btnRetry,this._buttonCss);

   Sys.UI.DomEvent.addHandler(btnRetry,'click',ptr);

   var btnIgnore =document.createElement('input');

   btnIgnore.setAttribute('type',"button");

   btnIgnore.setAttribute('value',"Ignore");

   Sys.UI.DomElement.addCssClass(btnIgnore,this._buttonCss);

   Sys.UI.DomEvent.addHandler(btnIgnore,'click',ptr);

   msgbox.appendChild(btnAbort);

   msgbox.appendChild(btnRetry);

   msgbox.appendChild(btnIgnore);

   if(defaultbutton==BinaryIntellect.MessageBoxDefaultButton.Button1)

   {

      btnAbort.focus();

   }

   if(defaultbutton==BinaryIntellect.MessageBoxDefaultButton.Button2)

   {

     btnRetry.focus();

   }

   if(defaultbutton==BinaryIntellect.MessageBoxDefaultButton.Button3)

   {

     btnIgnore.focus();

   }

 }

...

Figure 1: Addingbuttons to the message box.

 

The _AddButtons method first decides how many buttons tocreate. Once a user clicks on a button we must invoke a callback method so themessage box can be hidden and our calling script is notified about the userselection. To do this, first create a delegate for the _HideMessageBox privatefunction. Then various buttons are created using the createElement method of thedocument object. Notice the use of the Sys.UI.DomElement and Sys.UI.DomEventclasses. The DomElement class represents an HTML DOM element and itsaddCssClass method allows us to apply a CSS class to a specified element. TheDomEvent class represents an HTML DOM event and its addHandler method allows usto wire an event handler with a DOM event. In our case we wire the click eventof the buttons to the _HideMessageBox function. The dynamically added buttonsare then added to the message box. Finally, focus is set to one of the buttonsusing the JavaScript focus method. The code fragment in Figure 1 shows Abort,Retry, and Ignore buttons being added. The other button variations follow asimilar pattern.

 

Making the Message Box Visible

When a message box is ready with the message, caption,icon, and buttons you can show it to the user. The actual job of showing amessage box is done by various ShowXXXX methods discussed later in this article,but all the ShowXXXX methods make use of a helper method (_MakeVisible; seeFigure 2).

 

_MakeVisible:function(msgbox)

{

 Sys.UI.DomElement.setVisible(msgbox,true);

 Sys.UI.DomElement.addCssClass(msgbox,this._boxCss);

 Sys.UI.DomElement.addCssClass(document.body,this._backgroundCss);

 if(this._left==-1&& this._top==-1)

 {

   this._left =(screen.availWidth - this._width) / 2;

   this._top =(screen.availHeight - this._height) / 2;

 }

 msgbox.style.width=this._width;

 msgbox.style.height=this._height;

 msgbox.style.left=this._left;

 msgbox.style.top=this._top;

}

Figure 2: Makingthe message box visible.

 

The _MakeVisible method essentially sets the left and topcoordinates of the message box and makes it visible. The setVisible method of theDomElement class sets the visibility of the message box to true. TheaddCssClass method applies the CSS class to the message box. If the Left andTop properties are not specified, we set default values to them. The styleattributes width, height, left, and top are then set.

 

Hiding the Message Box

The _HideMessageBox method is called when a user clicks onany of the message box buttons. The complete code of _HideMessageBox is shownin Figure 3.

 

_HideMessageBox:function()

{

 Sys.UI.DomElement.removeCssClass(document.body,this._backgroundCss);

 Sys.UI.DomElement.setVisible(this._element,false);

 if(event.srcElement.value=='OK')

 {

   this._dialogResult=BinaryIntellect.DialogResult.OK;

 }

 if(event.srcElement.value=='Cancel')

 {

   this._dialogResult=BinaryIntellect.DialogResult.Cancel;

 }

 if(event.srcElement.value=='Yes')

 {

   this._dialogResult=BinaryIntellect.DialogResult.Yes;

 }

 if(event.srcElement.value=='No')

 {

   this._dialogResult=BinaryIntellect.DialogResult.No;

 }

 if(event.srcElement.value=='Abort')

 {

   this._dialogResult=BinaryIntellect.DialogResult.Abort;

 }

 if(event.srcElement.value=='Retry')

 {

   this._dialogResult=BinaryIntellect.DialogResult.Retry;

 }

 if(event.srcElement.value=='Ignore')

 {

   this._dialogResult=BinaryIntellect.DialogResult.Ignore;

 }

 this._callback(this._dialogResult);

}

Figure 3: Hidingthe message box.

 

The _HideMessageBox method first removes the CSS classapplied to the page body and hides the message box. Depending on the buttonclicked by the user (as indicated by the event.srcElement property), theDialogResult property of the MessageBox class is set. Finally, the callbackmethod as indicated by the CloseCallback property is invoked. This way you canwire a custom operation once the message box is closed. Note that the callbackfunction receives a parameter of type DialogResult.

 

Showing the Message Box

Now that we ve completed all the helper methods, let s addvarious ShowXXXX methods. The ShowXXXX methods prepare the message box and showit to the user. Figure 4 shows the complete list of ShowXXXX methods.

 

Method

Description

_ShowPlain

Displays the message box with only an OK button, but without any additional features such as caption, icon, or additional buttons.

_ShowCaption

Displays a message box with a message, caption, and OK button.

_ShowButtons

Displays a message box with a message, caption, and buttons, as indicated by the MessageBoxButtons enumeration.

_ShowIcon

Displays a message box with a message, caption, buttons, and icon, as indicated by the MessageBoxIcon enumeration.

_ShowDefaultButton

Displays a message box with a message, caption, buttons, icon, and default button, as indicated by the MessageBoxDefaultButton enumeration.

Figure 4: List ofShowXXXX methods.

 

Because most of them do similar jobs we won t discuss everyShowXXXX method. Figure 5 shows the code for the _ShowDefaultButton method.

 

_ShowDefaultButton:function(message,caption,buttons,

                           icon,defaultbutton)

{

 var msgbox=this._element;

 msgbox.innerHTML="";

 this._MakeVisible(msgbox);

 this._AddCaption(msgbox,caption);

 this._AddIcon(msgbox,message,icon);

 this._AddButtons(msgbox,buttons,defaultbutton);

}

Figure 5: Showing amessage box with caption, buttons, icon, and default button.

 

The _ShowDefaultButton method is the most expansive methodin that it accepts all the parameters (message, caption, buttons, icon, anddefault button). It then gets a reference of the base element that indicatesthe message box. It then calls various helper methods to attach requiredfeatures. For example, the code from Figure 5 calls the _AddCaption method toset a caption, the _AddIcon method to specify an icon, and the _AddButtonsmethod to add the required buttons. The _MakeVisible method makes the messagebox visible to the user. This completes our MessageBox control; we are ready touse it in our Web forms.

 

Using the MessageBox Control

Now that our MessageBox control is ready, let s put it touse in our Web form. Begin by adding a new CSS style sheet into your Web site,adding to it the CSS classes shown in Figure 6.

 


The modalBackground CSS class is intended for thebackground body when the message box is being displayed. The msgbox, caption,and button CSS classes are meant for the message box, caption of the messagebox, and buttons of the message box, respectively. Refer to the style sheet wejust created in the Web form using a tag. Next, add an HTML buttonand a

tag inside thetag, as shown in Figure 7.

 

Figure 7: Markupof a Web form that uses the message box.

 

When clicked, the HTML button calls the JavaScriptfunction ShowMsgBox (we ll write the ShowMsgBox function in a moment). The

with ID of divMsgBox acts as the message box. Thisacts as theoutermost container for the message, caption, icon, and buttons that we adddynamically. The ShowMsgBox function, which you can add in a block, is shown in Figure 8.</p><p> &nbsp;</p><p>function ShowMsgBox()</p><p>{</p><p>&nbsp;var msgbox=newBinaryIntellect.MessageBox($get('divMsgBox')); </p><p>&nbsp;msgbox.set_BoxCss('msgbox'); </p><p>&nbsp;msgbox.set_CaptionCss('caption'); </p><p>&nbsp;msgbox.set_BackgroundCss('modalBackground'); </p><p>&nbsp;msgbox.set_ButtonCss('button'); </p><p>&nbsp;msgbox.set_CloseCallback(OnComplete); </p><p>&nbsp;msgbox.set_Left(100); </p><p>&nbsp;msgbox.set_Top(200); </p><p>&nbsp;msgbox.set_Width(300); </p><p>&nbsp;msgbox.set_Height(100); </p><p>&nbsp;msgbox.Show("Theprocessing is over. Do you wish to print the&nbsp;</p><p>&nbsp;&nbsp;&nbsp;report?","Print",BinaryIntellect.MessageBoxButtons.YesNo, </p><p>&nbsp;&nbsp;&nbsp;BinaryIntellect.MessageBoxIcon.Question, </p><p>&nbsp;&nbsp;&nbsp;BinaryIntellect.MessageBoxDefaultButton.Button1); </p><p>}</p><p><b>Figure 8:</b>Consuming the message box control. </p><p> &nbsp;</p><p> The ShowMsgBox function creates an instance of ourMessageBox class by passing a reference to the <DIV> tag. Notice the useof the $get shortcut (instead of the document.getElementByID method) to get areference to a specified DOM element. We then set various CSS classes usingBoxCss, CaptionCss, BackgroundCss, and ButtonCss properties. The Left, Top,Height, and Width properties are also set. The CloseCallback property is set toanother JavaScript function (OnComplete). Finally, the Show method of theMessageBox class is called by passing various parameters. Notice the use of theenumerations we created earlier.</p><p> &nbsp;</p><p> The ShowMsgBox function simply displays the message box tothe user as per our settings. Equally important, however, is to process theuser selection. This is done inside the OnComplete function, shown in Figure 9. </p><p> &nbsp;</p><p>function OnComplete(dialogresult) </p><p>{</p><p>&nbsp;var msg="Youselected "; </p><p>&nbsp;switch(dialogresult) </p><p>&nbsp;{ </p><p>&nbsp;&nbsp;&nbsp;caseBinaryIntellect.DialogResult.OK: </p><p>&nbsp;&nbsp;&nbsp;msg += "OK"; </p><p>&nbsp;&nbsp;&nbsp;break; </p><p>&nbsp;caseBinaryIntellect.DialogResult.Cancel: </p><p>&nbsp;&nbsp;&nbsp;msg +="Cancel"; </p><p>&nbsp;&nbsp;&nbsp;break; </p><p>&nbsp;caseBinaryIntellect.DialogResult.Yes: </p><p>&nbsp;&nbsp;&nbsp;msg += "Yes"; </p><p>&nbsp;&nbsp;&nbsp;break; </p><p>&nbsp;caseBinaryIntellect.DialogResult.No: </p><p>&nbsp;&nbsp;&nbsp;msg += "No"; </p><p>&nbsp;&nbsp;&nbsp;break; </p><p>&nbsp;caseBinaryIntellect.DialogResult.Abort: </p><p>&nbsp;&nbsp;&nbsp;msg +="Abort"; </p><p>&nbsp;&nbsp;&nbsp;break; </p><p>&nbsp;caseBinaryIntellect.DialogResult.Retry: </p><p>&nbsp;&nbsp;&nbsp;msg +="Retry"; </p><p>&nbsp;&nbsp;&nbsp;break; </p><p>&nbsp;caseBinaryIntellect.DialogResult.Ignore: </p><p>&nbsp;&nbsp;&nbsp;msg +="Ignore"; </p><p>&nbsp;&nbsp;&nbsp;break; </p><p>&nbsp;} </p><p>&nbsp;alert(msg); </p><p>}</p><p><b>Figure 9:</b> The callbackfunction invoked after user selection. </p><p> &nbsp;</p><p> Recollect that the OnComplete function is a callback thatwill be invoked by the _HideMessageBox private function of the MessageBoxclass. The OnComplete function receives a parameter of type DialogResult enumeration.Though we can compare the enumeration values as integers for the sake of betterreadability, it is recommended to use enumerated values. Simply construct astring message based on the DialogResult value and display it to the user.Figures 10 and 11 show a sample run of the Web form. </p><p> &nbsp;</p><p><img width="241" height="200" src="https://www.itprotoday.com/content/legacy/images/asp200809bj_f_image004.jpg"><br><b>Figure 10:</b> Message box beingdisplayed.</p><p> &nbsp;</p><p><img width="241" height="197" src="https://www.itprotoday.com/content/legacy/images/asp200809bj_f_image006.jpg"><br><b>Figure 11:</b> Callback function calledafter user clicks the Yes button. </p><p> &nbsp;</p><h3>Deploying the MessageBox Control as a Script File</h3><p> So far we wrote the MessageBox class inside a Web form.Most probably the chances are that you ll need to consume the MessageBox classfrom multiple Web forms. The common approach in such situations is to place allthe AJAX code in a separate script file, then refer the file using theScriptManager control. Let s follow this approach for our control. Add a newAJAX client control to your Web site using the Add New Item dialog box (seeFigure 12). </p><p> &nbsp;</p><p><img width="333" height="224" src="https://www.itprotoday.com/content/legacy/images/asp200809bj_f_image008.jpg"><br><b>Figure 12:</b> Adding a new AJAX clientcontrol.</p><p> &nbsp;</p><p> Name the client control file MessageBox.js. When the fileis added to your Web site, move the entire MessageBox control class to theMessageBox.js file. Then locate the Scripts collection property of theScriptManager control and add the MessageBox.js to the Scripts collection, asshown in Figure 13. </p><p> &nbsp;</p><p><img width="319" height="236" src="https://www.itprotoday.com/content/legacy/images/asp200809bj_f_image010.jpg"><br><b>Figure 13:</b> Referring MessageBox.jsfile using the ScriptManager control.</p><p> &nbsp;</p><p> Notice that we set the Path property to ~/MessageBox.js,which causes the ScriptManager control to refer the script at run time. Youcould ve achieved the same result using the traditional <script src= ... >tag, but using the ScriptManager approach is more readable and manageable forAJAX scripts and controls. Now we can use the MessageBox control on any Webform of the Web site by referring it via the ScriptManager control.</p><p> &nbsp;</p><h3>Deploying the MessageBox Control as an Assembly</h3><p> Although deploying the MessageBox control as a script fileis better that inline script, it is essentially a source-code-based deployment.What if you want to reuse the same control in multiple Web sites and don t wantanyone to view or change the source code? In such cases we can bundle ourscript files in an assembly, so what gets deployed along with a Web site is anassembly and not the script file. </p><p> &nbsp;</p><p> To learn how this works, begin by adding a new class librarytype of project to the same solution. Let s name the class library MsgBoxLib.Then move the MessageBox.js file to the class library project. Using theProperty Window, set its Build Action property to Embedded Resource (see Figure14). This way the script file is treated as an embedded resource rather thansource code.</p><p> &nbsp;</p><p><img width="152" height="154" src="https://www.itprotoday.com/content/legacy/images/asp200809bj_f_image012.jpg"><br><b>Figure 14:</b> Adding MessageBox.js toan assembly as an embedded resource.</p><p> &nbsp;</p><p> Next, refer the System.Web assembly in the class libraryproject. The System.Web assembly supplies the [WebResource] attribute that allowsus to mark embedded resources from an assembly as Web-callable. Open theAssemblyInfo.cs of the class library project and import the System.Web.UInamespace. Then place the [WebResource] attribute as shown in Figure 15.</p><p> &nbsp;</p><p>using System.Web.UI; </p><p>...</p><p> [assembly:WebResource("MsgBoxLib.MessageBox.js", </p><p>"application/x-javascript")]</p> <p><b>Figure 15:</b> Addingthe [WebResource] attribute. </p><p> &nbsp;</p><p> The [WebResource] attribute takes two parameters. Thefirst parameter is the fully qualified name of the embedded resource; thesecond parameter is the content type of the resource. Notice that the fullyqualified name also includes the .js extension. The content type indicates thatit is a JavaScript resource.</p><p> &nbsp;</p><p> Now build the class library and refer it in the Web site.Referring the assembly will add its copy to the BIN folder of the Web site.Open the Scripts collection property of the ScriptManager control again. Thistime, configure it as shown in Figure 16. </p><p> &nbsp;</p><p><img width="319" height="236" src="https://www.itprotoday.com/content/legacy/images/asp200809bj_f_image014.jpg"><br><b>Figure 16:</b> Referring an embeddedscript from an assembly.</p><p> &nbsp;</p><p> Here we set two properties: Assembly and Name. TheAssembly property specifies the name of the assembly that is supplying theresource. The Name property specifies the fully qualified name of the resource.If you test the Web form again, it should work exactly as before. Now you candeploy the MsgBoxLib assembly along with your Web sites instead of theMessageBox.js script file.</p><p> &nbsp;</p><h3>Conclusion</h3><p> In this two-part series we developed an AJAX clientcontrol, MessageBox, which mimics the Windows Forms message box and supportsfeatures such as caption, icon, and buttons. In this second installment wecompleted the ShowXXXX methods that display a message box to the user, alongwith a few other private methods. The AJAX classes such as DomElement andDomEvent provide a standardized, browser-independent way to deal with HTMLelements and their events. We then consumed the MessageBox control on a test Webform. We then discussed two schemes to deploy the MessageBox control: deployingas a script file and deploying as an assembly. Deploying AJAX scripts embeddedin an assembly provides a neat mechanism when you don t want others to view orchange your code easily.</p><p> &nbsp;</p><p> As an improvement, you can focus on making the scriptbrowser-independent. You also can add more jazz to the message box in the formof shadows or animations. Support for dragging would be a nice addition, aswell.</p><p> &nbsp;</p><p> <i>The source codeaccompanying this article is available for download. </i></p><p> &nbsp;</p><p><b>Bipin Joshi</b> is theproprietor of BinaryIntellect Consulting (<a href="https://www.binaryintellect.com/" target="_blank">http://www.binaryintellect.com</a>)where he conducts premier training programs on a variety of .NET technologies.He wears many hats, including software consultant, mentor, prolific author, Webmaster,Microsoft MVP, and member of ASPInsiders. Having adopted Yoga as a way of life,Bipin also teaches Kriya Yoga. He can be reached via his blog at <a href="https://www.bipinjoshi.com/" target="_blank">http://www.bipinjoshi.com</a>.</p><p> &nbsp;</p><p> &nbsp;</p><p> &nbsp;</p>

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like