Introduction
Most serious software companies would never think of releasing a desktop application without a context sensitive help system. However, as companies are moving their applications to a web-based environment, many are neglecting the help system in their web versions. The idea is that the web is so easy to use, a help system is no longer required. But why would this be so? It is true that the scrolling capabilities of a web page in a browser provide more screen real-estate to explain concepts to users. For other web apps, "help" consists of little more than a site map. But, I think that as web applications become more complex and widespread, providing full-featured on-line help systems for web applications becomes more important. Also, the process of writing and implementing a context-sensitive help system for your web application provides the additional benefit of helping to find bugs and navigational inconsistencies.
RoboHelp WebHelp
One easy way to add a nicely functional help system to your web application is to use the WebHelp capabilities of Adobe RoboHelp. RoboHelp provides a single help authoring system, integrating Microsoft Word as the editor. From one help product, you can create WebHelp that can be accessed from a web server, as well as CHM help files, class Windows HLP files, and some other types.
While it may sound like this is going to be a promotional article for RoboHelp, that is far from the case. The length of this article alone should tell you that integrating WebHelp into your application is not straightforward. RoboHelp WebHelp has some significant bugs (although Adobe still has work to do to bring it up to CS3 standards). But the real challenge is finding an efficient and reliable way to integrate context-sensitive help into your web application, ensuring that each page in your web application displays the correct help topic.
In this article, we will focus on several different ways to implement context-sensitive WebHelp from RoboHelp 7:
- Display WebHelp in popup windows.
- Display WebHelp in a new browser window.
- An easy and effective way of creating context-sensitive help links dynamically from the code-behind.
I will also discuss some issues relating to upgrading to RoboHelp 7.
The project includes an ASP.NET example with source code, for Visual Studio 2005 in C#.
Display WebHelp as Popup Windows with the Navigation Pane
Most of the RoboHelp documentation I could find on WebHelp addresses displaying help topics in popup windows.
You use JavaScript links to display help in a popup window showing the navigation pane (see screenshot). The JavaScript function RH_ShowHelp
is provided with RoboHelp in the file RoboHelp_CSH.js. Be sure to link this JavaScript file to any page that will be displaying help popups.
Here is the function declaration for RH_ShowHelp
(from the RoboHelp_CSH.js file):
// Syntax:
// function RH_ShowHelp(hParent, a_pszHelpFile, uCommand, dwData)
//
// hParent
// Reserved - Use 0
//
// pszHelpFile
// WebHelp:
// Path to help system start page
// ("http://www.myurl.com/help/help.htm" or "/help/help.htm")
// For custom windows (defined in Help project),
// add ">" followed by the window name
// ("/help/help.htm>mywin")
//
// WebHelp Enterprise:
// Path to RoboEngine server ("http://RoboEngine/roboapi.asp")
// If automatic merging is turned off in RoboEngine Configuration Manager,
// specify the project name in the URL
// ("http://RoboEngine/roboapi.asp?project=myproject")
// For custom windows (defined in Help project), add ">"
// followed by the window name ("http://RoboEngine/roboapi.asp>mywindow")
//
// uCommand
// Command to display help. One of the following:
// HH_HELP_CONTEXT // Displays the topic associated
// with the Map ID sent in dwData
// if 0, then default topic is displayed.
// The following display the default topic and the Search, Index, or TOC pane.
// Note: The pane displayed in WebHelp Enterprise
// will always be the window's default pane.
// HH_DISPLAY_SEARCH
// HH_DISPLAY_INDEX
// HH_DISPLAY_TOC
//
// dwData
// Map ID associated with the topic to open (if using HH_HELP_CONTEXT), otherwise 0
//
Use the HH_HELP
constants to control which tab on the navigation pane to show by default - either Contents, Index, or Search.
Display Contents Tab by Default
<A HREF='javascript:RH_ShowHelp(0, "WebHelp/Webhelp_Demo.htm",
HH_HELP_CONTEXT, 0)'>Your Link Text Here</a>
Display Search Tab by Default
<A HREF='javascript:RH_ShowHelp(0, "WebHelp/Webhelp_Demo.htm",
HH_DISPLAY_SEARCH, 0)'>Your Link Text Here</a>
Display Index Tab by Default
<A HREF='javascript:RH_ShowHelp(0, "WebHelp/Webhelp_Demo.htm",
HH_DISPLAY_INDEX, 0)'>Your Link Text Here</a>
The JavaScript results in the following cropped popup (Search tab by default):
Note that the WebHelp pages are skinnable. You have several choices of skins provided by Adobe, and you could probably create your own by modifying the graphics and CSS.
Home File Name
Note that these links all start at the file WebHelp/Webhelp_Demo.htm. In this case, Webhelp_Demo was derived from the name of my help project, and I placed it in the WebHelp subdirectory. Your home file name will be different.
Display Context-Senstive Help from Popups
Up to this point, we have notspecified a topic number for the last parameter in the function call. When we do this, our popup goes directly to the specified topic; however, we lose the navigation pane as shown in this screenshot:
Losing the navigation pane may or may not be desirable. I could not get the JavaScript to work to specify a topic number and also show the navigation pane.
Problems with Popups
I opened with a discussion of popups because most web references I have seen for RH WebHelp discuss how to implement the help system as a popup. This was apparently the way the WebHelp creators expected users to display their help systems. Years ago, when WebHelp was first developed, this may have made sense. That was before the whole world was annoyed by popup ads. However, I strongly recommend you avoid using popups if at all possible. RH WebHelp popups have two critical bugs:
- In IE6, clicking the Back button after displaying a popup causes the popup to reappear - a highly undesirable navigation effect. I never tested in IE7.
- As discussed, you cannot specify a context sensitive help topic and also display the navigation pane. When you specify a context sensitive help topic, the navigation pane is suppressed. Without the navigation pane, users must rely on links on your help pages to navigate to other help topics.
Furthermore, there are enough web users disabling popups that they should be avoided in any serious web application.
Displaying Context Sensitive WebHelp in a New Browser Window
Because of the problems with popups, I think it is best to display the help topic in a new browser window. Here is the HTML syntax to display CSH in a new browser window:
<a href="WebHelp/Webhelp_Demo.htm#Topic1.htm" target="_new" >Your Link Text Here</a>
WebHelp/Webhelp_Demo.htm is the subfolder and page name for the home page for your web help project. This will be different for your application. It will be the same for every help link you use.
#Topic1.htm is the name of the page that contains the help topic you want to display (prefixed with #).
WebHelp displayed in a full browser window.
Creating Context-Sensitive Help Links Dynamically
The real challenge in implementing context sensitive WebHelp for a web application is the bookkeeping required for your application pages and help pages to make sure that the right help topic is displayed for each application page. You could type in the full link to the Help in all of your aspx files. However, that would be tedious and prone to errors. As a programmer, I prefer to make the computer do tedious work for me. The better way is to create links dynamically in your page's code-behind. Here is the technique I chose for my application.
BasePage Class
I start by creating a BasePage
class. BasePage
is derived from System.Web.UI.Page
. All pages in my application will be derived from BasePage
rather than System.Web.UI.Page
. (By the way, there are many reasons why this is a good idea for all of your web applications even if you are not implementing WebHelp - but that is another article.)
Here is the code for my BasePage
class:
public class BasePage : System.Web.UI.Page
{
public const int Unspecified = 0;
public const int Topic1 = 1;
public const int Topic2 = 2;
public const int Topic3 = 3;
public int m_nPageID = 0;
public BasePage()
{
m_nPageID = 0;
}
}
Note that I define a constant for each help topic page. In this trivial example, I only have three help topics. A real application could have hundreds. The BasePage
has a member m_nPageID
which identifies which of the help topic IDs belong to that page. Note that these are my own help topic IDs. They are not the ones automatically generated by RoboHelp. I do not use the RoboHelp IDs at all in this implementation.
This code snippet shows how, for each page in my application, I derive the page from BasePage
. In the Page_Load
function, I specify the value for the m_nPageID
value to indicate which topic to display for this page.
public partial class DynamicHelpLink : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
this.m_nPageID = BasePage.Topic2;
}
}
A Note on the Page Life Cycle
Make sure that the Page_Load
function occurs before you create your help link, or else you will not display the correct help topic. Ideally, you would assign the m_nPageID
value in the class constructor. But because Visual Studio creates a Page_Load
function by default, this saves me from having to add a constructor to each page in my application. Over hundreds of pages, that saves a lot of typing.
The HelpMap Class
In the project, I include a HelpMap.cs file with the HelpMap
class. The GetHelpFileName
function maps the BasePage
help ID number to a file name in my help system, as shown below. The GetHelpLink
function generates a string that is the hyperlink to the help file.
static public string GetHelpLink(BasePage bp, string strCaption)
{
string strHelpPage = GetHelpFileName(bp.m_nPageID);
string strTarget = " target=\"_blank\" ";
return "<a href=\"" + bp.ResolveUrl("~/WebHelp/WebHelp_Demo.htm") +
"#" + strHelpPage + "\" " + strTarget +
">" + strCaption + "</a>";
}
static protected string GetHelpFileName(int nPageID)
{
switch (nPageID)
{
case BasePage.Topic1: return "Topic1.htm";
case BasePage.Topic2: return "Topic_2.htm";
case BasePage.Topic3: return "Topic_3.htm";
}
return "Welcome";
}
Specifying the Correct Subdirectory for Your Help Pages
Here is another challenge to consider. If you decide to create a hierarchical table of contents for your help system, WebHelp will place your help pages in different directories based on the position in the TOC hierarchy. Make sure you provide the proper subdirectory location along with each help file name.
Adding a Help Link to Your Page Dynamically from Code-Behind
Here is how to add the help link to your page dynamically from the code-behind. In this example, assume you have a placeholder control on your web page called LocalPlaceHolder
. This control will hold the help link. Here is how to add a help link to the placeholder:
- Create a
Literal
control.
- Set the text for the
Literal
to the help link from the HelpMap
class.
- Add the
Literal
to the PlaceHolder
.
Literal lit = new Literal();
lit.Text = HelpMap.GetHelpLink(this, "Click Here for Help");
LocalPlaceHolder.Controls.Add(lit);
RoboHelp Browser Issues
WebHelp, as produced by RoboHelp, has a number of bugs beyond the scope of this article. For me, one of the most annoying is an apparently missing closing tag which causes the page to never stop loading in FireFox. This link has a good list of bugs and solutions:
Issues with RoboHelp Upgrades
RoboHelp is one of those unloved foster children that is passed from parent to parent, with each giving it less love. The application was created by Blue Sky Software in the early 1990s. It was a high-quality product, and became the industry standard help authoring tool. Blue Sky marketing wizards changed the company name to eHelp as part of the eEverything craze of the dot-com days. RoboHelp was then acquired by Macromedia, which was acquired by Adobe, which resulted in persistent rumors that the one-time industry standard help authoring product would be left to die on the vine.
If you are planning on upgrading to the latest version, don't expect installation to go smoothly. RoboHelp uses a lot of Microsoft Word templates (i.e., .dot files). Older template files are not compatible with newer versions of RoboHelp, so Adobe recommends uninstalling your old copy of RoboHelp before installing the new (see article here). That means that you will lose any customization you have made to the styles in the template. But worse, the upgrade checks your system for an existing copy of RoboHelp to validate upgrade eligibility. So, new RoboHelp doesn't work with old RoboHelp installed, but new RoboHelp won't install unless old RoboHelp is present! In fairness, they do give you one out. You can enter a valid serial number of RH6 or RHX5 during installation.
But what if you have an earlier version?
I had an old copy of RoboHelp 2000. When I tried to upgrade to Abode RoboHelp 7 to take advantage of the WebHelp features, the new version wouldn't accept my old RoboHelp serial number as valid for an upgrade. This resulted in an hour long (no joke) support call to Adobe, where I spoke to eight (no joke) different people. Each new support person had to ask for my customer ID number, RH7 serial number, and RH2000 serial number. Their final resolution was to give me a valid RH5 serial number. Adobe is not kidding when they say new versions do not work with old ones installed. When I finally got the upgrade installed, it didn't work on my system. I ended up installing it on another computer and using it only for the final build, while I still do my help authoring in RH2000.
The Project
The accompanying project is a Visual Studio 2005 ASP.NET web project that shows how to integrate WebHelp with your application. It shows how to use the HelpMap
class and how to generate help links dynamically on a page or in a UserControl.
Conclusions
Adobe RoboHelp is a popular and easy-to-use tool to create help projects in a variety of formats, using Microsoft Word as the authoring tool. One of those formats is WebHelp - help files that can be displayed in a web browser. Adobe WebHelp has a nice user interface, and provides a choice of skins by default. However, there are some issues to look out for when implementing WebHelp as context-sensitive help.
- Most RoboHelp documentation discusses displaying WebHelp in popup windows from JavaScript commands. However, popups are a problem. I could not get the popup to display the navigation pane when providing context-sensitive numbers. The popup window breaks the "back" button in IE6. Finally, many users disable popups.
- The better way to display WebHelp topics is in a new browser window. The challenge is to find the most reliable and efficient way to display the proper help page from each page in your web application. This article provides a solution.