OverLibWrapper -- C# wrapper of the overLIB DHTML popup JavaScript library






4.67/5 (11 votes)
An article on the use of the OverlibPageControl and OverlibPopupAnchor for extended manipulation of the overLIB popup JavaScript library.
Introduction
There are plenty of popup controls out there; just do a Google search and thousands will pop up (no pun intended). More often than not, these implementations are either pure JavaScript or simplified web control extensions. While these implementations are good, I was looking for a control that would be capable of writing the JavaScript for me and providing good design-time support. In the end, what I needed was a control that was a little more robust and capable of handling multiple pre-determined and on-the-fly popups from a central location on the page. Also, the need to provide massive amounts of information via a conventional tool tip just wasn't possible. After doing some research on DHTML implementations, I came across the overLIB DHTML library and was impressed with the way that more information could be arranged in the JavaScript DHTML environment. The big limitation for this library was the fact that the developer had to write all of the commands by hand. Although there were sites out there that could write the appropriate code blocks for you, I still needed a control that had everything localized.
The purpose of this article is to discuss the capability of the wrapper control that I developed in order to accomplish the need for showing formatted information whether it be from a database, dataset, or other forms of information repository. The source code provides extensive comments on how these controls operate and what was needed to wrap the overLIB functionality. The two major controls are the OverlibPageControl
which resides on any particular web page and is a central repository for binding popup tool tips to all web controls, e.g., Label
s, CheckBox
es, etc., during design time, and the OverlibPopupAnchor
which is a simplified hyperlink for adding popup capabilities to a word or word groups on any particular web form. I will discuss how to create and modify the popup during design- and run-time. The goal of this article is to show how this control can save time during the design and testing when lots of information, if shown as is, on a web page will make the webpage unreadable or cause major headaches when switching to lower screen resolutions.
Background
One of my previous projects needed to have the ability to show through tool tips extra data concerning a particular keyword or web control. Because of this, my searches led me to Code Project and the popup capabilities of Tomas Petricek and others within the Code Project arena.
Yet what we needed, however, was what none of these items seemed to be able to do. What we really needed was a way to handle a lot of popups from a central location within a page and also define new ones dynamically. Thus the OverLibWrapper
C# namespace
was created. For a more complete definition of the overLIB commands, go to the overLIB documentation site. There are a lot of commands and the definitions are much better explained on the Bosrup and Boughner pages.
Using the code
First of all, you will need to add the OverLibWrapper.dll file to your Toolbox. I will not go into the details of installing it, because many who are using this control should be familiar with adding/removing visual and non-visual controls to their IDE toolboxes. The OverLibWrapper
namespace
contains visual controls: OverlibPageControl
, OverlibPopupAnchor
and ColorComboBox
. Never mind the ColorComboBox
, it is a control that was developed because of some UI requirements for the design-time development of an OverlibCommand
. For a quick run down, download the demo to test out the operations of the controls.
The two controls that are the most important are the OverlibPageControl
and OverlibPopupAnchor
. The OverlibPopupAnchor
wraps itself around the basic <a>
HTML control with some side benefits. For those developers that don't want or don't have a lot tool tips or even just want to play around similar to what is shown on Robert Boughner or Erik Bosrup's pages; you will want to use this item. The concept is just like adding a new hyperlink to your page, but you can also change some of the parameters to make it view whatever you wish. It contains all of the other designers there are for the OverlibPageControl
so if you don't want to put a page control for just one measly anchor, you don't have to.
In the screenshots at the beginning of the article, you can see what the OverlibPageControl
looks like during design-time. The following shows what is seen in the HTML view:
<asp:Label id="Label1" style="Z-INDEX: 101; LEFT: 56px;
POSITION: absolute; TOP: 112px" runat="server">Label</asp:Label>
<asp:CheckBox id="CheckBox1" style="Z-INDEX: 102; LEFT: 32px;
POSITION: absolute; TOP: 160px" runat="server" Text="CheckBoxName">
</asp:CheckBox>
<olwc:OverlibPageControl id="OverlibPageControl1" runat="server"
PageDefaults="STICKY,FGCOLOR,'#D2691E',CAPCOLOR,'#D4D0C8',WRAP">
<OverlibPopup ControlLink="Label1"
Text="This is the Tip Text shows when the control is clicked"
Commands="STICKY,CENTER,CAPTION,'Clicked caption'" EventType="OnClick" />
<OverlibPopup ControlLink="Label1"
Text="This shows when the user passes the mouse over"
Commands="STICKY,CENTER"
EventType="OnMouseOver" />
</olwc:OverlibPageControl>
The OverlibPageControl Designer
The OverlibPageControl
has two properties that enable it to function within a web form. They are PageDefaults
and Tips
.
The PageDefaults
property connects to a custom UITypeEditor
that allows the developer to build the appropriate commands that will be used for every call to the underlying overlib
function call. These are the same commands that would have been normally typed by hand to the overLIB JavaScript library.
The Tips
property opens a CollectionEditor
that allows for the designer to create, delete, and modify popups for particular controls that reside on the current page. One of the good things about this control is that it allows for the developer to link more than one popup to a particular control with different actions. There are only two event types currently, OnMouseOver
and OnClick
. These are the most commonly used events in web development. For this article, they will be the ones that are referenced most often. As illustrated in the image below, there are two popups that govern Label1
. When you mouse over Label1
, a popup will appear; when you click on Label1
, another popup will appear. Technically, the number of popups per control is only limited to the number of events that a particular control can handle.
Inside of the CollectionEditor
, the Commands
property opens up the OverlibCommandEditor
which is used to add commands that will be run on this particular popup. The Text
property opens a text editor, and it also allows for the direct input of what the text for the ToolTip will be.
Code
Not only can popups be built in the designer, but they can also be built during runtime. This allows for greater flexibility when dynamic popups are needed.
// We want to add another popup -- so we build one from scratch
OverLibWrapper.OverlibPopup pop = new OverLibWrapper.OverlibPopup();
pop.Text = "This is a color test";
//this is a little hex color utility that was built
//by http://www.tonesco.com
string colorStr =
HexColor.HexColorUtil.ColorToHex(System.Drawing.Color.Beige);
string colorStr2 =
HexColor.HexColorUtil.ColorToHex(System.Drawing.Color.IndianRed);
//add the commands that we want for this call to the overlib function
pop.AddCommand(OverLibWrapper.OverlibCommand.BackgroundColor,colorStr2);
pop.AddCommand(OverLibWrapper.OverlibCommand.ForegroundColor,colorStr);
pop.AddCommand(OverLibWrapper.OverlibCommand.Caption,"This is a color Test");
//add out control to link to -- this is the control.ID value
//Note: if the ControlLink property is not set.
///During the pre render of the control an exception will be issued
pop.ControlLink = "Label1";
//add out event type: the default is onmouseover
//Note: that if two or more controls have the same control
//link and have the same
//ControlEventType, the first event will be captured, but the second
// will be discarded even though it will remain within the code or
//within the design collection
pop.EventType =
OverLibWrapper.ControlEventType.OnClick;
OverlibPageControl1.Tips.Add(pop);
One of the other classes to use during run-time is the OverlibPopupTextBuilder
. This class provides the same functionality as the Text Editor, but allows for the developer to specify the exact layout of the information during run-time. It is useful if you want to create a table to organize the data to display in the tool tip.
OverLibWrapper.OverlibPopupAnchor anchor =
new OverLibWrapper.OverlibPopupAnchor();
OverLibWrapper.Design.OverlibPopupTextBuilder optb =
new OverLibWrapper.Design.OverlibPopupTextBuilder();
optb.AddTable();
optb.AddTableAttribute("border","1");
int rowIndex = optb.AddTableRow();
optb.AddRowCell(rowIndex,"this is some information in a cell");
optb.AddRowCell(rowIndex,"This is an cell with information");
anchor.Title = "Inner popup";
anchor.PopupText = "This is text inside the popup";
anchor.IsInnerPopupAnchor = true;
anchor.OverlibCommands =
"STICKY,CAPTION,'This is an inner popup caption',WRAP";
rowIndex = optb.AddTableRow();
optb.AddRowCell(rowIndex,"This is another cell");
optb.AddRowCell(rowIndex,anchor.HyperlinkString());
string popupInformation = optb.PopupText();
//popupInformation will read:
//<table border=\'1\'>
//<tr><td>this is some information in a cell </td>
//<td>This is an cell with
//information</td></tr><tr><td>
//This is another cell</td>
//<td><a href="javascript:void(0);"
//onmouseover=
// "overlib2('This is text inside the popup',STICKY,CAPTION,'This is an
// inner popup caption',WRAP)" onmouseout="nd()2;">Inner popup</a>
//</td></tr> </table>
//this is then added to another anchor or popup and the
//entire object is written to the rendered html
To understand more of the workings of the OverlibPopupTextBuilder
, download the source code and see what is going on under the hood.
OverlibPopupAnchor
The OverlibPopupAnchor
contains the same items that an OverlibPageControl
does, except that it is more compact in its representation to the developer. This control displays a text hyperlink that is already set up to display popups. One limitation to using the anchor is that it cannot have multiple event types added during design time.
OverlibCommand and OverlibCommandCollection
The OverlibCommand
and OverlibCommandCollection
are two of the classes that build the command structure for a call to the overlib
function. The OverlibCommand
contains the entire list of 100+ overLIB commands that comprise the core and official plug-in for the overLIB library. The OverlibCommandCollection
is a strongly typed collection that allows for the normal methods for a collection (i.e., Add
, Remove
, IndexOf
, etc). One of the more interesting methods of the OverlibCommandCollection
is the ToString()
method. When calling the ToString()
, the return value is a comma delimited string containing all of the commands that were inserted into the collection. This is the exact format that the overLIB JavaScript library expects the commands to be in. The OverlibCommandEditorDialog
contains an OverlibCommandCollection
that will parse the incoming string of commands and convert them into valid OverlibCommand
s for editing. It is best not to directly create an OverlibCommand
, but to use the OverlibPopup
to add particular commands with values to the popup.
OverlibPopup
This class is one of the other important items within the OverLibWrapper
namespace
. The OverlibPopup
class is parsed and generated by the OverlibPageControl
. The OverlibPopupCollection
contains the popups during design and rendering. When adding a new OverlibPopup
during design and runtime, it is imperative that the ControlLink
property is set to a WebControl that is currently on the design view of the web form. By setting the ControlLink
property, you are indicating that the particular popup is going to show for that particular WebControl. If the property is not set then exceptions will be thrown when execution of the web page happens.
Examples of each of the above mentioned command types are:
OverlibCommand.Sticky; //flag type command
OverlibCommand.Caption; //quoted text command
//a text command; this is required for those commands that
//are looking for objects on the page using JavaScript
OverlibCommand.Frame;
// a color command in the form of '#FFCCAA'
OverlibCommand.ForegroundColor;
The following is an example of creating a popup and adding the various commands with their associated values:
OverLIBWrapper.OverlibPopup pop = new OverLIBWrapper.OverlibPopup();
pop.Text ="A new popup";
//this is a plugin command (unofficial)
pop.AddCommand(OverLIBWrapper.OverlibCommand.Draggable);
//this is a core command
pop.AddCommand(OverLIBWrapper.OverlibCommand.Center);
//core command with a quoted text value the single quotes are
//optional because the logic behind the OverlibCommand is
//that it will automatically determine whether or
//the text has to be quoted. Another item is that it will automatically
//escape the single quotes that internal to the string value.
pop.AddCommand(OverLIBWrapper.OverlibCommand.Caption,"This is a test");
//if the controlLink is not set there will be exceptions thrown
//during pre-render of this control
pop.ControlLink = "Label1"; //this is equivalent to Lable1.ID
//this adds the command to the current page control's popup collection
OverlibPageControl1.Tips.Add(pop);
Points of Interest
A point of interest that you may find interesting is the problem with trying to find the particular controls on the page. Tomas (mentioned earlier) got me half way to point with his UITypeEditor
that finds controls via the current context instance. However, when you create a new instance of a CollectionEditor
and add a new object, there is a problem with finding the current service that gives you the reference that has all of the controls on the page. The following snippet can be used with some minor modifications to find anything on the page that you wish:
public override object EditValue(ITypeDescriptorContext context,
IServiceProvider provider,object value){
if (context!=null && context.Instance!=null && provider!=null) {
edSvc=(System.Windows.Forms.Design.IWindowsFormsEditorService)
provider.GetService(typeof(
System.Windows.Forms.Design.IWindowsFormsEditorService));
if (edSvc!=null) {
lb=new System.Windows.Forms.ListBox();
lb.BorderStyle=System.Windows.Forms.BorderStyle.None;
lb.SelectedIndexChanged+=
new EventHandler(lb_SelectedIndexChanged);
ArrayList items = new ArrayList();
System.Web.UI.Control parentControl = null;
// gets all controls from the form
//this grabs the service for all the references that the provider has
//this is key if you are calling this editor
//from inside another editor
//,i.e., a CollectionEditor
IReferenceService service =
(IReferenceService)provider.GetService(typeof(IReferenceService));
object[] references =
service.GetReferences(typeof(System.Web.UI.Control));
//grabs the parent control based on the references.
foreach(Control control in references){
if(control.GetType() == typeof(System.Web.UI.UserControl) ||
control.GetType() == typeof(System.Web.UI.Page)){
parentControl = control;
break;
}
}
if (parentControl == null) {
return "No controls found";
}
//recursively grabs all the controls
//within each control's Controls container
//otherwise the only level we will see
//is the Page level controls, i.e. those
//controls that put on the actual page.
//All other controls that are placed
//inside panels,
//or other containers will not be shown
//and thus if you wish to get a
//control that is two or three levels deep or if there is a
//master page context
//you will be out of luck.
//This is especially the case when wanting to create a UserControl.
//and adds them to the item list
foreach(Control ctrl in parentControl.Controls){
GetControls(ctrl, items);
}
items.Sort();
lb.Items.AddRange(items.ToArray());
edSvc.DropDownControl(lb);
if (lb.SelectedIndex==-1) return value;
return lb.SelectedItem;
}
}
return value;
}
Another item to note is that trying to incorporate an already valid piece of code without rewriting it for yourself can be a big problem. Since this was the case in using overLIB JavaScript files, the idea of compiling them as resources and then inserting the resource files into the calling web project was both a good idea and a challenge. Two other classes inside the OverLibWrapper
namespace
helped in the manipulation of the web.config file and inserting the appropriate folders and files into the current web project. These classes are generic enough to insert and manipulate just about any embedded resource that you want inserted into a particular web project. OverLibWrapper.Design.ProjectController
handles the file insertion from an embedded resource. OverLibWrapper.Design.AppConfig
works with and manipulates the configuration files. For those of you who are sticklers for comments, you can even insert a comment into the particular configuration file based on the key that you had just inserted.
During the OnPreRender()
of both the OverlibPageControl
and the OverlibPopupAnchor
, the requisite overLIB JavaScript elements are generated and written to the page. Both controls are smart enough that if there are problems with the overLIB script location, or with the text that is supposed to be displayed, nothing will be injected into the page so that there is no clutter when you are trying to troubleshoot other elements of your web form source.
Tips, Tricks, and Troubleshooting
OverlibPageControl
- Dragging and dropping more than one page control onto a web form will result in an exception. Don't worry. This is by design. Since the
OverlibPageControl
holds a collection ofOverlibPopup
s there is really no need to have more than one control per page. - The JavaScript files for the overLIB library are embedded into the .dll. This means that the user never needs to worry about the ultimate location of the JavaScript files. It is loaded into the current web project automatically.
- The action of dragging and dropping the control will automatically load into the web project the appropriate files and also insert into the web.config the appropriate JavaScript file location set to the root level.
<appSettings> <add key="overLIBLocation" value="/OverlibDemo/overLIBScripts" /> </appSettings>
- If you wish to get rid of the page control, do not delete the overLIBScripts folder or the
appSettings
key first. If this happens and then you delete the control, during its refresh and initialization cycle the location of the key and the actual physical folder will be checked. If neither item exists, it will restore the key and all of the files. Don't worry, this is done by design. Too many times in the past, when other component developers developed high-speed low-drag controls, there was lots of work on the down-level developer's part to ensure that external file folders existed during the development and deployment process. This is not the case with this control. It has everything it needs to survive on your page, short of a nuclear explosion. The key here is to delete the control on the page first, then delete the web.config key, and finally the directory that holds the overLIB JavaScript files. - One of the nice things about this control is that when you feel there is an update on the overLIB JavaScript's, you can just copy the files over to the local file folder, and barring any unforeseen function or keyword additions, the code will work as is.
- The goal of wrapping the overLIB library was to leave the JavaScript alone and just allow the control to do all the work. I think that has been accomplished.
- The
OverlibPageControl
's mission is to be designer friendly. It will tell you where it sees the appropriate files,<appSettings></appSettings>
key, and also the total number of popups that the control contains. - This control has a rich UI that allows for the developer to do most of the work during design-time.
OverlibPopupAnchor
- Dragging and dropping the control onto the web form will conduct the same actions as the
OverlibPageControl
. Like theOverlibPageControl
, adding this control to your page will insert the<appSettings>
reference and also put the overLIBScripts folder in your web project. - Note: The action of deleting the overLIBScripts directory or excluding it from the project or deleting the
overLIBLocation
from the<appSettings>
will not be automatically re-added with anOverlibPopupAnchor
. This is due to the fact that theOverlibPopupAnchor
only looks for theappSettings
key and file folder location during the creation of the control. - The
OverlibPopupAnchor
is really only designed for smaller implementations on a page, where there is predominately a lot of text present. For a more robust implementation where there are controls, anOverlibPageControl
would be more suited for development.
Thanks
My deepest thanks go to the Code Project authors that provided serious timesaving steps and helped me muddle through some of the more distressing parts of this implementation. Other thanks and nods go to Erik Bosrup and his helpers for coming up with a well received and highly used piece of JavaScript and allowing me to wrap their code. Thanks also goes to Rob Battle for hitting me in the head a few times to drive me in the right direction during some of the seemingly hard portions of this code.
Legal
All overLIB JavaScript code is copyright of Erik Bosrup and Robert Boughner.
All other code is copyright to their respective developers.
At no time during the development of this code was intentional infringement conducted.
History
2005-02-16 -- Initial writing of this article.