56
MASARYK UNIVERSITY Faculty of Informatics BACHELOR’S THESIS Context Help for Kentico CMS Brno 2011 Petr Pěnička

Context Help for Kentico CMS - Muni - Masaryk University

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

MASARYK UNIVERSITY

Faculty of Informatics

BACHELOR’S THESIS

Context Help for

Kentico CMS

Brno 2011 Petr Pěnička

- ii -

Statement I declare that this thesis is my original copyrighted work, which I developed alone. All

resources, sources, and literature, which I used in preparing or I drew on them, I quote in the

thesis properly with stating the full reference to the source.

- iii -

Acknowledgements I would like to express sincere thanks to RNDr. Karel Kisza for his supervision and valuable

advice. I also want to thank Ing. Martin Hejtmanek, the CTO at Kentico Software, for his

consultations and in-depth information on Kentico CMS internals.

- iv -

Resume The aim of this thesis was to create a module which would enhance the current context-related

documentation (i.e. context help) possibilities of Kentico CMS, the ASP.NET web content

management system. The module’s implementation was carried out to comply with module

requirements received from Kentico Software, the company producing the system.

The module should provide website developers using the system with a way how they can

display help related to terms in website text or HTML elements in its code, both on the live

site and in the system’s user interface. On top of this functionality, it should also provide a

way how to customize default context help natively included in the system’s user interface.

Output of the thesis should be an export package containing the module’s definition and

related files. It should be possible to add it into any Kentico CMS 5.0 instance using the native

export/import functionality of the system.

Key words WWW, HTML, ASP.NET, C#, XML, Kentico CMS, documentation, help, term, HTML

element, module development

- 1 -

Contents

1 INTRODUCTION ....................................................................................................... 3

2 CONTENT MANAGEMENT SYSTEM .................................................................. 5

3 KENTICO CMS .......................................................................................................... 6

3.1. SYSTEM REQUIREMENTS ................................................................................... 6 3.2. KENTICO CMS FEATURES ................................................................................. 6

3.3. ADMINISTRATION INTERFACE ........................................................................... 7 3.3.1. CMS Desk ................................................................................................ 7

3.3.2. CMS Site Manager ................................................................................... 8 3.3.3. Default Context Help Functionality ....................................................... 10

4 ANALYSIS AND DESIGN ...................................................................................... 12

4.1. MODULE REQUIREMENTS................................................................................ 12

4.2. ANALYSIS OF REQUIRED FUNCTIONALITY ...................................................... 12

5 IMPLEMENTATION .............................................................................................. 15

5.1. DATABASE STRUCTURE .................................................................................. 15 5.2. PARSING ALGORITHMS ................................................................................... 15

5.2.1. What Data Should Be Parsed ................................................................. 16 5.2.2. Connection to the OutputFilter .............................................................. 16 5.2.3. Terms Highlighting ................................................................................ 18

5.2.4. HTML Elements Help ............................................................................ 22 5.2.5. ResolveHelpUrl Method ........................................................................ 24

5.3. CUSTOM CONTEXT HELP TOPICS .................................................................... 26 5.4. CUSTOMHELP.ASPX PAGE ............................................................................... 27 5.5. USER INTERFACE OF THE MODULE .................................................................. 29 5.5.1. User Interface Pages Nesting ................................................................. 31

5.5.2. The Terms, Elements and Custom Topics Tabs .................................... 32

6 FURTHER IMPROVEMENT POSSIBILITIES ................................................... 35

7 CONCLUSION ......................................................................................................... 36

LITERATURE ............................................................................................................. 37

ANNEXES .................................................................................................................... 39

A. MODULE REQUIREMENTS FROM KENTICO SOFTWARE ..................................... 39 A.1 Purpose ................................................................................................... 39

A.2 Description ............................................................................................. 39 A.3 Use Cases ............................................................................................... 39 A.4 User Interface ......................................................................................... 40 A.5 Interactions with Other Modules ........................................................... 40 A.6 Security Requirements ........................................................................... 40

A.7 Performance Requirements .................................................................... 41

- 2 -

B. DESCRIPTIONS OF DATA RECORDS STORED BY THE MODULE ........................... 41 B.1 dbo.customtable_ContextHelpTerms ..................................................... 41 B.2 dbo.customtable_ContextHelpElements ................................................ 42 B.3 dbo.customtable_ContextHelpTopics .................................................... 43 C. CODE EXTRACTS ............................................................................................. 44

C.1 Connection of the Module’s Methods to the OutputFilter ..................... 44 C.2 The AddTermsHelp Method .................................................................. 45 C.3 The AddTermTooltip Method ................................................................ 46 C.4 The AddElementsHelp Method ............................................................. 47 C.5 The ResolveHelpUrl Method ................................................................. 48

C.6 The ResolveCustomTopic Method ........................................................ 50 C.7 The CustomHelp.aspx Page ................................................................... 50

C.8 The PageLoad Method from the CustomHelp.aspx.cs File ................... 51 D. INSTALLATION INSTRUCTIONS ........................................................................ 52 E. ATTACHED CD MEDIUM ................................................................................. 52

- 3 -

Chapter 1

Introduction

With growing complexity of today’s software products, the need for high quality

documentation is being both expressed by software users and understood by software

development companies. Accessibility of documentation while using a software product is of

the highest importance, as users do not want to spend hours browsing through various

manuals and reference guides, looking for a piece of information which is needed for their

particular purpose and situation. This is where the idea of context help comes in handy.

Context help can be understood as documentation accessible directly from an

application’s user interface, relevant for the particular part of the user interface where a user is

currently intending to perform an action. The biggest advantage of this kind of documentation

is that the user gets just the information related to his current activity. This results in him not

being overwhelmed by tons of extensive texts to read through, which greatly decreases the

time needed for him to find the required information.

The same applies to today’s websites. Modern dynamic web applications are, in terms of

complexity of their user interface and provided functionality, fully comparable to traditional

installed desktop applications. They are capable of providing advanced functionality, whose

utilizing requires hands-on experience or previous study. Here again arises the need to provide

users with the right information and advice on how to use the current part of the web

application’s user interface.

Ultimately, website content itself can also get quite complex in many situations, typically

on websites focusing on a specialized topic. It can be virtually any field of interest – websites

about computer hardware, gardening, car modifications, fishing, politics, etc. can all have

content which may not be understandable to a novice or non-specialist site visitor. Such

websites often have a terminology section where terms often used in website content are

explained. However, visitors of these websites have to open the terminology section in a new

browser window or browse to it and back whenever they do not understand some term in

website text. This is obviously not very convenient and may even discourage users from

visiting the website in the future. Context help in form of the terms highlighting functionality

is an elegant solution for these situations.

For me as a documentation author at Kentico Software, writing context help articles is an

integral part of my everyday work. When the opportunity came to develop a module shifting

the current context help possibilities of Kentico CMS to a next level, I evaluated it as a great

opportunity to get valuable practical experience in software development, mainly in the field

of programming, which is not among my day-to-day professional duties. On the other hand,

the purpose of the module is directly related to my field of activity in the company –

- 4 -

documentation authoring. The combination of these two factors led me to the decision to

design and develop the module as my bachelor’s thesis.

- 5 -

Chapter 2

Content Management System A content management system (the CMS abbreviation is commonly used for this type of

software and will be used further in the text of this thesis) is a piece of software which enables

even users with limited technical skills and knowledge to create and manage web content, i.e.

content of a website. In the broader meaning of the word, a CMS can be conceived as a

development framework upon which a website can be built. These systems’ popularity is

rising steeply these days. It happens mainly thanks to the fact that the Internet has become an

inseparable part of how business is done. Even the smallest companies can benefit from

having a web presentation or an e-shop, while not having one means a substantial

disadvantage in the competition fight.

Without a content management system, unskilled business users would need a specialist

whenever they wanted to change the content of their website. Programming knowledge,

software tools and knowledge of website structure would be required from the specialist,

resulting in additional costs of any required content change. Contrary to this, when a CMS is

used, even complex content changes can be performed with little effort by the business users

themselves, whilst near-zero programming knowledge is required. On top of it, even no

special software tools are required to perform the content changes – the content can be

managed conveniently from a browser-based user interface. Another advantage of the

browser-based user interface is that it can be accessed from anywhere – it is a part of the

actual website, accessible under a special URL, hence the only necessary prerequisite is a

compatible web browser.

- 6 -

Chapter 3

Kentico CMS Kentico CMS is a web content management system produced by a software vendor named

Kentico Software. The company is based in Brno, Czech Republic. The full name of the

system is Kentico CMS for ASP.NET, which indicates that the system is based on Microsoft’s

ASP.NET platform. Its entire code is written in the C# programming language. Data storage is

provided by a Microsoft SQL Server database.

According to information published on Kentico Software’s website [1], the CMS is

currently used by approximately 4000 websites in more than 60 countries around the globe.

The latest released version of the system at the time when work on this thesis started was

Kentico CMS 5.0. The Context Help module developed as the output of this thesis is designed

for and tested on this particular version.

3.1. System Requirements

On the server side, Kentico CMS is compatible with all versions of Microsoft Windows as of

Windows XP, i.e. Windows XP, Windows 2003, Windows 2008, Windows 2008 R2, Windows

Vista and Windows 7. As for data storage, it requires Microsoft SQL Server 2005 or Microsoft

SQL Server 2008.

The CMS is designed for the front-end website to be compatible with most of today’s

web browsers, while the user interface is only tested and officially supported under Microsoft

Internet Explorer 7, Microsoft Internet Explorer 8, Mozilla Firefox 3.5 and Apple Safari 4.0.

Code of the web application can be edited in Microsoft Visual Studio or the free

Microsoft Visual Web Developer, both as of version 2005.

Detailed system requirements can be found in Kentico CMS for ASP.NET (on-line):

System requirements [2].

3.2. Kentico CMS Features

Kentico CMS is a feature-rich solution. It provides most of the functionality required by

today’s modern dynamic websites in a single package, giving web developers a powerful tool

for creation of such websites.

The following list is not meant to provide a complete overview of the system’s features. It

only points out the most important and useful ones.

Browser-based user interface for website development, management and content editing.

Unlimited number of separate websites running in a single instance on the web server.

WYSIWYG editor for editing of page content in Microsoft Word-like manner.

- 7 -

Support for multiple language versions of particular websites, as well as full localizability

of the user interface.

Workflow and Versioning features for team content editing, where an approval process for

documents to be published on the website can be defined. It also enables rollbacks to

previous versions of documents.

Full source code available.

Free edition with limited features, sufficient for personal or non-commercial websites.

E-commerce module for creation of on-line stores.

Media libraries module for storage of large numbers of media files and their presentation

on the website.

Extensive documentation, including context help natively integrated into the system’s user

interface.

A complete overview of Kentico CMS features can be found in Kentico CMS for ASP.NET

(on-line): Features [3].

3.3. Administration Interface

The administration interface of Kentico CMS is accessible directly from a web browser. It is a

part of the actual website, accessible under a special URL. The administration interface is

divided into two main sections – CMS Desk and CMS Site Manager. In brief, CMS Desk is

used for creation and administration of one particular website’s content, while CMS Site

Manager is the interface where settings of particular websites running in the instance of the

CMS can be managed and where development- and administration-related tasks can be

performed.

3.3.1. CMS Desk

As mentioned above, CMS Desk is the part of the administration interface where content of

one particular website running in the system can be created and managed. It is accessible from

a URL in the following format: <website URL>/cmsdesk. The interface is divided into four

main tabs.

The first one – Content – is where content of the website can be created and managed. It

is depicted by Figure 1 below. The tree on the left of this tab is called the content tree and it

represents the site map, i.e. particular pages of the website. Site navigation controls are

rendered to reflect the documents in the content tree. By clicking a page in the tree, its content

gets displayed in the main area. Based on selection in the ribbon toolbar above the main area,

you can display the page for editing (the Edit option), display a preview of how the page will

look like after publishing (the Preview option), view the page’s current appearance on the

front-end website (the Live site option), or view a listing of all pages stored under the current

page in the content tree. In the Edit mode, users can make actual changes to content, design

and properties of the pages.

- 8 -

The second tab is called My desk and it provides content editors with easy access to their

agenda, i.e. document management, workflow-related actions, user profile management,

communication with other users of the system, etc.

The Tools tab contains administration interface of native built-in modules like E-

commerce, Media libraries, Newsletters, Web analytics, etc. This is where the administration

interface of the Context Help module will be located (see 5.5 for more details).

The last tab of CMS Desk is the Administration tab. This is where content editors can

administer user accounts, user roles, access permissions for particular sections of the user

interface, etc. This tab is also present in CMS Site Manager, where some extra options are

offered together with the ones present in CMS Desk. This duplicity is caused by the need to

allow limited administration to the content editors in CMS Desk, while advanced

administration possibilities are offered only to system administrators in CMS Site Manager.

Figure 1 - The Content tab of CMS Desk viewed in a web browser.

3.3.2. CMS Site Manager

CMS Site Manager serves for managing websites running in the CMS and for adjusting global

settings applied to all sites in the system. It is accessible under a URL in the following format:

<website URL>/cmssitemanager. Similarly to CMS Desk, CMS Site Manager is also divided

into tabs that encapsulate related functionality.

- 9 -

On the Sites tab, you can see all websites running in the system. You can run or stop the

sites from here, as well as import new websites or objects and edit basic website settings. This

is the part of the user interface where the Context Help module can be imported into any

Kentico CMS 5.0 instance from the package included on the attached CD medium.

Figure 2 - List of websites on the Sites tab in CMS Site Manager.

The Administration tab contains the same sections as the Administration tab in CMS Desk,

while some additional sections like system monitoring or web farm synchronization settings

are added. In brief, the added sections are those which are intended only for experienced

system administrators and therefore are not available to content editors in CMS Desk.

The next tab is the Settings tab, which serves for management of global- or website-level

settings.

The Development tab allows management of document types, CSS style sheets, web

parts, widgets, etc. The Context Help module will be registered in the Modules subsection of

this tab (as explained in Kentico CMS 5.0 Developer’s Guide (on-line): Developing custom

modules [4]).

The Licenses tab is used for entering licenses for particular domains, while the Support

tab lists links to Kentico CMS documentation and the technical support department.

- 10 -

3.3.3. Default Context Help Functionality

Kentico CMS is a fully documented solution. Complete documentation of the system can be

viewed or downloaded in various formats at Kentico DevNet (on-line): Documentation [5].

The full documentation consists of numerous separate guides, each of them aimed at a

different target audience or intended for different purposes. Among others, we can name

Kentico CMS Developer’s Guide, Kentico CMS E-commerce Guide, Kentico CMS API

Reference, etc.

On the top of these guides, the user interface of the system contains native context help

accessible via the green question mark icon in the top right corner of each user interface page.

Clicking the icon results in brief documentation of the current administration interface being

opened in a new browser window.

Figure 3 - Context help icon in Kentico CMS user interface.

Default Kentico CMS context help is a set of web pages with their own navigation, nested

inside the Kentico CMS web project. It is created with and rendered by a software tool called

EC Software Help & Manual. In the website root, it is stored in HTML format inside the

~/CMSHelp folder (the tilde (~) character prefix notation indicates location of the web

project’s root folder and will be used further in the text of this thesis).

The context help icons link to URLs in the following format: <website

URL>/CMSHelp/<topicname>.htm. The <topicname> part of the URL is unique for each

user interface page. When the icon is clicked and the URL accessed, the context help gets

opened in a new browser window, with the appropriate page selected in the navigation and

displayed in the main area. In Figure 4, you can see the context help page displayed after

clicking the icon on the List tab in CMS Desk -> Content.

- 11 -

Figure 4 - Default Kentico CMS context help.

- 12 -

Chapter 4

Analysis and Design

4.1. Module Requirements

This thesis is a response to module requirements received from Kentico Software’s

development department. These requirements are a standard internal document which is

created in the beginning of the development process of each internally developed module or

set of features. The document is attached with this thesis as A - Module Requirements from

Kentico Software.

4.2. Analysis of Required Functionality

Based on these requirements, the module’s functionality was divided into three main groups:

Terms highlighting – this functionality should provide content editors with a tool to

create a terminology database. Each defined term should have a short description

displayed in a tooltip when it is found in website text. In the tooltip, there should be a link

leading to a more extensive description of the term, displayed on a separate page.

HTML elements help – similarly to terms highlighting, this functionality should provide

a tool to display an icon with help tooltip next to HTML elements with certain IDs

detected in output HTML code.

Custom context help topics – as described in 3.3.3, Kentico CMS natively contains

context help topics (articles) for each page of its user interface. These topics are a part of

the standard installation and cannot be modified by default. The third goal in development

of this module was to enable replacing of these default topics with custom topics defined

via the module’s user interface.

Kentico CMS is a standard ASP.NET application. All pages of both the front-end website and

the user interface are standard ASPX web pages dynamically generated on the server side.

Analysis of the module requirements showed that the module will have to parse output HTML

code of each page generated by the system and add additional HTML tags where the defined

terms or HTML elements are found. For this purpose, it will be necessary to create static

methods that would perform parsing of the HTML code and adding of the HTML elements

with defined help. These methods should be stored in a separate static class.

This will have to be carried out at the end of each page’s life cycle, before the final

output HTML code is sent to the browser. According to Kentico DevNet (on-line): DIY: How

to apply custom output filter [6], a modification of the OutputFilter module, which natively

processes the output HTML code at this specific point of each page’s life cycle, will be

- 13 -

carried out to ensure execution of the parsing methods after the OutputFilter finishes its native

modifications of the output code. We will have to modify the code further before it is sent to

the client browser.

The custom context help topics functionality will be provided by a modification to the

~/CMSAdminControls/UI/Help.ascx control, described in 3.3.3 and depicted in Figure 3. The

modification will have to ensure that the help icons’ target link will be set dynamically as a

URL returned by a custom static method. The method should return URL of the default

context help topic if no custom topic is defined for the current page, or a URL of a page where

a custom topic will be displayed in case that the current page has such topic defined. The

custom topics should be displayed on a dedicate page included with this module, as referred to

further below.

Based on analysis of the module requirements, the following UML 2.0 Activity diagrams

were created:

Figure 6 - UML 2.0 Activity diagram showing the connection of the module's methods

within each page request.

Figure 7 - UML 2.0 Activity diagram illustrating the flow of the AddTermsHelp method.

Figure 8 - UML 2.0 Activity diagram illustrating the flow of the AddTermTooltip method.

Figure 9 - UML 2.0 Activity diagram illustrating the flow of the AddElementsHelp

method.

Figure 10 - UML 2.0 Activity diagram illustrating the flow of the ResolveHelpUrl

method.

Figure 11 - UML 2.0 Activity diagram illustrating the flow of the ResolveCustomTopic

method.

For better clarity, these diagrams are located with each method’s description in Chapter 5 -

Implementation.

To provide data storage, it will be necessary to create three database tables, while defined

help for each of the three required sets of functionality will be stored in each of them. To

achieve inclusion of the tables in the final export package, the Custom tables module, natively

shipped with Kentico CMS, will be used. This module allows easy creation of custom

database tables in the system’s database and provides a useful API for querying of these

database tables dynamically from module code, without the need to write or generate custom

SQL queries. The tables will be independent, each serving only for the purpose of one of the

three functionalities. Each record will be identifiable using an integer primary key.

The ERD diagram below illustrates these three database tables, the columns in them and

the primary keys used to identify the data records. Descriptions of particular columns of these

tables and the data stored in them are attached in B - Descriptions of Data Records Stored by

the Module.

- 14 -

Figure 5 - ERD model of data stored by the module.

To enable users define help for terms, HTML elements and custom context help topics, a user

interface will also have to be created for the module. This user interface should be embedded

within the native user interface of Kentico CMS. As the most of the native modules included

in Kentico CMS have their user interface located in the Tools section of CMS Desk, user

interface of our module should also be added to this section. The module’s user interface

should be further divided into three tabs, while each tab will be dedicated to one of the three

required functionalities. On each of the tabs, it should be possible to view a list of defined

terms, HTML elements or custom context help topics, edit the listed ones or define new ones.

The last part of the module will be another user interface page. Even though it should

have a uniform look as all other user interface pages, this one will not be accessible through

any menu in the user interface. Contrary to that, it will only be linked from the modified code

in output pages and it will ensure displaying of detailed descriptions of terms and HTML

elements, as well as displaying of custom context help topics.

- 15 -

Chapter 5

Implementation

5.1. Database Structure

The first step in development of the module was to define database tables where module data

will be stored. I utilized the Custom tables module, which is a built-in module in Kentico

CMS. Its documentation can be found in Kentico CMS 5.0 Developer’s Guide (on-line):

Custom tables [7]. It provides website developers with the possibility to create and manage

database tables from within the system’s user interface, without the need to use Microsoft SQL

Server Management Stuido or write and execute any SQL queries. Furthermore, the Custom

tables module comes with a useful API for access and modification of data stored in the

tables.

Apart from these possibilities, custom tables are standard SQL database tables stored in

the system’s database. Among other tables in the database, they can be recognized by the

dbo.customtable_ prefix.

Based on expected functionality expressed in modules requirements (see A - Module

Requirements from Kentico Software), I created the following three custom tables:

dbo.customtable_ContextHelpTerms for storing terms data records.

dbo.customtable_ContextHelpElements for storing HTML elements data records.

dbo.customtable_ContextHelpTopics for storing custom context help topics data records.

These database tables reflect the ERD model presented in Figure 5 above. For detailed

descriptions of particular columns and the values stored in them, please refer to B -

Descriptions of Data Records Stored by the Module.

5.2. Parsing Algorithms

With the data structure defined, the next logical step was to proceed to development of the

actual methods that would parse output HTML code and search for terms and element IDs

whose help should be displayed.

As these methods were all meant to be static, I created the ContextHelpHelper.cs class,

which is a static class where all static methods of the module are stored. The namespace of the

class is CMS.ContextHelp.

The class is stored under the ~/AppCode/Global/ContextHelp folder. This location,

according to Kentico CMS 5.0 Developer’s Guide (on-line): Folder structure and

import/export [8], enables export of the folder’s content into a package using Kentico CMS

- 16 -

native export/import functionality. It will be facilitated later when creating the export package

containing the module.

5.2.1. What Data Should Be Parsed

Based on A - Module Requirements from Kentico Software, the parsing algorithms needed to

be applied to the final output code of each HTML page rendered by the system, both in the

system’s user interface and on the live site. For this purpose, I decided to utilize the

OutputFilter module. As described in Kentico DevNet (on-line): DIY: How to apply custom

output filter [6], the OutputFilter module is a standard ASP.NET HTTP module and it is a

native part of the system. Its original and main purpose is to perform additional modifications

to the final output code rendered by the system, such as adding missing closing tags, ensuring

validity based on various standards (e.g. XHTML), etc.

On top of the basic functionality, it contains a number of pre-defined events. These events

can be used as customization connection points in cases when customers need to apply some

specific custom filtering to the output code. This was exactly our situation, so from all the

available events, I chose the OnAfterFiltering event. This event is raised when the default

filtering performed by the OutputFilter finishes. This is when the output HTML code is

processed, stored in the finalHtml variable and ready to be sent to the browser for rendering.

In order to ensure the required functionality, we will further process this code by our custom

methods implemented in the ContextHelpHelper class.

5.2.2. Connection to the OutputFilter

As explained in Kentico DevNet (on-line): How to effectively customize Kentico CMS UI

[9], Kentico CMS contains a set of classes which serve as connection points for customization

of its user interface. These are the classes stored in the ~\AppCode\Global\CMS folder.

Location under ~\AppCode\Global ensures that these classes will be a part of the final export

package.

I made a modification to the CMSApplication.cs class, specifically to its

AfterApplicationStart method, analogically following the code example published and

explained in Kentico DevNet (on-line): How to effectively customize Kentico CMS UI [6]. I

based connection of my custom processing methods on the same principle that is described in

the referenced article.

The code ensures that after the application is started (in the AfterApplicationStart method,

which is executed at that specific moment), each newly created OutputFilter calls the

OutputFilter_OnFilterCreated method, which is declared next. The method adds a new

CustomFilterHandler with the filter_OnAfterFiltering method in its constructor parameter

into the OnAfterFiltering event. Since an instance of the OutputFilter is created with each

page request, we have ensured that the filter_OnAfterFiltering method will be called on each

page request, at the specific moment when filtering has just been performed and the output

HTML code to be processed is available in the referenced finalHtml variable.

- 17 -

The filter_OnAfterFiltering method is declared as the last method in the code sample

above. It ensures processing of the output HTML code in the referenced finalHtml variable by

our custom methods declared in the ContextHelpHelper class – the AddTermsHelp and

AddElementsHelp methods.

The activity diagram in Figure 6 below shows at which point within a page request these

methods are executed. The actual code ensuring this behavior is attached in C.1.

Figure 6 - UML 2.0 Activity diagram showing the connection of the module's methods within each page request.

To execute these module’s methods, the following variables are initialized first:

int originalLength – length of the HTML code to be processed; this value is used at the

end of processing to check if the HTML code was modified.

- 18 -

string currentUrl – URL of the currently processed page; this value is used below to

ensure processing of only pages with the “.htm”, “.html” or “.aspx” extensions; the value

is obtained from CMS.GolbalHelper.UrlHelper.CurrentURL.

CMS.URLRewritingEngine.URLRewritingResultEnum currentStatus – this enumeration is

used to identify the type of the processed page; it is used to ensure filtering of only live

site pages (the PathRewritten status) and user interface pages (the SystemPage status); its

value is passed in a parameter of both the AddTermsHelp and the AddElementsHelp

methods; this value for the current page is always available in

CMS.URLRewritingEngine.URLRewriter.CurrentStatus, so the variable is initialized with

its current value.

string currentCulture – culture of the processed page; it is used as a parameter of the

processing methods; after verifying that the processed page has one of the allowed

extensions and that it is either a live site page or a user interface page, we either get it

using the CMS.GlobalHelper.CultureHelper.GetPreferredCulture() method (if it is a live

site page), or using the CMS.GlobalHelper.CultureHelper.GetPreferredUICulture()

method (if it is a user interface page).

With these variables initialized, the AddTermsHelp and AddElementsHelp methods are

executed with the finalHtml, currentStatus and currentCulture variables as their parameters,

entered respectively. After processing, a check for the finalHtml variable’s modification is

performed based on comparison of its current length with the value stored in the

originalLenght variable. If a modification is detected, it indicates that some help has been

added by one or both of the methods. In this case, we need to add the tooltip script to the

beginning of the page (the beginning of the page is recognized by the regular expression

matching the opening <form> tag). The script is needed in order for tooltips with help added

by the methods to be displayed.

5.2.3. Terms Highlighting

The first functionality covered by the module is terms highlighting. It is ensured by two

methods – the main AddTermsHelp method and the AddTermTooltips method, which is called

from the code of the first one. The text below focuses on how the output HTML code is

processed by these methods.

The AddTermsHelp method is executed after the OutputFilter processes pages’ output

HTML code, as explained in 5.2.2.

The method ensures processing of the output HTML code by regular expression-based

search and replace of defined terms in page text, i.e. the text enclosed in between particular

HTML tags. The beginning of the method initializes local variables, among which ArrayList

terms is the most important. This ArrayList (see MSDN Library (on-line): ArrayList Class

[10] for more details on this ASP.NET class) contains data rows from the

- 19 -

dbo.customtable_ContextHelpTerms table that contain definitions of terms to be processed on

the current page.

To eliminate repetitive access to the system database and therefore optimize performance

of the module, these ArrayLists are stored in the htTerms hash table (see MSDN Library (on-

line): Hashtable Class [11]). As the key for each item in the hash table, URL of the current

page (value from the PageUrl column of the data record) together with the current culture

(value from the CurrentCulture column) is used, separated by the tube character.

If no record is found for the current URL and culture in the hash table, the ArrayList with

terms needs to be obtained from the database. The method first instantiates a

CMS.SiteProvider.CustomTableItemProvider and uses it to retrieve a DataTable with the

records, while an SQL WHERE condition is used in the second parameter of the GetItems

method to retrieve only those rows that match the current culture and that are defined either

for live site pages or for user interface pages, based on the current context. Then, records from

this DataTable are filtered further into the final ArrayList that will be added to the hash table.

The second filtering selects only those records (terms) that should be applied for the current

URL. Emptiness of the PageUrl column is checked first, another part of the condition

(evaluated as logical disjunction) is the ResolveHelpUrl method executed with parameters

reflecting the current context. The checks are intentionally in this order for the benefit of

better performance, as the more selective condition is always better to be checked first with

lazy evaluation (the type of evaluation used in this case in C#). Finally, the ArrayList filled

with matching items is added to the hash table.

To ensure processing of only the text between HTML tags, the method instantiates the

RegExTags instance of the System.Text.RegularExpressions.Regex class (see MSDN Library

(on-line): Regex Class [12] for more details). The actual text of the regular expression

matches all HTML tags in a provided text. It is originally used in the RegExFixXHTML

method declared in the CMS.GlobalHelper .HTMLHelper.RegExFixXHTML class included in

the standard installation of the CMS. I utilized it in my methods so that I didn’t need to design

my own regular expression. The regular expression is also utilized in the AddElementsHelp

method described in 5.2.4.

This regular expression is applied to the processed HTML code in a cycle for each row in

the ArrayList. Using positions of the regular expression matches (the HTML tags), we get

substrings of text in between them. Then another regular expression matching is performed on

the substrings, while now the actual term is searched. If the searched term is found in the

substring, the AddTermTooltip method is used to wrap the term with code ensuring that a

tooltip with defined help will be displayed. The AddTermTooltip method is described in more

details in the following sub-chapter.

Substrings of the original HTML code, either modified or in their original form, are

subsequently appended to one string using an instance of the StringBuilder class (see MSDN

Library (on-line): StringBuilder Class [13] for more details). When processing finishes, the

string from the StringBuilder is saved into the processedHTML variable and another cycle

- 20 -

begins, this time searching for another term in the already modified text. When the cycle

finishes, value of the processedHTML variable is returned as the result of the method.

Figure 7 below is an activity diagram which illustrates the flow of the method. The actual

code of the method is attached in C.2.

Figure 7 - UML 2.0 Activity diagram illustrating the flow of the AddTermsHelp method.

- 21 -

The AddTermTooltips method is a helper method utilized within execution of the

AddTermsHelp method described above. It takes a substring of the processed HTML code

(text in between HTML tags) provided in the first parameter and replaces occurrences of the

term provided in the second one. Replacing is performed by instantiating another

System.Text.RegularExpressions.Regex, and executing its Regex.Replace method (see MSDN

Library (on-line): Regex Class [12] for more details) with the processed text in its parameter.

As can be seen in the code of the method attached in C.3, the method has two main

branches: the first one for terms that are defined as plain text, and the other one for terms

defined as a regular expression. This decision is done based on the value provided in the fifth

parameter, which is originally taken from the term’s database row’s IsRegex column.

Depending on this value, the second Regex is either created from the unmodified string from

the TermExpression column, or from the string wrapped by the “\\b” regular expression meta-

characters (indicating word boundaries).

All matches of the regular expression created this way are then replaced with the original

occurrence wrapped in added HTML tags that ensure displaying of help tooltips. In each

branch, there are two sub-branches, while the added tags vary in each of them depending on if

the help icon should also be displayed after the detected terms.

The processed text, stored in the string result variable, is then returned as the result of the

method and processed further by the AddTermsHelp metod, as described in the beginning of

this chapter.

Figure 8 below is an activity diagram which illustrates the flow of the method. The actual

code of the method is attached in C.3.

- 22 -

Figure 8 - UML 2.0 Activity diagram illustrating the flow of the AddTermTooltip method.

5.2.4. HTML Elements Help

The second functionality of the module is displaying of help next to HTML elements with

certain IDs. These elements can be virtually any HTML tags that have the ID attribute and

some value in it. The functionality is provided by the AddElementsHelp method declared in

the ContextHelpHelper class. As explained in 5.2.2, the method is executed after the

AddTermsHelp method, with the output HTML code already processed by this method used in

its first parameter.

Similarly as in the AddTermsHelp method, the htElements hash table is used to store

ArrayLists containing defined help for elements that should be searched on particular pages.

These ArrayLists contain only those rows from the dbo.customtable_ContextHelpElements

custom table that match the current URL, type of page (either system page or live site page)

and the current culture. As a key for each hash table record, the current culture code and

current URL are used respectively, separated by the tube character.

If no record for the current page is found in the hash table, the

CMS.SiteProvider.CustomTableItemProvider is initialized and used to retrieve records from

the dbo.customtable_ContextHelpElements custom table. An SQL WHERE condition is used

in the second parameter of the GetItems method to retrieve only those rows that match the

current culture and that are defined either for live site pages or for user interface pages, based

on the current context. Then, records from this DataTable are filtered further into the final

ArrayList that will be added to the hash table. Filtering selects only those records (elements)

that should be applied for the current URL. Emptiness of the PageUrl column is checked first

(it is expected to be more selective and therefore it should be checked first with lazy

- 23 -

evaluation, which is used in this case), the second part of the logical disjunction is the

Boolean value returned by the ResolveHelpUrl method. The method is executed with the

parameters initialized above to reflect the current context. If the condition is met, the row is

added to the ArrayList. When iteration for all retrieved records finishes, the ArrayList filled

with data rows of elements to be searched on the current page is added to the hash table.

With the ArrayList with elements to be searched ready, the method proceeds to the actual

detection of HTML element IDs. For this purpose, the RegExTags regular expression, also

utilized and described in 5.2.3, is used to identify HTML tags in the processed HTML code.

This is done in a cycle for each defined element in ArrayList elements. In each iteration of this

cycle, a collection of tags found by the regular expression is searched to identify tags with the

ID attribute matching the value in the ElementID column of the respective data record from

ArrayList elements. If a matching tag is found, the helpIconLink string, which is the actual

HTML code of the help icon with the help tooltip and link leading to the CustomHelp.aspx

page, is added after it in case of self-closing tags, or after the currently processed opening

tag’s closing tag in case of pair tags. The openCount integer counter and the lastOpen string

variable are utilized to ensure that the help icon is added after appropriate closing tags when

the processed HTML code contains nested tags.

An instance of the StringBuilder class is used here, similarly as in 5.2.3, to append

processed substrings of the original HTML code, either in their original form or with the

additional tags ensuring displaying of help. When the last iteration of the cycle finishes,

processed HTML code with all help tags added is returned as the result of the method.

Figure 9 below is an activity diagram illustrating the flow of the method. The actual code

of the method is attached in C.4.

- 24 -

Figure 9 - UML 2.0 Activity diagram illustrating the flow of the AddElementsHelp method.

5.2.5. ResolveHelpUrl Method

This method is used in both the AddTermsHelp and the AddElementsHelp methods (described

in 5.2.3 and 5.2.4 respectively). In both cases, it is used as a part of a condition to decide if

- 25 -

each defined term or HTML element retrieved from the database should be searched on the

current page.

The method takes the resolved URL defined in the PageURL column of each term or

HTML element data record and compares it with the current page URL, which is provided to

the method in the second parameter. Based on the value of the third parameter, which is

originally the value of the UrlResolveType column of each particular term or HTML element

record, the code continues to one of the four branches of the switch branching. As explained in

the UrlResolveType column’s description in 5.1, particular branches ensure that the method

returns the true value (the URLs are matching), if:

case 0: the URL in the first parameter is equal to the current URL

case 1: the URL in the first parameter is a substring of the current URL

case 2: the URL in the first parameter is a regular expression that matches the current

URL

case 3: the URL in the first parameter is a regular expression that matches a substring of

the current URL

Except for the first case where comparison is done using the String.Equals method, regular

expression comparison using the Regex.IsMatch method (documented at MSDN Library (on-

line): Regex Class [12]) is used to compare the two URLs. Instantiation of a regular

expression in the Regex reUrl property using the RegexHelper.GetRegex method is performed

first, while the resolvedUrl string provided in the first parameter is used as its parameter,

differently in each of the remaining three branches.

When comparing as URL substring, it is escaped using the Regex.Escape method. When

comparing as a regular expression, it is wrapped in the ^ and $ meta-characters. When

comparing as a regular expression substring, the string is left unmodified. Then, the

reUrl.IsMatch method is called with the currentUrl value in its parameter. Boolean result of

this matching is then returned as a result of the whole method.

Figure 10 below is an activity diagram illustrating the flow of the method. The actual

code of the method is attached in C.5.

- 26 -

Figure 10 - UML 2.0 Activity diagram illustrating the flow of the ResolveHelpUrl method.

5.3. Custom Context Help Topics

The last functionality of the module is achieved by a modification of the

CMSAdminControls\UI\Help.ascx control. This control is a native part of Kentico CMS and it

is used in all user interface pages to provide users with access to the default context help

topics. The control appears as a green circle icon with a question mark in the middle, as

depicted in Figure 3 in chapter 3.3.3. The modification of the control is based on adding the

following extra line to the control’s Help.ascx.cs code behind file:

lnkHelp.NavigateUrl = ContextHelpHelper.ResolveCustomTopic(TopicName, DocumentationUrl);

The added code ensures that the value returned by the ResolveCustomTopic method, called

with the topic name in the first parameter and the default context help location in the second

one, is inserted as a value of the lnkHelp.NavigateUrl property. This is the property where the

actual target of the help icon, i.e. the URL of the default context help topic, is natively stored.

The method takes a context help topic name in the first parameter and checks if there is a

custom context help topic defined for it.

As explained in 5.1, defined custom topics are stored in the

dbo.customtable_ContextHelpTopics custom table. For optimized performance, the

htIsCustomTopic hash table is used here to eliminate repetitive database access, similarly as in

5.2.3 and 5.2.4. The hash table contains a Boolean value indicating if there is a custom topic

defined for a particular topic under a specific user interface culture. The culture code and topic

name are used as a key for each record, separated by the tube character.

If there is a record for the topic, the method returns a URL of the CustomHelp.aspx page

(see 5.4 for more details) with the topic name and current culture appended in query string

- 27 -

parameters. If no record is found for the topic, the method returns a URL of the default

context help topic, which is the default context help location provided in the second

parameter, with the topic name and the “.htm” suffix appended. The actual data of the custom

topic are not loaded at this point yet – they are obtained on page load of the CustomHelp.ascx

page, as explained in 5.4.

Figure 11 below is an activity diagram which illustrates the flow of the method. The

actual code of the method is attached in C.6.

Figure 11 - UML 2.0 Activity diagram illustrating the flow of the ResolveCustomTopic method.

5.4. CustomHelp.aspx Page

The CMSGlobalFiles/ContextHelp/CustomHelp.aspx page is used for three purposes:

Displaying detailed descriptions of terms.

Displaying detailed descriptions of HTML elements.

Displaying custom Context Help topics.

The graphic elements in the header and footer of the page (see Figure 12 below) are inherited

from the ~/CMSMasterPages/UI/Dialogs/ModalDialogPage.master master page (the concept

of master pages in ASP.NET is described in MSDN Library (on-line): ASP.NET Master

- 28 -

Pages [15]). This master page is commonly used for various parts of the system's user

interface. Besides ensuring the uniform look that all Kentico CMS user interface pages share,

using this master page also causes that the CustomHelp.aspx page will be treated as a system

page by the system. This, among other things, means that text of this page will be processed

by the two methods described in 5.2.3 and 5.2.4. In other words, help for terms and HTML

elements is displayed on this page too, as can be seen in Figure 12 below.

Figure 12 - Detailed description of a term displayed on the CustomHelp.aspx page. Please note that defined terms are

highlighted on this page too.

Below the graphic elements inherited from the master page, only a single Literal control

resides. This is a native ASP.NET control used to insert dynamically provided raw HTML

code into a page’s output HTML code (see MSDN Library (on-line): LiteralControl Class [14]

for more details). In our case, it is used to display the actual help text, obtained differently in

each of the three cases. The actual code of the method is attached in C.7.

The code attached in C.8 is the page’s Page_Load method. A Page_Load method is

present in the code behind file of each ASP.NET page (CustomHelp.aspx.cs in this case) and

it is executed when the page is loaded. As you can see, the code splits into three branches,

depending on the name of the query string key in the URL under which the page was

accessed. The CMS.GlobalHelper.QueryHelper.Contains method from Kentico CMS API is

used here to verify if the query string contains either the „termId“, „elementId“ or „topic“

- 29 -

parameters. The parameters are expected to be present in the URL, as all URLs leading to this

page are rendered with them, as explained in 5.2.3, 5.2.4 or 5.3. In case that neither of the

parameters is present (e.g. on access by entering a direct URL into the browser without any

query string), the following text message is displayed in the Literal control: “Invalid access -

no help subject specified in querystring.”

Based on presence of one of the parameters, a DataRow with the required help record is

loaded from either the htTerms, htElements or htTopics hash table (see 5.2.3, 5.2.4 or 5.3

respectively for more information on how data records are stored in the hash tables for

optimized performance). To get a key for a hash table record, value of the parameters

mentioned above is used, together with the value of the “culture“ parameter. Values are

obtained using the CMS.GlobalHelper.QueryHelper.GetValue mehtod, also available in the

native Kentico CMS API.

When the DataRow is obtained, values from the LongDescription column (for terms and

HTML elements) or the TopicText column (for custom topics) is inserted into the Literal.Text

property of the Literal control mentioned in the beginning of this chapter. This ensures that

defined custom help is displayed on the page.

5.5. User Interface of the Module

The module’s user interface is located in CMS Desk -> Tools -> Context help. This location

was chosen based on the module requirements attached as A - Module Requirements from

Kentico Software. Physically, pages of this user interface are stored inside the project folder,

specifically in ~\CMSGlobalFiles\ContextHelp\Tools. This location was chosen, according to

Kentico CMS 5.0 Developer’s Guide (on-line): Folder structure and import/export [8], to

ensure that the user interface pages will be included in the export package, together with the

rest of the module. Figure 13 below depicts all files stored in this folder, viewed as a tree in

Visual Studio’s Solution Explorer.

- 30 -

Figure 13 - Folder containing module's user interface pages viewed in Visual Studio's Solution Explorer.

Figure 14 is a screenshot of the list of defined terms in the module’s user interface. As can be

seen, the module is fully integrated into the native user interface of the CMS. This was

achieved by registering the module in the system and creating a UI element for it in the Tools

section’s main menu. To achieve this, I followed Kentico CMS 5.0 Developer’s Guide (on-

line): Developing custom modules [4]. In CMS Site Manager -> Development -> Modules,

the module is both registered as a separate module and added as a UI element of the Tools

module, which represents the menu on the CMS Desk -> Tools tab. As a target URL of this UI

element, the ~/CMSGlobalFiles/ContextHelp/Tools/ContextHelpModule_Frameset.aspx page

is used. The page is described further in this chapter.

Use of the master pages stored in ~/CMSMasterPages/UI/ ensures that the same CSS

styles that are used for the rest of the user interface are used on these pages too. This is

another way how uniform look with the rest of the user interface of the CMS was achieved.

- 31 -

Figure 14 - List of defined terms in the module’s user interface.

5.5.1. User Interface Pages Nesting

Figure 8 below illustrates how the user interface consists of particular nested sub-sections.

The following list gives more details on each sub-section, while the corresponding area on the

page is marked with a rectangle with a corresponding number:

1. CMS Desk’s main menu – this is a native part of Kentico CMS user interface; it provides

four tabs, while the Context help module’s user interface is located on the Tools tab

2. Tools menu – this is also a native part of the CMS, displayed when the Tools tab is

selected in the main menu; the Tools menu contains all native Kentico CMS modules,

while the added Context help module is at the bottom of the menu; clicking the menu item

opens the linked

~/CMSGlobalFiles/ContextHelp/Tools/ContextHelpModule_Frameset.aspx page in the

area indicated by rectangles number 3 and 4, where each of the rectangles indicates one

frame of the page.

3. The first frame of the ContextHelpModule_Frameset.aspx page. Contains the nested

Header.aspx page.

4. The second frame of the ContextHelpModule_Frameset.aspx page. It dynamically

displays the actual pages of the user interface, as further explained in 5.5.2.

- 32 -

Figure 15 – This is the same screenshot as in Figure 14, while the red areas are highlighting particular nested parts of the

displayed page. This nesting is described in the paragraph above.

5.5.2. The Terms, Elements and Custom Topics Tabs

The actual user interface pages for listing, defining and managing terms, HTML elements and

custom context help topics are physically stored in the three sub-folders of the

CMSGlobalFiles\ContextHelp\Tools folder. Each sub-folder contains two pages – one for

listing and one for creating new records or editing the existing ones. Besides the two pages

and their associated code behind files, each of the folders also contains an ASCX control used

on the editing page and an XML definition of the UniGrid control used on the listing page.

The following list explains content of the three sub-folders:

Terms – this folder contains pages displayed under the Terms tab

o Term_Edit.aspx – page used for creating new terms or editing the existing ones

(see Figure 16)

o Term_EditForm.ascx – ASCX user control encapsulating input controls for

particular fields of the dbo.customtable_ContextHelpTerms custom table; it is

used on the above mentioned page

- 33 -

o Terms_List.aspx – page used for listing of already defined terms; the UniGrid

control is used on the page, uniformly as in all listings in the system’s native user

interface

o Terms_List.xml – this XML file contains configuration of the UniGrid control

used on the above mentioned page; it defines which columns of the custom table

should be displayed in the grid and offered in the filter above the grid

Figure 16 - Editing of an existing terms on the Term_Edit.aspx page. The same page is also used for definition of new

terms.

The Elements and Topics folders have content similar to the Terms folder, and the purpose

and content of particular files is also fully analogical to what is described above:

Elements – contains pages displayed under the Elements tab

o Element_Edit.aspx

o Element_EditForm.aspx

o Elements_List.aspx

o Elements_List.xml

Topics – contains pages displayed under the Custom topics tab

o Topic_Edit.aspx

o Topic_EditForm.aspx

o Topics_List.aspx

- 34 -

o Topics_List.xml

- 35 -

Chapter 6

Further Improvement Possibilities As usual in software development, ideas for further improvements of the module over the

scope defined by received module requirements (as attached in A - Module Requirements

from Kentico Software) appeared during its implementation. Even though the module brings

an already interesting and powerful set of functionality, it may be further improved or

extended in many ways. The following list contains ideas for further improvements that may

be implemented in the future:

Enable global disabling of the module’s activity using a settings key in the user interface

of the CMS.

Ensure both case sensitive and case insensitive detection of defined terms.

Enable definition of scopes for more detailed specification of pages where particular

terms or HTML elements should be searched.

Enable advanced customization of added help styling, i.e. an alternative to the currently

used double-underlined font used for detected terms. This should be achievable by

selecting a custom or pre-defined CSS class within the system’s user interface, so that

users have no need to modify the code of the module to achieve this level of

customization.

Enable customization of the help icon displayed with detected terms of HTML elements.

This should be achievable by uploading a custom image file from the user’s local

computer via the system’s user interface.

Create a larger default set of defined HTML elements, terms or custom topics that would

be included in the package and that would extensively demonstrate possibilities of the

module on some of the sample websites shipped with the system.

Create dedicated data objects, providers and database tables for the module, so that it is

unified with the native part of the CMS.

Include the module in the standard installation of some future major release version of

Kentico CMS.

- 36 -

Chapter 7

Conclusion Development of the module described in this thesis contributed to further extension of the

possibilities that Kentico CMS gives to website developers. By adding this module to the

standard installation of Kentico CMS, website developers get a simple and straightforward

way how they can provide users of their websites with context-related help directly on the live

site or in the system’s user interface. If properly used, the module may contribute to their

websites being easier to use and their content easier to understand.

On top of it, the custom context help topics functionality allows web developers to

customize default context help that is natively shipped with the system. Because the default

context help is sometimes too general to be fully understood by non-technical end users, this

module enables its customization with regards to the specific needs of an individual website

and its content editors or generally all users of the system’s user interface.

- 37 -

Literature

[1] Kentico CMS for ASP.NET (on-line), 2010. Accessible at URL http://www.kentico.com

(May 2010).

[2] Kentico CMS for ASP.NET (on-line): System requirements, 2010. Accessible at URL

http://www.kentico.com/Download/System-Requirements.aspx (May 2010).

[3] Kentico CMS for ASP.NET (on-line): Features, 2010. Accessible at URL

http://www.kentico.com/free-cms-asp-net.aspx (May 2010).

[4] Kentico CMS 5.0 Developer’s Guide (on-line): Developing custom modules, 2010.

Accessible at URL: http://devnet.kentico.com/docs/5_0/devguide/custom_modules.htm

(June 2010).

[5] Kentico DevNet (on-line): Documentation, 2010. Accessible at URL:

http://devnet.kentico.com/Documentation.aspx (May 2010).

[6] Hejtmánek, Martin. Kentico DevNet (on-line): DIY: How to apply custom output filter,

2010. Accessible at URL: http://devnet.kentico.com/Blogs/Martin-Hejtmanek/April-

2010/DIY--How-to-apply-custom-output-filter.aspx (June 2010).

[7] Kentico CMS 5.0 Developer’s Guide (on-line): Custom tables, 2010. Accessible at URL:

http://devnet.kentico.com/docs/5_0/devguide/custom_tables_module_overview.htm (June

2010).

[8] Kentico CMS 5.0 Developer’s Guide (on-line): Folder structure and import/export, 2010.

Accessible at URL:

http://devnet.kentico.com/docs/5_0/devguide/folder_structure_and_importexport.htm

(June 2010).

[9] Hejtmánek, Martin. Kentico DevNet (on-line): How to effectively customize Kentico

CMS UI, 2009. Accessible at URL: http://devnet.kentico.com/Blogs/Martin-

Hejtmanek/June-2009/How-to-effectively-customize-Kentico-CMS-UI.aspx (June 2010).

- 38 -

[10] MSDN Library (on-line): ArrayList Class, 2010. Accessible at URL:

http://msdn.microsoft.com/en-us/library/system.collections.arraylist%28VS.71%29.aspx

(June 2010).

[11] MSDN Library (on-line): Hashtable Class, 2010. Accessible at URL:

http://msdn.microsoft.com/en-us/library/system.collections.hashtable%28VS.71%29.aspx

(June 2010).

[12] MSDN Library (on-line): Regex Class, 2010. Accessible at URL:

http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.aspx (June

2010).

[13] MSDN Library (on-line): StringBuilder Class, 2010. Accessible at URL:

http://msdn.microsoft.com/en-us/library/system.text.stringbuilder%28VS.71%29.aspx

(June 2010).

[14] MSDN Library (on-line): LiteralControl Class, 2010. Accessible at URL:

http://msdn.microsoft.com/en-us/library/system.web.ui.literalcontrol.aspx (June 2010).

[15] MSDN Library (on-line): ASP.NET Master Pages, 2010. Accessible at URL:

http://msdn.microsoft.com/en-us/library/wtxbf3hh.aspx (June 2010).

Please note: off-line versions of all referenced resources are available on the attached CD

medium.

- 39 -

Annexes

A. Module Requirements from Kentico Software

The following is a literal transcription of the module requirements received from Kentico

Software as the assignment of this thesis.

A.1 Purpose

The goal is to provide the way how to interactively provide the context help for the UI,

editable by the client (for their own specific purposes).

A.2 Description

The module should allow management of the context help topics (tooltips), their relations and

detailed descriptions to interconnect parts of the system and make the UI more friendly for

beginners. It should allow following options:

Term highlighting – Similar to Google AdWords, specific defined terms will be

highlighted and tooltips created over them

Tooltip for specific elements – User defines tooltip and location for specific UI page and

element on the page

Context help for specific page – It should replace current context help hint with the data

from the context help database

The tooltips will be displayed with the tooltip JS framework included into Kentico CMS.

There will be base version of tooltip and detailed version, which will display when the user

clicks “More information …” link at the bottom of the base tooltip. The tooltip will expand

automatically. The tooltips should be bound to specific UI culture as a new tab in the UI

culture properties. The tooltips should support all types of macros (should be resolved by the

macro resolver).

A.3 Use Cases

Term Highlighting

1. Administrator defines the specific term that should be highlighted across the system in

any text (not inside of the tags), e.g. “web part”.

2. He chooses the scope of the term from following options (different than the following

controls may be used):

(radiobutton) All pages in given scope

[checkbox] UI pages

[checkbox] Live site pages

- 40 -

(radiobutton) Specific URL

URL: [textbox]

3. He selects whether the help icon should be displayed at the term, if checked, the help icon

will be added directly after the given term.

[checkbox] Display the help icon

4. When user opens the UI, the given terms will be double underlined, and given tooltip will

be applied to the term

Element Tooltips

1. Administrator defines the specific tooltip

2. He defines for which pages the tooltip should apply (same as above)

3. He defines the HTML element ID to which the tooltip should be applied (different than

the following suggested controls may be used):

(radionbutton) Specific element

ID: [textbox]

4. When user opens the specific UI, the given elements will have

Page Context Help

1. Administrator defines the specific context help article

2. He defines for which page the context help should apply

3. The context help control on the page will automatically pick up the context help from the

context help module and displays in the new window the new help.

A.4 User Interface

The interactive context help will be editable within the Development section of the Site

manager.There will be three tabs:

Terms highlighting

Element tooltips

Page context help

Each tab will provide a list of the given settings, and the possibility to manage them.

A.5 Interactions with Other Modules

It should interact automatically with all pages in some way, the processing should be done

through the OutputFilter modification.

A.6 Security Requirements

The context help must be editable only by users with access to the Tools section of CMS

Desk.

- 41 -

A.7 Performance Requirements

The context help rules must be cached and the process of applying the data should not take too

long.

B. Descriptions of Data Records Stored by the Module

The following tables contain descriptions of particular database tables created with the

module. Each table contains a listing of all columns in the particular table, while information

on the type of information stored in the column is provided.

B.1 dbo.customtable_ContextHelpTerms

Column name Data type Allows

nulls

Description

ItemID Int false Identifier of the data record.

ItemGUID uniqueidentifier false Identifier of the data record unique in

the whole system.

TermExpression nvarchar(200) false Sequence of characters representing the

term searched in output HTML code.

IsRegex Bit false Indicates if the string in the

TermExpression column should be

searched as a regular expression.

ShortDescription Ntext false Short description of the term displayed

in a tooltip on mouse-over of the term or

help icon.

LongDescription Ntext false Long description displayed after mouse

click on the term or help icon. It is

displayed in a new browser window on

the CustomHelp.aspx page.

LivePages Bit false Indicates if the terms should be searched

in output code of live site pages, i.e.

pages of the actual front-end website.

UIPages Bit false Indicates if the terms should be searched

in output code of user interface pages.

PageURL nvarchar(100) True URL of a page where the terms should

be searched. URL resolving depends on

the value in the UrlResolveType column.

When null, the terms are searched on all

pages compliant to other conditions.

UrlResolveType Int false Determines how page URL entered in

the PageURL column will be resolved.

The following integer numbers indicate

- 42 -

Column name Data type Allows

nulls

Description

the following resolve types:

0: exact URL – the entered URL must

match the page URL exactly

1: URL substring – the entered URL

must be a substring of the page URL

2: Regular expression – the entered

value is a regular expression which must

match the page URL exactly

3: Regular expression substring – the

entered value is a regular expression

which must match a substring of the

page URL

CultureCode Nvarchar(10) false Code of website or user interface culture

in which the term should be searched.

DisplayIcon Bit false Indicates if the green question mark icon

with link to the long description should

be displayed after the term. If false, the

term is double-underlined and becomes

a link.

B.2 dbo.customtable_ContextHelpElements

Column name Data type Allows

nulls

Description

ItemID Int false Identifier of the data record.

ItemGUID uniqueidentifier false Identifier of the data record unique in

the whole system.

ElementID nvarchar(100) false Value of the HTLM element’s ID

attribute. HTML elements help are

searched based on this value.

ShortDescription Ntext false Short description of the HTML element

displayed in a tooltip on mouse-over of

the displayed help icon.

LongDescription Ntext false Long description displayed after

clicking the help icon. It is displayed in

a new browser window on the

CustomHelp.aspx page.

LivePages Bit false Indicates if the HTML element should

- 43 -

Column name Data type Allows

nulls

Description

be searched in output code of live site

pages, i.e. pages of the actual front-end

website.

UIPages Bit false Indicates if the HTML element should

be searched in output code of user

interface pages.

PageURL nvarchar(100) true URL of a page where the HTML

element should be searched. URL

resolving depends on the value in the

UrlResolveType column. When null, the

HTML elements are searched on all

pages compliant to other conditions.

UrlResolveType Int false Determines how page URL entered in

the PageURL column will be resolved.

The following integer numbers indicate

the following resolve types:

0: exact URL – the entered URL must

match the page URL exactly

1: URL substring – the entered URL

must be a substring of the page URL

2: Regular expression – the entered

value is a regular expression which must

match the page URL exactly

3: Regular expression substring – the

entered value is a regular expression

which must match a substring of the

page URL

CultureCode Nvarchar(10) false Code of website or user interface culture

in which the HTML elements should be

searched.

B.3 dbo.customtable_ContextHelpTopics

Column name Data type Allows

nulls

Description

ItemID Int false Identifier of the data record.

ItemGUID Uniqueidentifier false Identifier of the data record unique in the

whole system.

- 44 -

Column name Data type Allows

nulls

Description

TopicName nvarchar(100) false Name of the default context help topic

which has to be replaced by this custom

topic. Name of the appropriate .htm file

stored in the ~/CMSHelp folder needs to

be entered. See 3.3.3 for more details on

default context help topic names.

TopicText Ntext false HTML code of the actual custom context

help topic. The code will be displayed on

the CustomHelp.aspx page.

CultureCode Nvarchar(10) false Code of website or user interface culture

where the HTML elements should be

searched.

C. Code Extracts

This annex contains extracts of the module’s code, which are referenced throughout the text of

this thesis.

C.1 Connection of the Module’s Methods to the OutputFilter

The following code extract is the code that was added to the CMSApplication.cs class in order

to ensure processing of output HTML code generated by the system with the module’s

mehthods, as described in 5.2.2.

/// <summary>

/// Fires after the application start event

/// </summary>

public static void AfterApplicationStart(object sender, EventArgs e)

{

// Add your custom actions

CMS.CMSOutputFilter.OutputFilter.OnFilterCreated += new

CMS.CMSOutputFilter.OutputFilter.OutputFilterHandler(OutputFilter_OnFilterCreated);

}

/// <summary>

/// Runs after the filter for given request was created

/// </summary>

/// <param name="filter"></param>

static void OutputFilter_OnFilterCreated(CMS.CMSOutputFilter.OutputFilter filter)

{

filter.OnAfterFiltering += new CMS.CMSOutputFilter.OutputFilter.CustomFilterHandler(filter_OnAfterFiltering);

}

/// <summary>

/// Runs after output filter finished its procesing

/// </summary>

/// <param name="filter">Output filter</param>

/// <param name="finalHtml">Output page HTML</param>

static void filter_OnAfterFiltering(CMS.CMSOutputFilter.OutputFilter filter, ref string finalHtml)

{

int originalLength = finalHtml.Length;

string currentUrl = UrlHelper.CurrentURL;

CMS.URLRewritingEngine.URLRewritingResultEnum currentStatus = CMS.URLRewritingEngine.URLRewriter.CurrentStatus;

if ((currentStatus == CMS.URLRewritingEngine.URLRewritingResultEnum.PathRewritten) ||

((currentStatus == CMS.URLRewritingEngine.URLRewritingResultEnum.SystemPage) &&

(currentUrl.EndsWith(".aspx") || currentUrl.EndsWith(".html") || currentUrl.EndsWith(".htm"))))

{

string currentCulture;

if (currentStatus == CMS.URLRewritingEngine.URLRewritingResultEnum.PathRewritten)

{

currentCulture = CultureHelper.GetPreferredCulture();

}

else

{

currentCulture = CultureHelper.GetPreferredUICulture();

}

- 45 -

finalHtml = CMS.ContextHelp.ContextHelpHelper.AddTermsHelp(finalHtml, currentStatus, currentCulture);

finalHtml = CMS.ContextHelp.ContextHelpHelper.AddElementsHelp(finalHtml, currentStatus, currentCulture);

// registers tooltip script for a page where context help was added

if ((finalHtml.Length != originalLength) && !finalHtml.Contains("wz_tooltip.js"))

{

string tooltipScript = "<script src=\"" + UrlHelper.ResolveUrl("~/CMSScripts/ToolTip/wz_tooltip.js") + "\"

type=\"text/javascript\"></script>";

System.Text.RegularExpressions.Regex re = RegexHelper.GetRegex("<form ", RegexHelper.DefaultOptions |

System.Text.RegularExpressions.RegexOptions.IgnoreCase);

finalHtml = re.Replace(finalHtml, tooltipScript + "$0");

}

}

}

C.2 The AddTermsHelp Method

The following code extract is the code of the AddTermsHelp method. The method is

implemented in the ContextHelpHelper.cs class and ensures adding of terms help, as

explained in 5.2.3.

public static string AddTermsHelp(string sourceHtml, CMS.URLRewritingEngine.URLRewritingResultEnum currentStatus, string currentCulture)

{

string processedText = String.Empty;

string processedHtml = String.Empty;

string currentUrl = UrlHelper.RemoveQuery(UrlHelper.CurrentURL);

string lowerUrl = currentUrl.ToLower();

// load array list with terms for the current culture and url from the hashtable

ArrayList terms = (ArrayList)htTerms[currentCulture + "|" + lowerUrl];

// if the array list is not in the hash table, load it from the custom table in DB

if (terms == null)

{

CustomTableItemProvider ctiProvider = new CustomTableItemProvider(CMSContext.CurrentUser);

DataSet ds = new DataSet();

if (currentStatus == CMS.URLRewritingEngine.URLRewritingResultEnum.SystemPage)

{

ds = ctiProvider.GetItems("customtable.ContextHelpTerms", "UIPages=1 AND CultureCode='" + currentCulture + "'", null);

}

else

{

ds = ctiProvider.GetItems("customtable.ContextHelpTerms", "LivePages=1 AND CultureCode='" + currentCulture + "'", null);

}

DataTable tableTerms = (DataTable)ds.Tables[0];

// create an arraylist with rows of the data table table

terms = new ArrayList();

for (int i = 0; i < tableTerms.Rows.Count; i++)

{

DataRow row = tableTerms.Rows[i];

string termUrl = (string)row["PageUrl"];

int resolveType = (int)row["UrlResolveType"];

if ((termUrl == String.Empty)||(ResolveHelpUrl(termUrl, currentUrl, resolveType)))

{

terms.Add(row);

}

}

// save the array list into the hashtable

htTerms[currentCulture + "|" + lowerUrl] = terms;

}

Regex RegExTags =

RegexHelper.GetRegex("<(?:/?(\\w+)(?:\\s+(\\w+)(?:\\s*=(?!\\s)((?:\"(?:[^\"]|\\\\\")*\")|(?:\'(?:[^\']|\\\\\')*\')|(?:[^\\s/>]|/(?!>))*)|(

?=[\\s/>])(?<3>)|(?<3>=)))*\\s*/?>|(?<1>!--))|(?<1>-->)");

processedHtml = sourceHtml;

// repeat for each term

foreach (DataRow dr in terms)

{

string term = (string)dr["TermExpression"];

bool displayHelpIcon = (bool)dr["DisplayIcon"];

// creates a string builder for the final output

StringBuilder sb = new StringBuilder();

// tags in the currently processed html

MatchCollection tags = RegExTags.Matches(processedHtml);

int counter = 0;

int index = 0;

bool isBody = false;

bool isScript = false;

foreach (Match m in tags)

{

string tag = m.ToString();

bool endTag = tag.StartsWith("</");

bool selfClosed = tag.EndsWith("/>");

string tagName = m.Groups[1].ToString();

string lowerTagName = tagName.ToLower();

int tagIndex = m.Index;

// append text before tag

- 46 -

if (tagIndex > index)

{

processedText = processedHtml.Substring(index, tagIndex - index);

if (isBody && !isScript)

{

string finalText = AddTermTooltips(processedText, term, (int)dr["ItemID"], (string)dr["ShortDescription"],

(bool)dr["IsRegex"], currentUrl, currentCulture, displayHelpIcon);

sb.Append(finalText);

}

else

{

sb.Append(processedText);

}

}

// append tag

sb.Append(m.ToString());

index = m.Index + m.Length;

counter++;

// check if position is inside the Body or Script element

if (lowerTagName == "body")

{

isBody = !endTag && !selfClosed;

}

else if (lowerTagName == "script")

{

isScript = !endTag && !selfClosed;

}

}

// append text after the last tag (or whole text if there are no tags)

if (processedHtml.Length > index)

{

processedText = processedHtml.Substring(index, processedHtml.Length - index);

sb.Append(processedText);

}

// save processed html at the end of processing

processedHtml = sb.ToString();

}

// return processed Html

return processedHtml;

}

C.3 The AddTermTooltip Method

The following code extract is the code of the AddTermTooltip method. The method is

implemented in the ContextHelpHelper.cs class and it works as a helper method used within

the code of the AddTermsHelp method, as explained in 5.2.3.

private static string AddTermTooltip(string processedText, string term, int termId, string description, bool isRegex, string currentUrl,

string currentCulture, bool displayHelpIcon)

{

string result = String.Empty;

// if the term IS a regular expression

if (isRegex)

{

Regex RegExTerms = RegexHelper.GetRegex(term);

string withTooltipAndLink = String.Empty;

if (displayHelpIcon)

{

string helpIcon = ("<img style=\"border: none\"

src=\"/KenticoCMS/App_Themes/Default/Images/General/HelpSmall.png\"onmouseover=\"Tip('" + description + "')\"

onmouseout=\"UnTip('')\"></img>");

string helpIconWithLink = "<a target=\"_blank\" href=\"" +

UrlHelper.ResolveUrl("~/CMSGlobalFiles/ContextHelp/CustomHelp.aspx?termId=") + termId + "&culture=" + currentCulture + "&originalUrl=" +

currentUrl.ToLower() + "\">" + helpIcon + "</a>";

withTooltipAndLink = "$0" + helpIconWithLink;

}

else

{

string withTooltip = "<span style=\"border-bottom: 3px double #000;\" onmouseover=\"Tip('" + description + "')\"

onmouseout=\"UnTip('')\">$0</span>";

withTooltipAndLink = "<a target=\"_blank\" style=\"text-decoration:none\" href=\"" +

UrlHelper.ResolveUrl("~/CMSGlobalFiles/ContextHelp/CustomHelp.aspx?termId=") + termId + "&culture=" + currentCulture + "&originalUrl=" +

currentUrl.ToLower() + "\">" + withTooltip + "</a>";

}

result = RegExTerms.Replace(processedText, withTooltipAndLink);

}

// if the term IS NOT a regular expression

else

{

Regex RegExTerms = RegexHelper.GetRegex("\\b" + Regex.Escape(term) + "\\b");

string withTooltipAndLink = String.Empty;

if (displayHelpIcon)

{

string helpIcon = ("<img style=\"border: none\"

src=\"/KenticoCMS/App_Themes/Default/Images/General/HelpSmall.png\"onmouseover=\"Tip('" + description + "')\"

onmouseout=\"UnTip('')\"></img>");

string helpIconWithLink = "<a target=\"_blank\" href=\"" +

UrlHelper.ResolveUrl("~/CMSGlobalFiles/ContextHelp/CustomHelp.aspx?termId=") + termId + "&culture=" + currentCulture + "&originalUrl=" +

currentUrl.ToLower() + "\">" + helpIcon + "</a>";

withTooltipAndLink = "$0" + helpIconWithLink;

}

- 47 -

else

{

string withTooltip = "<span style=\"border-bottom:3px double #000;\" onmouseover=\"Tip('" + description + "')\"

onmouseout=\"UnTip('')\">" + term + "</span>";

withTooltipAndLink = "<a target=\"_blank\" style=\"text-decoration:none\" href=\"" +

UrlHelper.ResolveUrl("~/CMSGlobalFiles/ContextHelp/CustomHelp.aspx?termId=") + termId + "&culture=" + currentCulture + "&originalUrl=" +

currentUrl.ToLower() + "\">" + withTooltip + "</a>";

}

result = RegExTerms.Replace(processedText, withTooltipAndLink);

}

return result;

}

C.4 The AddElementsHelp Method

The following code extract is the code of the AddElementsHelp method. The method is

implemented in the ContextHelpHelper.cs class and it ensures adding of help for HTML

elements, as explained in 5.2.4.

public static string AddElementsHelp(string sourceHtml, CMS.URLRewritingEngine.URLRewritingResultEnum currentStatus, string

currentCulture)

{

string processedText = String.Empty;

string processedHtml = String.Empty;

string currentUrl = UrlHelper.RemoveQuery(UrlHelper.CurrentURL);

string lowerUrl = currentUrl.ToLower();

ArrayList elements = (ArrayList)htElements[currentCulture + "|" + lowerUrl];

if (elements == null)

{

// load the custom table with terms to be highlighted into a DataTable

CustomTableItemProvider ctiProvider = new CustomTableItemProvider(CMSContext.CurrentUser);

DataSet ds = new DataSet();

if (currentStatus == CMS.URLRewritingEngine.URLRewritingResultEnum.SystemPage)

{

ds = ctiProvider.GetItems("customtable.ContextHelpElements", "UIPages=1 AND CultureCode='" + currentCulture + "'", null);

}

else

{

ds = ctiProvider.GetItems("customtable.ContextHelpElements", "LivePages=1 AND CultureCode='" + currentCulture + "'", null);

}

DataTable tableElements = ds.Tables[0];

// create an arraylist with rows of the Terms custom table

elements = new ArrayList();

for (int i = 0; i < tableElements.Rows.Count; i++)

{

DataRow row = tableElements.Rows[i];

string elementUrl = (string)row["PageURL"];

int resolveType = (int)row["UrlResolveType"];

bool livePages = (bool)row["LivePages"];

bool uiPages = (bool)row["UIPages"];

if ((elementUrl == String.Empty)||(ResolveHelpUrl(elementUrl, currentUrl, resolveType)))

{

elements.Add(row);

}

}

htElements[currentCulture + "|" + lowerUrl] = elements;

}

Regex RegExTags =

RegexHelper.GetRegex("<(?:/?(\\w+)(?:\\s+(\\w+)(?:\\s*=(?!\\s)((?:\"(?:[^\"]|\\\\\")*\")|(?:\'(?:[^\']|\\\\\')*\')|(?:[^\\s/>]|/(?!>))*)|(

?=[\\s/>])(?<3>)|(?<3>=)))*\\s*/?>|(?<1>!--))|(?<1>-->)");

processedHtml = sourceHtml;

foreach (DataRow dr in elements)

{

string id = dr["ElementID"].ToString();

int itemId = (int)dr["ItemID"];

string description = dr["ShortDescription"].ToString();

string helpIcon = (" <img style=\"border: none\" src=\"App_Themes/Default/Images/General/HelpSmall.png\"onmouseover=\"Tip('" +

description + "')\" onmouseout=\"UnTip('')\"></img>");

string helpIconLink = "<a target=\"_blank\" href=\"" +

UrlHelper.ResolveUrl("~/CMSGlobalFiles/ContextHelp/CustomHelp.aspx?elementId=") + itemId + "&culture=" + currentCulture + "&originalUrl="

+ lowerUrl + "\">" + helpIcon + "</a>";

MatchCollection tags = RegExTags.Matches(processedHtml);

StringBuilder sb = new StringBuilder();

int openCount = 0;

int counter = 0;

int currentIndex = 0;

bool isBody = false;

string lastOpen = String.Empty;

foreach (Match m in tags)

{

// append normal text before the tag

if (currentIndex < m.Index)

{

string substring = processedHtml.Substring(currentIndex, m.Index - currentIndex);

sb.Append(substring);

}

// append the tag

- 48 -

string tag = m.ToString();

bool endTag = tag.StartsWith("</");

bool selfClosed = tag.EndsWith("/>");

string forAppend = String.Empty;

string tagName = m.Groups[1].ToString();

string lowerTagName = tagName.ToLower();

// opening tags

if (!(endTag || selfClosed))

{

// performs if the tag has the required ID

if (lowerTagName == lastOpen)

{

openCount++;

}

else if (lowerTagName == "body")

{

isBody = true;

}

else

{

if (((tag.Contains("ID=\"" + id + "\"")) || (tag.Contains("id=\"" + id + "\""))) && (lastOpen == String.Empty) &&

isBody)

{

lastOpen = lowerTagName;

openCount = 0;

}

}

forAppend = tag;

}

// closing tags

else if (endTag)

{

if (lowerTagName == lastOpen)

{

if (openCount == 0)

{

forAppend = tag + helpIconLink;

lastOpen = String.Empty;

}

else

{

forAppend = tag;

openCount--;

}

}

else if ((lowerTagName == "body") && (lastOpen != String.Empty))

{

forAppend = helpIconLink + tag;

lastOpen = String.Empty;

isBody = false;

}

else

{

forAppend = tag;

}

}

// self-closing tags

else

{

if (((tag.Contains("ID=\"" + id + "\"")) || (tag.Contains("id=\"" + id + "\""))) && isBody)

{

forAppend = tag + helpIconLink;

}

else

{

forAppend = tag;

}

}

sb.Append(forAppend);

currentIndex = (m.Index + m.Length);

counter++;

}

// append text after last tag

if (processedHtml.Length > currentIndex)

{

string substring = processedHtml.Substring(currentIndex, processedHtml.Length - currentIndex);

sb.Append(substring);

}

processedHtml = sb.ToString();

}

// return processed Html

return processedHtml;

}

C.5 The ResolveHelpUrl Method

The following code extract is the code of the ResolveHelpUrl method. The method is

implemented in the ContextHelpHelper.cs class and it is used by both the AddTermsHelp and

the AddElementsHelp methods to determine if a term or HTML element should be searched

on pages with a particular URL, as explained in 5.2.5.

- 49 -

- 50 -

private static bool ResolveHelpUrl(string resolvedUrl, string currentUrl, int resolveType)

{

string urlForRegex = string.Empty;

Regex reUrl = null;

bool urlMatches = false;

switch (resolveType)

{

// Exact URL

case 0:

urlMatches = String.Equals(resolvedUrl, currentUrl);

break;

// Substring of URL

case 1:

urlForRegex = Regex.Escape(resolvedUrl);

reUrl = RegexHelper.GetRegex(urlForRegex);

urlMatches = reUrl.IsMatch(currentUrl);

break;

// RegEx

case 2:

urlForRegex = "^" + resolvedUrl + "$";

reUrl = RegexHelper.GetRegex(urlForRegex);

urlMatches = reUrl.IsMatch(currentUrl);

break;

// RegEx substring

case 3:

reUrl = RegexHelper.GetRegex(resolvedUrl);

urlMatches = reUrl.IsMatch(currentUrl);

break;

}

return urlMatches;

}

C.6 The ResolveCustomTopic Method

The following code extract is the code of the ResolveCustomTopic method. The method is

implemented in the ContextHelpHelper.cs class and it works as a helper method and it is used

to modify help icon links in case that there is a custom context help topic defined for the

current page of the user interface. More details about the method can be found in 5.3.

public static string ResolveCustomTopic(string TopicName, string DocumentationUrl)

{

string currentCulture = CultureHelper.GetPreferredUICulture();

if (!htIsCustomTopic.ContainsKey(currentCulture + "|" + TopicName))

{

CustomTableItemProvider ctiProvider = new CustomTableItemProvider(CMSContext.CurrentUser);

DataSet ds = ctiProvider.GetItems("customtable.ContextHelpTopics", "TopicName = '" + TopicName.Replace("\'", "\''") + "' AND

CultureCode='" + currentCulture + "'", null);

if (!DataHelper.DataSourceIsEmpty(ds))

{

DataRow topicRow = ds.Tables[0].Rows[0];

htTopics[currentCulture + "|" + TopicName] = topicRow;

htIsCustomTopic[currentCulture + "|" + TopicName] = true;

}

else

{

htIsCustomTopic[currentCulture + "|" + TopicName] = false;

}

}

bool isCustomTopic = (bool)htIsCustomTopic[currentCulture + "|" + TopicName];

if (isCustomTopic == true)

{

return (UrlHelper.ResolveUrl("~/CMSGlobalFiles/ContextHelp/CustomHelp.aspx?topic=") + TopicName + "&culture=" + currentCulture);

}

else

{

return (DocumentationUrl + TopicName + ".htm");

}

}

C.7 The CustomHelp.aspx Page

The following code extract is the code of the CustomHelp.aspx page. The page is used to

display detailed help for terms and HTML elements, as well as text of custom context help

topics. More details can be found in 5.4.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="CustomHelp.aspx.cs" Inherits="CMSGlobalFiles_ContextHelp_CustomHelp"

Theme="Default" MasterPageFile="~/CMSMasterPages/UI/Dialogs/ModalDialogPage.master" Title="Custom help topic" %>

<asp:Content ID="Content1" ContentPlaceHolderID="plcContent" runat="server">

<div style="margin-left: 15px; margin-top: 15px">

<asp:Literal ID="Literal1" runat="server"></asp:Literal>

</div>

</asp:Content>

- 51 -

C.8 The PageLoad Method from the CustomHelp.aspx.cs Code Behind File

The following code extract is the PageLoad method from the code behind of the

CustomHelp.aspx page. The page is used to display detailed help for terms and HTML

elements, as well as text of custom context help topics. More details can be found in 5.4.

protected void Page_Load(object sender, EventArgs e)

{

string text = string.Empty;

// display help for custom topics

if (QueryHelper.Contains("topic"))

{

string culture = QueryHelper.GetString("culture", "culture_not_found");

string topicName = QueryHelper.GetString("topic", "topic_not_found");

this.Page.Title = "Custom Context Help Topic - " + topicName;

CurrentMaster.Title.TitleText = "Custom Context Help Topic - " + topicName;

CurrentMaster.Title.TitleImage = GetImageUrl("General/HelpLarge.png");

DataRow dr = (DataRow)ContextHelpHelper.htTopics[culture + "|" + topicName];

if (!DataHelper.DataSourceIsEmpty(dr))

{

text = (string)dr["TopicText"].ToString();

}

}

// display help for element

else if (QueryHelper.Contains("elementId"))

{

string culture = QueryHelper.GetString("culture", "culture_not_found");

int itemId = QueryHelper.GetInteger("elementId", 0);

string url = QueryHelper.GetString("originalUrl", "element_not_found");

ArrayList elements = (ArrayList)CMS.ContextHelp.ContextHelpHelper.htElements[culture + "|" + url];

if (elements != null)

{

foreach (DataRow dr in elements)

{

if ((int)dr["ItemID"] == itemId)

{

string elementId = (string)dr["ElementID"];

this.Page.Title = "Detailed description of a UI element - " + elementId;

CurrentMaster.Title.TitleText = "Detailed description of a UI element - " + elementId;

CurrentMaster.Title.TitleImage = GetImageUrl("General/HelpLarge.png");

text = dr["LongDescription"].ToString();

}

}

}

}

// display help for term

else if (QueryHelper.Contains("termId"))

{

this.Page.Title = "Detailed description of term";

string culture = QueryHelper.GetString("culture", "culture_not_found");

int termId = QueryHelper.GetInteger("termId", 0);

string url = QueryHelper.GetString("originalUrl", "element_not_found");

ArrayList terms = (ArrayList)CMS.ContextHelp.ContextHelpHelper.htTerms[culture + "|" + url];

if (terms != null)

{

foreach (DataRow dr in terms)

{

if ((int)dr["ItemID"] == termId)

{

string termExpression = (string)dr["TermExpression"];

this.Page.Title = "Detailed description of a term - " + termExpression;

CurrentMaster.Title.TitleText = "Detailed description of a term - " + termExpression;

CurrentMaster.Title.TitleImage = GetImageUrl("General/HelpLarge.png");

text = dr["LongDescription"].ToString();

}

}

}

}

else

{

text = "Invalid access - no help subject specified in querystring.";

}

Literal1.Text = text;

}

- 52 -

D. Installation Instructions

The following steps need to be taken in order to add the module to an existing Kentico CMS

5.0 project:

1. Unzip the contents of the ContextHelpModule.zip package into the root of your web

project folder (e.g. c:\inetpub\wwwroot\KenticoCMS\). The folder structure within the ZIP

package reflects the structure of the web project folder, so that files will be copied to the

appropriate folders.

2. When extracting, confirm overwriting of the original Help.ascx and Help.ascx.cs files

with the ones from the package. The actual ContextHelp_Import.zip import package will

be copied to ~\CMSSiteUtils\Imports, which will ensure that it will be offered in the

packages list in step 4.

3. Log in to the Kentico CMS user interface using the administrator's account. Go to Site

Manger -> Sites and choose Import site or objects.

4. In Step 1 of the import wizard, choose the ContextHelp_Import.zip package that will be

offered in the Import packages list. Choose the Preselect all items option and click Next.

5. Go through the rest of the wizard until the import finishes. Once the package is imported,

restart your web application and you may start using the module.

E. Attached CD Medium

The CD medium attached with this thesis contains the module’s installation package

(ContextHelpModule.zip), an electronic printable version of this thesis (thesis.pdf) and off-line

versions of referenced literature and resources (the Literature folder).