Theming Bedework
Documentation In Progress
This chapter of the Bedework 3.8 Documentation is in the process of being updated.
Overview
This section is a resource for web designers who would like to customize the look and layout of the Bedework calendar web clients. No programming experience is assumed, though a basic understanding of how web applications work is helpful.
Themes
A generic theme is provided with each web application in the quickstart release. The public client's MainCampus calendar suite comes with a number of themes to get you started. Fonts, colors, and most layout specifics are defined with CSS.
MainCampus skin
Examples of how members of the Bedework community have implemented themes can be viewed by selecting from our listing on the Bedework website, “Who's using Bedework?”: http://www.bedework.org/bedework/update.do?artcenterkey=35
Examples:
Theming Prerequisites
Changing headers, footers, colors, and fonts can be accomplished with an understanding of XHTML and CSS. Changing global layout or presentation behavior requires an understanding of XML and XSL (xslt and xpath, in particular).
Because the calendar front-end uses XSLT to transform XML, you must use valid XML markup for all templates. Skins that produce HTML must be written using XHTML (regardless of the final output). Skins without valid markup will fail to transform.
Definitions
- Theme: a collection of XSL, CSS, image, javascript, and other resources used to deliver the look, feel, and functionality of a Bedework xml-based web client.
- Skin: a single XSL file, or a group of XSL files included into a master XSL file.
Location of the Theme Directories
In the quickstart directory, the theme files for the xml-based web applications are found in the following directories:
bedework/deployment/webpublic/webapp/resources/ bedework/deployment/webuser/webapp/resources/ bedework/deployment/webadmin/webapp/resources/ bedework/deployment/websubmit/webapp/resources/ bedework/deployment/feeder/webapp/resources/
If you rebuild the application (you will want to do this to create a production release), the skins are copied into:
jboss-5.1.0.GA/server/default/deploy/ROOT.war/calrsrc.MainCampus [jboss-5.1.0.GA/server/default/deploy/ROOT.war/calrsrc.OtherCalSuite] jboss-5.1.0.GA/server/default/deploy/ROOT.war/ucalrsrc and jboss-5.1.0.GA/server/default/deploy/ROOT.war/caladminrsrc and jboss-5.1.0.GA/server/default/deploy/ROOT.war/eventsubmitrsrc and jboss-5.1.0.GA/server/default/deploy/ROOT.war/calfeedrsrc.MainCampus
The quickstart distribution comes with the themes already in place and ready to use.
Editing, Building, and Avoiding SSL Mixed Content
Once deployed (as they are in the quickstart), the skins can be manipulated directly inside the JBoss ROOT.war directory for quickest development; be aware however that on a rebuild the source files will overwrite the JBoss files, so it is safest to edit in the source folder and copy files into the JBoss directories as you go. You may also choose to place your theme files on a separate web server. (Note: the destination folder into which the theme files are copied during a build is defined by the ...resources.dir property in the cal.properties config file.)
The locations of the theme directories are defined in the file
bedework/config/bwbuild/<target>/cal.options.xml
which should be copied to your user home directory or to another location as described in Configuring Bedework.
For each web client, the <appRoot> is where the server will find the xsl files that transform Bedework's XML, and the <browserResourceRoot> is where the browser will request css, images, javascript, and other resources. In the quickstart, these values are the same for each client and point to http://localhost:8080/_resourcesdir_.
In production, however, the <browserResourceRoot> must be served over https for secure web sites to avoid mixed content errors. To build a production release, change the values of <appRoot> and < browserResourceRoot> to the name of the server hosting the resources, and add https: to the <browserResourceRoot> for those web clients you will provide over SSL (e.g. personal, submissions, and admin web clients).
.
The <appRoot> takes the following value:
http://a-web-server-path/to/your/template/directory/
which for the quickstart is
http://localhost:8080/calrsrc/ and http://localhost:8080/ucalrsrc/ and http://localhost:8080/caladminrsrc/ and http://localhost:8080/eventsubmitrsrc/ and http://localhost:8080/calfeedrsrc/
The appRoot is modified at run time for portals and calendar suites. If we are running under a portal the approot has .portalPlatform appended. For example, if the portal platform is uPortal2 the user client appRoot defined above becomes
appRoot = http://localhost:8080/ucalrsrc.uPortal2
In addition, we append the calendar suite name for public clients (all calendar suites and the feeder application). So if the calendar suite is MainCampus we have
appRoot = http://localhost:8080/ucalrsrc.MainCampus
or for the portlet
appRoot = http://localhost:8080/ucalrsrc.uPortal2.MainCampus
Structure of the Theme Directories
The public web client appRoot directories have the following structure:
appRoot/ default/ (default locale) strings.xsl (language text for default locale) default/ (default browser type) default.xsl (references globals, strings, and theme index) globals.xsl (global variables) other skins (can be called dynamically) PDA/ (mobile browser type) default.xsl (references iphone theme) globals.xsl (global variables) themes/ nameTheme/ (resources for a specific theme) *.xsl (xsl template files) css/ (css files) images/ (css files) javascript/ (css files)
The personal, admin, and submissions web clients use a slightly different structure for resource files and language strings. All templates in these clients are found in the default.xsl file for a particular skin. These will be refactored in upcoming releases to match the current structure of the public clients. Behaviors are otherwise the same among all the xsl clients.
Stylesheet discovery
When a Bedework web application is requested, the server goes through a process of stylesheet discovery in three steps: selecting the locale, selecting the browser type, and finally selecting the skin.
Locale selection
The top-level directories of the appRoot define locales. The default locale is default. You may add directories here using a locale name such as en_US or fr_CA. Browsers provide Bedework with a locale; if a directory is found with a name that matches the locale provided by the browser, Bedework will use the skins found there. Otherwise, the default locale directory will be used.
For a locale to be supported by Bedework it must be included in the list of supported locales in the Admin Client. For example, if you wish to support fr_CA, visit http://localhost:8080/caladmin → System tab → Manage system preferences, and add fr_CA to the list of supported locales.
Browser type selection
The next level down defines the browser type. Bedework looks first for a folder whose name is associated with the user-agent of the visiting browser. If found, Bedework will use that folder to deliver the skin. If not found, Bedework will use the default directory seen here. Currently, the acceptable folder names are:
- default
- Netscape4
- MSIE, Opera
- Mozilla
- PDA.
Bedework can be forced to use a specific browser type and skin and can have multiple skins per browser type. See Actions & Parameters for more information about this.
This code is somewhat archaic, and PDA user-agent sniffing is out-of-date; to use the PDA directory found in the quickstart release, you can explicitly request it by adding the request parameter browserTypeSticky=PDA. browserTypeSticky=default will reset this to the default path.
Skin selection
Once the locale and browser type paths have been selected, the server will select the xsl skin used for transforming Bedework's XML. If no skin is explicitly requested, the server will fall back to default.xsl. A skin can be directly requested using the request parameter skinName=someskin or skinNameSticky=someskin. See Actions & Parameters for more information about this.
In the public client, the default.xsl skin includes the global.xsl file for global variables, the strings.xsl file for internationalized language strings, and the root xsl file of the theme that will be used by default. Here is the example from default.xsl of the MainCampus calendar suite:
<!- DEFINE INCLUDES -> <xsl:include href="./globals.xsl" /> <xsl:include href="../strings.xsl" /> <!- DEFAULT THEME NAME -> <!- to change the default theme, change this include -> <xsl:include href="../../themes/bedeworkTheme/bedework.xsl" />
In the personal, submissions, and admin client, default.xsl includes strings.xsl. The rest of the xsl logic is self-contained.
Skins are only loaded at first reference and are then cached. The skins can be explicitly flushed using the refreshXslt=yes query parameter (see Actions and Parameters below). Most themes shipped with Bedework have a Refresh XSLT link in the footer of the web client. (You will probably want to disable this link prior to production.)
The discovered 'real' path is cached with the 'idealized' path as the key so that subsequent lookups for the same path will proceed without the discovery phase.
Internationalization
As a first step towards internationalizing Bedework, nearly all English strings have been pulled from the xsl templates that produce the personal, public, admin, and submission web clients.
The public client locale directories contain two files, strings.xsl and localeSettings.xsl. These two files contain the replacement text and settings for the language associated with the current locale. The themes reference the current locale's strings and localeSettings files. The strings should be translated to the default language you wish to use for your site. If you wish to support other languages in the same client, create a locale directory and place a translated strings and localeSettings files into it.
For example:
appRoot/ default/ (default locale) strings.xsl (language text for default locale) localeSettings.xsl(internationalization settings) default/ default.xsl globals.xsl fr_CA/ (locale for French, Canadian) strings.xsl (language text for fr_CA locale) localeSettings.xsl(internationalization settings) default/ default.xsl themes/
Each default.xsl includes the strings file from its locale directory. Each otherwise includes default/default/globals.xsl file and the theme of its choice. Here is an example of what the fr_CA default.xsl would look like for the MainCampus calendar suite:
<!-- DEFINE INCLUDES --> <xsl:include href="../../default/default/globals.xsl" /> <xsl:include href="../localeSettings.xsl" /> <xsl:include href="../strings.xsl" /> <!-- DEFAULT THEME NAME --> <!-- to change the default theme, change this include --> <xsl:include href="../../themes/bedeworkTheme/bedework.xsl" />
Caveats
In the Administration and Personal web clients, there are a handful of English strings that have yet to be pulled from the xsl template. Also, there are a few English strings that are written out by Javascript routines that reside in bedework-common/javascript. Those routines have not been prepared for translation yet.
Making Stylistic Changes – the Public Client Themes
The public themes consist of a collection of xsl skins that contain a series of xsl templates. The theme directories are found in
bedework/deployment/webpublic/webapp/resources/demoskins/CalSuiteName/themes
In the MainCampus/themes directory, you'll find Bedework default theme bedeworkTheme. The root xsl file is called bedework.xsl. Likewise, in the iphoneTheme, the root xsl file is called iphone.xsl.
In each theme directory, you will also find a themeSettings.xsl file in which the resourcesRoot variable is defined. resourcesRoot is used throughout the xsl documents to reference css, images, and javascript.
If you have a good grasp of XHTML and CSS, you can modify the graphics, colors, and general feel of a skin by editing one of the examples and copying the changes into its associated resources directory in JBoss. Skins are cached in memory, so to update a skin you must refresh the stylesheet by appending your query string with refreshXslt=somestring. For example:
http://localhost:8080/cal/setup.do?refreshXslt=yes -or- http://localhost:8080/cal/event/eventView.do?eventId=2&refreshXslt=yes
Working with the bedeworkTheme
Bedework's default theme is based on work at Duke and Yale Universities. The theme includes a number of features that can be configured in themeSettings.xsl. These include:
- Ongoing events: you can specify a category to mark events as ongoing, and display these events in a separate listing. By default, the category “Ongoing” (as shipped with the quickstart's default data) is used to mark ongoing events.
- Featured events: the three graphics at the top of the default theme are “featured events”. The images and links used are defined in bedeworkTheme/featured/FeaturedEvent.xml. If you choose to use featured events, you must (for now) maintain this xml file outside the Bedework system (either manually or using an outside process to write the xml file).
- Configurable event icons: the icons used to download or share events can be enabled and disabled by editing the themeSettings.xsl.
- Configurable header, footer, left-sidebar links, and favicon: all can be defined in the themeSettings.xsl file. By editing this file and manipulating the CSS found in css/bwTheme.css, it is possible to create a highly customized instance of Bedework without having to dig deeper into the xsl code.
Setting event colors in the Public Web Client
Events can be colored by category in the public web client if you choose. This is currently accomplished by customizing a template in the stylesheet.
For example, to color events in the calendar grid of the bwclassicTheme, search for the template that looks like this (approx. line 170 of themes/bwclassicTheme/eventGrids.xsl):
<xsl:template match="categories" mode="customEventColor"> <!-- Set custom color schemes here. --> <xsl:choose> <!-- <xsl:when test="category/value = 'Athletics'">bwltpurple</xsl:when> <xsl:when test="category/value = 'Arts'">bwltsalmon</xsl:when> --> <xsl:otherwise></xsl:otherwise> <!-- do nothing --> </xsl:choose> </xsl:template>
Uncomment the category tests and add your own logic for setting the event colors. The values such as bwltpurple are css classes that will be applied to each event in the grid or list, and are found in bedework/deployment/resources/xsl/default/default/subColors.css
This file gets deployed to the bedework-common directory and is referenced by the public web client.
You can use this approach to color events in other ways or use your own custom classes.
Making Stylistic Changes – the Personal, Admin, and Submissions Clients
In future versions of Bedework, we will refactor the personal, admin, and submissions clients to use the same structure as the public themes. For now, theming for these clients involves modifying the appRoot/default/default/default.xsl files and default.css files.
Actions & Parameters
What are Actions & Parameters?
Typical of web applications, Bedework receives HTTP requests and returns responses based on the page or action requested and the parameters sent in the query string. Look at the following URL:
http://localhost:8080/cal/main/setViewPeriod.do?b=de&viewType=weekView&date=20091121
Bedework is built in the Apache Struts MVC framework, and as such does not reference "web pages" through URLs directly. setViewPeriod.do in the URL above calls a Java "action" that returns a response based on the query string "date=20101121". This URL tells the personal calendar to set the current view to November 21, 2010.
Parameters can be strung together with ?'s and &'s on a query string like so:
http://hostname:port/context/action?param1=value¶m2=value
Normal Actions & Render Actions
Request processing in Bedework is divided into two parts: a normal action that may change the state of the application, and a render action that returns the resulting state for display. This is required, among other things, for Bedework to run as a portlet.
For each normal action that is called, Bedework will automatically redirect to the appropriate render action. Normal actions take a .do extension. Render actions have an .rdo extension.
As the developer of a skin, you will be primarily concerned with normal actions, and it is these that will be presented in the XSL stylesheets for users to click. All actions and parameters described below are normal actions.
Bedework Actions & Parameters in Detail
All actions used by the Bedework web clients are defined in the client's struts-config.xml file. For example, the public and personal web clients are described in
bedework/projects/webapps/webclient/war/WEB-INF/struts-config.xml
and all actions used by the Bedework admin web client are described in
bedework/projects/webapps/webadmin/war/WEB-INF/struts-config.xml
For detailed information about all actions and parameters used in Bedework, please see the API reference found from the Bedework Wiki.
Bedework Skin Parameters
The following parameters provide control over stylesheets. They can be added to any Bedework URL and combined with any other parameter.
setappvar
setappvar=key(value) - Pass a key/value pair into the XML output.
- Use for passing a parameter between pages, much like in other frameworks,
- Pass as many appvars as you need
- Change the value of an appvar by sending the same key with a different value.
- Note: appvars, once set, persist through a user session
skinName, skinNameSticky
skinName=name - Set the skin to name during for the request
skinNameSticky=name - Set the skin to name for the rest of the session (or until another skin is called).
where name is the file name of an XSLT document at the bottom of the locale/browserType path, leaving off the .xsl extension.For example:
appRoot/ default/ (locale) default/ (browserType) default.xsl shiny.xsl cleanXml.xsl themes/
If skinName is unspecified, Bedework uses the default skin. The URL to select "shiny.xsl" might look like this: http://hostname/cal/setup.do?skinNameSticky=shiny
http://hostname/cal/setup.do?skinNameSticky=shiny
browserType, browserTypeSticky
browserType=default, MSIE, Netscape, Netscape4, Mozilla, PDA, other - Set browser folder during request
browserTypeSticky=default, MSIE, ... - Set browser folder for the remainder of the session (or until another browserType is called).
For example:
appRoot default/ default/ default.xsl Mozilla/ default.xsl PDA/ default.xsl themes/
If unspecified, Bedework uses the folder that most closely matches the user-agent of the requesting browser. If not found, the "default" folder will be used. The example above would use the Mozilla folder for an incoming Mozilla browser. You may also create your own folder and call it explicitly, though Bedework cannot automatically associate it with a user-agent.
refreshXslt=anystring
XSL skins are cached once per user session to improve performance. If you make a change to your skin, you need to pass this parameter to reload it. anystring can be any value; we typically set it to yes. Example:
update.do?catcenterkey=12&skinName=shiny&refreshXslt=yes
noxslt=anystring
This parameter turns off the XSLT filter and returns raw xml in the response. You can look at the xml by selecting "view source" from your browser. This feature is very important when designing skins because it allows you to reference the exact XML you are trying to transform. anystring can be any value; we typically set it to yes. Example:
update.do?catcenterkey=12&noxslt=yes
XML
Bedework XML Structure
In Bedework, you can effectively look at the XML in two ways:
First way: add noxslt=yes parameter
In a user client (guest or personal) append noxslt=yes to the query string and view the page source. For example:
http://localhost:8080/cal/setup.do?noxslt=yes
There is a link in the footer of each web client that reads “show XML” which adds this parameter to the query string for the current page. When manipulating the XSLT, this is the easiest way to understand the underlying XML that is being transformed.
Second way: examine the source (JSP)
Look at the JSP pages which produce the XML output. These can be found in:
bedework/projects/webapps/client/war/docs
where client is webclient, webadmin, websubmit, or feeder.
Each “page” of an XML response takes the following form:
<bedework> [header data/variables and urlPrefixes for building links] <page>pageName</page> [page specific XML - changes from page to page] [footer data/variables (if any)] </bedework>
In most cases, the skins look first at the pageName found in the incoming XML and branch to an appropriate XSL template based on that. Look to the default template (the first in the stylesheets, matching on “/”) to see a listing of all incoming “pages” and their associated XSL templates. For example of this branching, look in
/bedework/deployment/webpublic/webapp/resources/demoskins/MainCampus/themes/bedeworkTheme/bedework.xsl
Bedework XSLT
Bedework uses Apache Xalan as its XSLT processor, and processes XSLT version 1.0 and Xpath version 1.0. Bedework uses the standard Xalan libraries without extensions. The XSLT language is reasonably simple, and if you are familiar with basic programming or scripting, you will have little difficulty reading it.
The key to understanding how the transformations take place, however, is to look at the underlying XML (by switching off the transform in Bedework using the “noxslt=yes” parameter and viewing the page source) and recognizing how XPath expressions are used to locate the xml nodes for transformation.
As noted above, a good place to begin understanding how the XML is transformed is
/bedework/deployment/webpublic/webapp/resources/demoskins/MainCampus/themes/bedeworkTheme/bedework.xsl
XSLT References
XSLT & XPath Quick Reference (PDF): http://www.mulberrytech.com/quickref/XSLT_1quickref-v2.pdf
XPath Specification: http://www.w3c.org/TR/xpath
XSLT Specification: http://www.w3c.org/Style/XSL/
Bedework Enterprise Calendar, version 3.9