HomeASP.NET ASP.NET Custom Server Controls: Cute ToolT...
ASP.NET Custom Server Controls: Cute ToolTip Control with Better Framework
This article further extends my previous article on “Cute ToolTip control” with a few more enhancements, together with a flexible and understandable approach to the JavaScript code.
A downloadable file for this article is available here.
The sample downloadable solution (zip) is entirely developed using Visual Studio.NET 2003 Enterprise Architect on Windows Server 2003 Standard Edition. But, I am confident that it would work with other versions of Windows (which support .NET 1.1) as well.
How is it different from the old one?
I already introduced a technique for creating our own “tooltip” control for our web application. Even though it works well for that scenario, certain features are still missing. Let us consider what would happen if I wanted to add a HTML table within the tool tip. By using the method I discussed in my previous article, it is highly complicated. I actually designed that “tooltip” control simply to display some messages (and it works well only for that scenario).
But one of my colleagues asked me to improve it a bit, so that it would accept any HTML based content (because it is very easy to work with HTML, rather than with DHTML)! I liked his suggestion and started designing a flexible JavaScript framework (which is the main problem with my previous control) to achieve his expectations.
Finally, I came up with a solution by separating JavaScript content (from the custom control) to an external file (.js). This would cause the browser to cache the JavaScript file in memory, and we can even achieve better performance. Apart from simply writing structured JavaScript code, now I managed to redesign the JavaScript with some object orientation.
As you know, JavaScript is not a complete Object Oriented Programming language (actually it is an Object Based Language), so it is a bit difficult to abstract and encapsulate all the issues. But, somehow I managed to get it a bit encapsulated. As there is always room for new innovations (or enhancements), I hope that you would modify and extend the same control according to your necessities. Don’t forget to email me with your better enhancements.
Coming to the details of the “cute tool tip control” class, I am emitting only IFRAME tags and very little JavaScript code. I separated the whole burden of JavaScript code to a separate file (.js). But now you have to carry (of course even copy) the same file to every web application, which needs the tool tip functionality, unless you make an alternate arrangement by configuring your IIS to work for all web applications (from the same host).
Now that we understand some enhancements to my previous “Cute Tooltip control”, we shall delve into the details of code.
As I wanted the tooltip control to be as simple as possible, I declared only one property i.e., “IsDesignTime”. It is declared as “private” within the control class. It is created with the following code:
Private ReadOnly Property IsDesignTime() Get Return (Not Me.Site Is Nothing) AndAlso (Me.Site.DesignMode) End Get End Property
It checks whether the control is at the stage of design-time or run-time. This is very important for me to determine whether the control needs to emit JavaScript or not. During design-time, it is not necessary to emit JavaScript! It needs to be emitted only at run-time. You also need to observe that the property is “readonly” (no changes) and it is private (can be used only within the class and not outside the class). I used it only within the “Render” method.
To work with this control, we need to drag it from the toolbox (after adding it to the toolbox) onto the design surface. We can drag it to any location, as it is by default invisible at run-time. After placing it onto the surface, we need to bind the tooltip to all of our respective controls during the “page load” event. The following is the code-fragment I used as part of the demonstration:
Me.TextBox1.Attributes.Add("onMouseOver", "ShowToolTip (event,'this is first sample message',100);") Me.TextBox1.Attributes.Add("onMouseOut", "HideToolTip ();") Me.TextBox2.Attributes.Add("onMouseOver", "ShowToolTip (event,'this is second sample message',100);") Me.TextBox2.Attributes.Add("onMouseOut", "HideToolTip ();")
The first statement adds the “OnMouseOver” event attribute to “TextBox1” by calling the JavaScript function “ShowToolTip”. This is similar to the second statement with the “onMouseOut” event and “hideToolTip” JavaScript functions.
In that way, I used the same tooltip control for both “TextBox1” and “TextBox2” on my web page (as seen in the above code).
In my previous examples, I defined “RenderBeginTag”, “Render”, “RenderEndTag” and several other methods of rendering. In this scenario, as the control (tooltip) will not be displayed immediately after the web page gets rendered, certain methods are not used.
Finally, I ended up overriding only two methods from the base class “webcontrol”. They are as follows:
AddAttributesToRender
Render
Even though it is not essential to use the “AddAttributesToRender” method in this case, I used it to separate the registration of JavaScript code from the “Render” method. It is defined as follows:
Protected Overrides Sub AddAttributesToRender(ByVal writer As System.Web.UI.HtmlTextWriter) MyBase.AddAttributesToRender(writer) 'emit javascript only at run-time If Not IsDesignTime Then If Not Page.IsStartupScriptRegistered ("ToolTipFunctions") Then Page.RegisterStartupScript("ToolTipFunctions", getJS4ToolTip()) End If End If End Sub
Within the above method, I am trying to call the “MyBase.AddAttributesToRender(Writer)” statement to add any design-time attributes to my control. It is not essential for this control in this scenario, but this is a must when we design interactive controls (as explained in my previous articles of the same series).
And you can even observe that I am using the “IsDesignTime” method here. I would like to emit JavaScript code if, and only if, it is not design time in Visual Studio.NET. I think you can understand the rest. It's emitting JavaScript from a single function named “getJS4ToolTip” (which we will see in later sections). Coming to the “Render” method, it is defined as follows:
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter) AddAttributesToRender(writer) writer.Write("<iframe id=""frIFrame"" name=""frIFrame"" frameBorder=""0"" scrolling=""no"" ondrop=""return false;""></iframe>") End Sub
The above method gets executed immediately when the control has to render itself. The first statement tries to emit JavaScript code (if it is not design time). Immediately after that, I am emitting an embedded IFRAME (not at all enclosed in DIV as stated in my previous article). This emission of IFRAME is much simpler, when compared with the code available in my previous article for the same method.
Until now, we have seen only the ASP.NET custom control code, but didn’t go through JavaScript code at all. Now we shall go through the main JavaScript method “getJS4ToolTip” step by step:
Dim js As String js = "<script language=""javascript"" src=""IFrameBox.js""></script>"
The above simply declares “js” as a variable of string. It starts linking (or including) with external JavaScript file “IFrameBox.js”.
After that, we open another JavaScript tag and create an object for the “IFrameBox” class (defined in IFrameBox.js file) with the name of the IFRAMEID, the current object, width and height.
The above is a simple JavaScript based function, which simply shows the tooltip with the specified message and width. This would further call the functions in “IFrameBox.js”.
As, I included the entire source code, I will not be discussing very much about the inner workings of IFrameBox.js (it would simply take too many pages with the code). But, I will try to give you a brief on some of the functions I used (as part of the IFrameBox framework). The following is the list of functions I used:
The above is the list of all JavaScript functions which are part of the framework. Even though I didn’t use (or call) some of the functions at all, I just defined them for my future expansion of the same framework. As of now, you can use them as helper functions for your own enhancements.
The “IFrameBox” function creates (indirectly assigns) a new instance to the calling program. The “GetIFrameDocument” function simply gets the reference of the “document” object of IFRAME. The “RenderContent” function is considered to be heart of the framework as it displays (or renders) the entire HTML to the IFRAME. The “Resize” function simply resizes the IFRAME based on the content it has. The “PlaceAt” function simply places the IFRAME based on the X and Y positions of mouse pointer. The “IsVisible” function checks to see whether IFRAME is already visible or not. I hope you can easily understand “Show” and “Hide”. “IsBrowserIE”, “IsBrowserNS” and “IsBrowserFirefox” are helper functions to determine the type of browser being used.
That is a special type of class, which gets executed when the control is about to be rendered only at design time. Here it makes sense to use it, as there is no involvement of design-time properties to be set. It is defined something like this:
Public Class ToolTipDesigner Inherits System.Web.UI.Design.ControlDesigner
Public Overrides Function GetDesignTimeHtml() As String Return "You will be able to see the tooltips only at runtime" End Function End Class
The method “GetDesignTimeHtml” gets executed when our tooltip control is dragged from the toolbox onto the web page at design time. As the control does nothing here and it does not have any properties, we simply return a message.
This class (“ToolTipDesigner”) gets linked to our control with the “<Designer>” attribute at class level. The class declaration of our ToolTip control would be something like this:
<Designer(GetType(ToolTipDesigner)), DefaultProperty("Text"), ToolboxData("<{0}:ToolTip runat=server></{0}:ToolTip>")> Public Class ToolTip Inherits System.Web.UI.WebControls.WebControl
That finishes the matter. Please undestand that all of the ASP.NET controls (in this series) have been tested only with Internet Explorer 6.0. I request that you make necessary modifications to suit your needs of cross browser compatibility. I leave it to the developers for further enhancing the same control. The areas of improving the same control would include better eventing, better JavaScript, data-binding support, cross browser support, and so on. Good luck.
Any comments, suggestions, bugs, errors, feedback etc. are highly appreciated at jag_chat@yahoo.com.