Friday, November 27, 2015

More Features for your Jade Templates

If you've seen Amphibian.com today you might notice the Christmas lights hanging from the header. I wanted to decorate the site a little, but I was worried that I might forget to take them down at the end of December. I think I left the lights up on my house until March last year. It was really cold and I didn't want to go outside.


To prevent this from happening to my website, I decided to add some code which will check the date and automatically display the lights only during the Christmas season. Since the HTML for Amphibian.com is generated by the Jade template system and Express, conditionally including some lights could be accomplished by putting a date check in the template for the comic page. The problem? The check for the Christmas season is a little more complicated than I cared to cram into a Jade template. And Jade/Express doesn't provide any utility libraries by default that help in this situation.

Fortunately, it's rather simple to add your own modules that can be used in your templates.

First, I made a holiday module that I can use to determine if we are currently in the Christmas season.

module.exports = function() {

    return {

        /*
         * Returns a Date object that represents Thanksgiving (US)
         * for this year. The fourth Thursday in November.
         */
        thanksgiving: function() {

            var d = new Date();

            d.setDate(1);
            d.setMonth(10);

            while (d.getDay() != 4) {
                d.setDate(d.getDate()+1);
            }

            d.setDate(d.getDate()+21);

            return d;

        },

        /*
         * This function returns true during the Christmas season.
         * I define that as Thanksgiving through the end of December.
         */
        isChristmasSeason: function() {

            var monthToday = (new Date()).getMonth();
            var dateToday = (new Date()).getDate();

            return (monthToday == 11 || (monthToday == 10 && dateToday >= this.thanksgiving().getDate()));

        }

    };

};

This is a standard Node module that exports an object containing two functions. One returns a Date object for Thanksgiving in the current year. In the United States, Thanksgiving is the 4th Thursday in November, so the function finds the first Thursday and then adds 3 weeks. The second function returns true if the current date falls within the Christmas season. I have personally defined that as Thanksgiving (hence the need for the first function) through the end of December.

Now to enable this module in Jade templates, you just need to add it to the locals object in the Express app. Here's an example of how to do that with this particular module:

var express = require('express');

var app = express();

app.locals.holiday = require('./holiday')();

Any fields on the locals object are available in Jade templates. In my comic page template, I can now do do this:

doctype html
html
 include head
 body
  include header
  if holiday.isChristmasSeason()
   include holidayHeader
  div#comicArea
   include comic
  include footer
  include js

The holiday object can be used anywhere it's legal to use JavaScript expressions in the template. I use it in the if block to see if I need to include the special holiday header.

You can use this technique to add whatever module you want to locals and then use them inside your templates. While Jade is not perfect, this capability adds a lot of flexibility to the framework.

Please continue to enjoy this Christmas season by viewing today's comic, which is, appropriately, about the Christmas season.

Amphibian.com comic for 27 November 2015