Chapter 12. An Example Theme

12.1. Image-Free Theme

12.1. Image-Free Theme

This section demonstrates the creation of a theme that is based on a 960-grid, uses no images, yet provides several regions and otherwise participates fully in Perforce Chronicle operations. To create the required components, perform the following steps. For further details about specific topics, refer to the linked documentation.

  1. Create a skeletal theme structure in the folder sites/all/themes:

    imagefree/
        layouts/
        styles/
        views/
            content/
                index/
    
  2. Create the imagefree/theme.ini theme definition file:

    title                       = Image-Free
    version                     = 1.0
    description                 = A theme without images.
    tags                        = example, no-image
    
    [maintainer]
    name                        = Perforce Software
    email                       = support@perforce.com
    url                         = http://www.perforce.com/
    
    [stylesheets]
    all.href                    = styles/styles.css
    
    [menus]
    footer.home.label           = Home
    footer.home.module          = content
    footer.home.controller      = index
    footer.home.action          = index
    footer.home.class           = home
    footer.home.order           = 0
    footer.home.test            = true
    
    footer.login.handler        = user.login-logout
    footer.login.order          = 90
    
    [regions]
    header.1.title              = Site Title
    header.1.type               = widget/text
    header.1.class              = site-title
    header.1.config.text        = The Image-Free Theme
    
    feature.1.title             = Feature Image
    feature.1.type              = widget/image
    feature.1.class             = feature-image
    
    feature.2.title             = Feature
    feature.2.type              = widget/text
    feature.2.class             = feature-text
    feature.2.showTitle         = 1
    feature.2.config.text       = "
    The text for the feature should be added here.<br/><br/>
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce congue
    nunc a velit fermentum in tempor diam lacinia. Pellentesque tristique
    dui eget nibh lobortis congue. Maecenas eu bibendum erat. Aliquam
    varius tempor fermentum.
    "
    
    important.1.title           = Important #1
    important.1.type            = widget/text
    important.1.class           = three-column
    important.1.showTitle       = 1
    important.1.config.text     = "
    An important item.<br/><br/>
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce congue
    nunc a velit fermentum in tempor diam lacinia. Pellentesque tristique
    dui eget nibh lobortis congue. Maecenas eu bibendum erat. Aliquam
    varius tempor fermentum.
    "
    
    important.2.title           = Important #2
    important.2.type            = widget/text
    important.2.class           = three-column
    important.2.showTitle       = 1
    important.2.config.text     = "
    An important item.<br/><br/>
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce congue
    nunc a velit fermentum in tempor diam lacinia. Pellentesque tristique
    dui eget nibh lobortis congue. Maecenas eu bibendum erat. Aliquam
    varius tempor fermentum.
    "
    
    important.3.title           = Important #3
    important.3.type            = widget/text
    important.3.class           = three-column
    important.3.showTitle       = 1
    important.3.config.text     = "
    An important item.<br/><br/>
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce congue
    nunc a velit fermentum in tempor diam lacinia. Pellentesque tristique
    dui eget nibh lobortis congue. Maecenas eu bibendum erat. Aliquam
    varius tempor fermentum.
    "
    

    The first eight lines of this file specify the theme's version, provide a description, list the tags used for filtering themes, and identify the maintainer of the theme.

    The [stylesheets] section includes the CSS stylesheet styles/styles.css in the generated HTML to ensure that the theme is styled correctly.

    The [menus] section specifies the default entries for a menu that is presented in the theme's footer. The footer is identified as footer, and contains two entries: one is a link to the home page and is labelled Home, and the second is a dynamic link that is labelled Login or Logout depending on the user's current authentication state. The Login link specifies an order of 90 to place the link after any other menu items that may be added in the future.

    The [regions] section specifies three logical areas that can be included on pages, identified as header, feature, and important respectively. The configuration for each of these regions specifies the widgets that should be included by default: a text widget labelled Site Title in the header region, an image widget labelled Feature Image and a text widget labelled Feature in the feature region, and three text widgets in the important region with appropriately numbered labels.

    Note how the text widgets define the default text in each case. This provides default content for the widgets to demonstrate the styles in effect.

    At this point, the theme is listed on the Manage Themes page, although it doesn't do anything yet.

    For details about theme configuration details, see Section 11.1, “Configuration File - theme.ini.

  3. Create the imagefree/layouts/default-layout.phtml view script:

    <?= $this->doctype() ?>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <?= $this->headTitle() ?>
    <?= $this->dojo() ?>
    <?= $this->headScript() ?>
    <?= $this->headLink() ?>
    <?= $this->headStyle() ?>
    </head>
    
    <body class="claro
     <?=$this->layout()->getLayout()?>
     <?=$this->request()->getModuleName()?>-module
     <?=$this->request()->getControllerName()?>-controller
     <?=$this->request()->getActionName()?>-action">
    <?=$this->toolbar()?>
    <?=$this->notifications()?>
    
    <div id="header"><div class="container">
    <?= $this->region('header') ?>
    </div></div>
    
    <div id="nav"><div class="container">
    <?= $this->menu('primary', array('maxDepth' => 0)); ?>
    </div></div>
    
    <div id="main"><div class="container">
    <?= $this->layout()->content ?><br class="clear" />
    </div></div>
    
    <div id="footer"><div class="container">
    <?  if (P4Cms_Menu::exists('footer')):
            $menu = P4Cms_Menu::fetch('footer');
            echo $this->menu()->renderMenu(
                $menu->getExpandedContainer(), array('maxDepth' => 0)
            );
        endif;
    ?></div></div>
    
    </body></html>
    

    default-layout.phtml is a view script. It defines the overall structure for pages using this layout.

    Within the layout file are PHP commands, which are surrounded by <? and ?> tag markers. The tag marker <?= is a shortcut that emits the value of the PHP variable or command within the tag.

    The first 18 lines are common to most themes. They setup the markup to use the correct document type, provide a page title, includes the Dojo Toolkit, any required Javascript and CSS files, plus any required link tags. The body tag provides a number of CSS classes to assist in customizing the presentation for any activity. Finally, the Chronicle toolbar and notifications facilities are included.

    [Warning] Warning:
    If lines 17 and 18 are removed or damaged, interaction with the Chronicle management interface could be significantly compromised.

    The remaining lines are organized into groups which provide the markup respectively for the header, top navigation, page content, and footer. The header region and all of its widgets are generated on line 21. The top navigation is provided by lines 24-31. Note the PHP commands that test for the existence of the menu, which is an important consideration when menus can be removed through the management interface. The page content is provided by line 34. The footer navigation is provided by lines 37-44, using code similar to the top navigation.

    For more details about layouts, see Section 11.3, “Layouts”, or about view scripts, see Section 11.4, “View Scripts”.

  4. Create the imagefree/views/content/index/index.phtml view script:

    <?= $this->region('feature') ?>
    
    <?= $this->region('important') ?>
    

    index.phtml is a view script. It provides the default markup for the home page of your site. The PHP code renders the two regions feature and important, including the widgets defined in the theme.ini presented in step 2.

    For more details about view scripts, see Section 11.4, “View Scripts”.

  5. Create the imagefree/views/content/index/view.phtml view script:

    <div class="three-column-2">
    <?= $this->contentEntry($this->entry, $this->entryOptions) ?>
    </div>
    
    <div class="three-column">
    <?= $this->region('sidebar') ?>
    </div>
    

    view.phtml is a view script. It provides the default markup for content. The first three lines render the content entry. The last three lines render a region named sidebar.

    For more details about view scripts, see Section 11.4, “View Scripts”.

  6. Create the imagefree/styles/styles.css CSS file:

    body {
        background-color: #f4f2f3;
        font-family: Arial, Helvetica, sans-serif !important;
        font-size: 14px;
        color: #3d3d3d;
        margin: 0;
        padding: 0;
    }
    
    * {
        margin: 0;
        padding: 0;
    }
    
    img {
        border: none;
        margin: 0;
        padding: 0;
        vertical-align: text-bottom;
    }
    
    a {
        color: #2753a2;
    }
    a:hover {
        color: black;
    }
    
    p,
    .content-element-body {
        font-size: 14px;
        line-height: 19px;
        color: #3d3d3d;
        padding: 4px 0 6px 0;
    }
    
    h1, h2, h3, h4, h5 {
        padding: 6px 0 5px 0;
    }
    
    .content-element, .content-entry {
        margin: 0;
        padding: 0;
    }
    .content-element-title,
    .content-entry-type-basic-page .content-element-title {
        font-size: 21px;
        line-height: 19px;
        padding: 6px 0 9px 0;
        font-weight: bold;
        color: #3d3d3d;
        margin: 0;
    }
    
    .clear {
        clear: both;
    }
    
    /* Container Styles
    ------------------------------------------------*/
    
    #header {
        background: #4e5661;
        height: 88px;
    }
    
    #nav {
        background-color: #404852;
        height: 31px;
    }
    
    #main {
        padding: 10px 0;
    }
    
    #footer {
        clear: both;
        background: #404852;
        font-size: 12px;
        margin-top: 10px;
        height: 29px;
    }
    
    .container {
        margin: 0 auto;
        width: 960px;
    }
    
    /* Styles
    ------------------------------------------------*/
    
    .logo {
        padding: 25px 0 0 10px;
    }
    
    /* Nav */
    
    ul.navigation {
        list-style: none;
        padding: 5px 0 0 0;
    }
    
    ul.navigation li {
        float: left;
        padding: 0;
        font-size: 14px;
    }
    #footer ul.navigation li {
        font-size: 12px;
    }
    
    ul.navigation li a {
        color: white;
        text-decoration: none;
        padding: 7px 10px;
    }
    
    ul.navigation li a:hover {
        background: #2f353c;
    }
    
    /* Column Styles */
    
    .one-column {
        float: left;
        padding: 5px 10px;
        margin: 5px 0;
        width: 940px;
    }
    
    .two-column,
    .two-column.dijitContentPane {
        float: left;
        padding: 5px 10px;
        margin: 5px 0;
        width: 460px;
    }
    
    .three-column,
    .three-column.dijitContentPane {
        float: left;
        padding: 5px 10px;
        margin: 5px 0;
        width: 300px;
    }
    
    .three-column-2,   /* 2 columns wide - using 3 column measurements */
    .three-column-2.dijitContentPane {
        float: left;
        padding: 5px 10px;
        margin: 5px 0;
        width: 620px;
    }
    
    .four-column,
    .four-column.dijitContentPane {
        float: left;
        padding: 5px 10px;
        margin: 5px 0;
        width: 220px;
    }
    
    .four-column-3,   /* 3 columns wide - using 4 column measurements */
    .four-column-3.dijitContentPane {
        float: left;
        padding: 5px 10px;
        margin: 5px 0;
        width: 700px;
    }
    
    /* Other Page Styles */
    
    hr {
        clear: both;
        background: #cfcfd1;
        border: none;
        display: block;
        margin: 0;
        padding: 15px 0;
        height: 1px;
        font-size: inherit;
    }
    
    .callout {
        background: white;
    }
    
    ul {
        list-style: outside;
        padding: 5px 0 7px 15px;
    }
    
    ul.links {
        list-style: none inside;
        padding: 5px 0 7px 0;
    }
    
    ul li {
        padding: 2px 0 4px 0;
    }
    
    /* Regions & Widgets */
    
    #region-feature,
    #region-important {
        overflow: hidden;
        float: left;
        width: 960px;
    }
    #region-feature {
        border-bottom: 1px solid #cfcfd1;
        margin-bottom: 10px;
        padding-bottom: 9px;
    }
    
    #region-header .widget-container {
        float: left;
        padding: 25px 0 0 10px;
        overflow: inherit;
    }
    
    #region-header .site-title {
        float: left;
        color: #e4e4e4;
        font-size: 24px;
        font-weight: bold;
        padding-top: 30px;
    }
    #region-header .layout-title .widget-content {
        text-align: right;
    }
    
    #region-feature .feature-image {
        float: left;
        min-width: 460px;
        min-height: 100px;
    }
    #region-feature .feature-image .widget-content {
        text-align: right;
    }
    
    #region-feature .widget-title,
    #region-important .widget-title {
        color: #3d3d3d;
        padding: 4px 0 8px 0;
        font-size: 19px;
        font-weight: bold;
        line-height: 19px;
    }
    
    #region-feature .widget-widget-text,
    #region-important .widget-widget-text,
    #region-sidebar .widget-content {
        color: #3d3d3d;
        font-size: 14px;
        line-height: 19px;
        padding: 0;
    }
    

    These CSS classes are inserted into your theme's output by Chronicle due to the [stylesheets] section on lines 10-11 of imagefree/theme.ini above.

    These styles make it fairly easy to construct one to four column layouts based on a 960 pixel grid, similar to the 960 Grid System.

    For more details about resources, see Section 11.2, “Resources”.

  7. Try the new theme!

    You now have a functional theme that you can enable in Chronicle by performing the following steps:

    1. Log into your instance of Chronicle.
    2. To enable the imagefree theme, follow the instructions in Section 19.1, “Applying Themes”.
    3. Click Back to Website.

    Congratulations! You have successfully created your first theme for Chronicle.

Perforce Chronicle - Release: 2012.2/486814