Adding Formatting

A typical deployment of web formatting involves adding class attributes to elements and then developing an external CSS file that specifies the formatting for each such attribute. In this lesson, you’ll learn how to apply class names to Handlebars files, and also learn how to generate CSS files using Less.

Step 1: Adding Class Attributes to Article Handlebars File

In this step, you apply class attributes to the article’s Handlebars file. You also expand Handlebars’s modularity using the {{with}} and {{this}} placeholders.

  • Returning to the IDE, update the file Article.hbs with the following:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="Article">

    {{#with headline}}
        <div class="Article-headline">
            <h1>{{this}}</h1>
        </div>
    {{/with}}

    {{#with leadImageUrl}}
        <div class="Article-leadImage">
            <img src="{{this}}" height="300">
        </div>
    {{/with}}

    {{#with body}}
        <div class="Article-body">
            {{this}}
        </div>
    {{/with}}

</div>

In the previous snippet—

  • Lines 1, 4, 10, and 16 provide the class attribute for various elements. The class names follow the Block-Element-Modifier methodology.
  • Lines 4, 10, and 16 introduce nested divs for various elements. Nesting elements is a best practice when working with Less files as described in Step 3.
  • This snippet introduces the standard Handlebars {{with}} and {{this}} placeholders. These placeholders improve modularity when you incorporate one Handlebars file into different parent files.

For advanced Handlebars techniques to further automate the naming process, see Templating (Handlebars).

Step 2: Adding Class Attributes to Page Handlebars File

  • Returning to the IDE, update the file Page.hbs with the following:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
    <link href="/styleguide/All.min.css" type="text/css" rel="stylesheet"/>
    <script src="/styleguide/All.min.js" type="text/javascript"></script>
</head>

<body>
    <header class="Page-header">{{title}}</header>

    <div class="Page-body">
        {{body}}
    </div>
</body>

</html>

In the previous snippet—

  • Line 7 provides the link to an external CSS file (which you’ll generate in Step 6).
  • Line 12 adds the article’s title to the page. This line and line 6 are an example of replicating text with the {{title}} placeholder in more than one location on a rendered page.
  • Line 14 adds the class attribute to the page body, which itself nests the Article.hbs Handlebars file.
  • All class names in this snippet follow the Block-Element-Modifier methodology for CSS selectors.

Step 3: Implementing Article Styles Using Less

Less is a styling language and preprocessor that generates traditional CSS files at build time. Using Less along with the BEM methodology greatly reduces the burden of maintaining and debugging CSS files.

Note

When creating Less files, configure your text editor’s end-of-line character to newline only (\n).

  1. Returning to the IDE, change to styleguide/tutorial/article/, create a new file Article.less and enter the following text (last line is blank):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
.Article {
    &-headline {
        font-size: 18px;
        color: red;
        text-decoration: underline;
    }

    &-body {
        font-size: 14px;
    }
}
/* Replace this comment with a blank line. */

In the previous snippet—

  • Line 1 establishes Article as the block portion of a BEM selector name. Brightspot expands line 1 to create the CSS selector .Article, corresponding to the class name Article in the listing in Step 1.
  • Line 2 establishes headline as the element portion of a BEM selector name. Brightspot expands line 2 to create the CSS selector .Article-headline, corresponding to the class name Article-headline in the listing in Step 1.
  • Line 8 establishes body as the element portion of a BEM class name. Brightspot expands line 8 to create the CSS selector .Article-body, corresponding to the class name Article-body in the listing in Step 1.

Step 4: Implementing Page Styles Using Less

  • Returning to the IDE, change to styleguide/tutorial/page/, create a new file Page.less and enter the following text (last line is blank):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
.Page {
    font-family: sans-serif;
    color: black;
    margin: 5px;

    &-header {
        font-size: 10px;
        font-weight: bold;
        text-align: right;
    }

    &-footer {
        font-size: 10px;
        text-align: center;
        margin-top: 15px;
    }
}
/* Replace this comment with a blank line. */

In the previous snippet—

  • Line 1 establishes Page as the block portion of a BEM selector name. Brightspot expands line 1 to create the CSS selector .Page.
  • Line 6 establishes header as the element portion of a BEM selector name. Brightspot expands line 6 to create the CSS selector .Page-header, corresponding to the class name Page-header in the listing in Step 2.
  • Line 12 establishes footer as the element portion of a BEM class name. Brightspot expands line 12 to create the CSS selector .Page-footer.

Step 5: Importing Less Files into Project

Brightspot creates a master CSS file from the file styleguide/All.less. Therefore, you need to import your customized Less files into this file.

  • Returning to the IDE, open the file styleguide/All.less, and replace its contents with the following text (last line is blank):
@import 'tutorial/page/Page';
@import 'tutorial/article/Article';
/* Replace this comment with a blank line. */

Step 6: Assembling Templates and Stylesheets

  1. Returning to the IDE, change to styleguide/, create a new file _wrapper.json, and enter the following text:
1
2
3
4
5
6
7
{
    "_template": "tutorial/page/Page.hbs",
    "title": "Hello Styleguide",
    "body": {
        "_delegate": true
    }
}
  1. Refresh the page running at localhost:3000/_styleguide/index.html and click Article. The preview presents with the new formatting (headline set with red text and underline, header appears in upper-right corner).

    ../../../_images/styleguide-article-formatted.png
  2. Refresh the web page running at localhost:9480. Brightspot generates a formal CSS file at target/tutorial-1.0-SNAPSHOT/styleguide/All.min.css.

In the previous snippet—

  • Line 2 declares that the current JSON object is associated with the Handlebars template located at tutorial/page/Page.hbs (relative to the location of _wrapper.json).
  • Line 3 provides static text for the Handlebars helper {{title}}, showing this text when displaying the preview from Styleguide.
  • Lines 4–6 indicate that static text for the Handlebars helper {{body}} comes from a getBody method in the ViewModel.

Step 7: Updating ArticleViewModel

  1. Returning to the IDE, update the file ArticleViewModel.java with the following:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package brightspot.tutorial.article;

import brightspot.tutorial.image.Image;
import styleguide.tutorial.article.ArticleView;

import com.psddev.cms.rte.RichTextViewBuilder;
import com.psddev.cms.view.ViewModel;
import com.psddev.dari.util.StorageItem;

public class ArticleViewModel extends ViewModel<Article> implements ArticleView {

    @Override
    public CharSequence getHeadline() {
        return model.getHeadline();
    }

    @Override
    public CharSequence getLeadImageUrl() {
        Image leadImage = model.getLeadImage();

        if (leadImage != null) {
            StorageItem file = leadImage.getFile();

            if (file != null) {
                return file.getPublicUrl();
            }
        }

        return null;
    }

    @Override
    public CharSequence getBody() {
        String body = model.getBody();

        if (body != null) {
            return RichTextViewBuilder.buildHtml(body, (rte) -> null);
        }

        return null;
    }
}

In the previous snippet—

  • Line 4 imports the View automatically generated by Styleguide. This line replaces the @ViewInterface and @HandlebarsTemplate annotations.
  • Line 10 adds the implements clause for ArticleView.
  • Lines 12, 17, and 32 add the @Override annotation, because the associated methods now override the corresponding methods in the implemented interface ArticleView.

Step 8: Updating PageViewModel

  1. Returning to the IDE, update the file PageViewModel.java with the following:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package brightspot.tutorial.page;

import styleguide.tutorial.page.PageView;
import styleguide.tutorial.page.PageViewBodyField;

import com.psddev.cms.db.Content;
import com.psddev.cms.db.Seo;
import com.psddev.cms.view.PageEntryView;
import com.psddev.cms.view.ViewModel;

public class PageViewModel extends ViewModel<Content> implements PageView, PageEntryView {

    @Override
    public CharSequence getTitle() {
        return model.as(Seo.ObjectModification.class).findTitle();
    }

    @Override
    public Iterable<? extends PageViewBodyField> getBody() {
        return createViews(PageViewBodyField.class, model);
    }
}
  1. Refresh the web page running at localhost:9480 (or restart the Brightspot server). Brightspot recompiles the code using the updated ViewModels.
  2. In the URLs widget, click the permalink. The published version appears with the new formatting.
../../../_images/styleguide-article-published.png

In the previous snippet—

  • Line 3 imports the View automatically generated by Styleguide. This line replaces the @ViewInterface and @HandlebarsTemplate annotations.
  • Line 11 adds the implements clause for PageView.
  • Lines 13 and 18 add the @Override annotation, because the associated methods now override the corresponding methods in the implemented interface PageView.
  • Lines 18–21 return an iterable of PageViewBodyFields instead of a single string as in other ViewModels. Brightspot concatenates the returned PageViewBodyFields and places them inside the {{body}} placeholder declared in Page.hbs.