Skip to main content

Time is essential to all of us... and if you are like me there is never enough of it!  Anyway, the amount of time to read a piece of content can persuade someone whether to read on further... or swipe it away.  When on the verge of flipping an article as the title and /or teaser text hasn't got me across the line, the time to read is a handy reference for me.  This handy feature is becoming more common across any decent article publisher.

So how do you add this feature to your Drupal 8.9.x/9 site and have it nested along side author and creation date.  You can see it in action right now as it is being used on this site.  Yes it is there with a Font Awesome icon on display.

 

Get the time to read an article functionality

This is really easy as the hard work has been done for us by Yasen Ivanov with his node read time module. 

There are several ways to complete this task and rather than go into this step by step, I'll take it that you can achieve this yourself.  As I know from previous pm's, the method we use to resolve this is through shell and vim.  Which is completed through the following steps:

  1. Using shell, log into the server and go to the corresponding directory for the website;
  2. Locate the composer.json file and enter the command vi composer.json to edit.  If you want a cheat sheet for shell commands see vim cheatsheet;
  3. Scroll down the screen to the require area and add the following line (yes you'll need to press i to insert text):
    1. "drupal/node_read_time": "^1.2",
  4. Being a super organised as a team, this listing will be in alphabetical order so we find its alphabetical location;
  5. Press [Esc] key and type wq!;
  6. Run composer to download the module (composer update);
  7. Done

 

Applying the read time module

Through the Drupal administration area, add the module.  There is not much to the configuration as only three key areas are shown:

  • Content types to apply reading time field to;
  • Words per minute; and
  • Unit of time.

Now the fun begins.  As to have it displaying any where, you need to have it displayed in the corresponding content type (Home  > Administration > Structure > Content types > {Example type}).  Click on the Manage display tab.  Note, check if you are altering default and / or teaser displays.  Look for the field Reading time.  Ensure that this field is in the active area.  If not, drag it in and save.  Check the front end by reloading the page and it should be displaying.  Success!

Well almost.  While it is displaying, it isn't in the correct area.  Remember from the outset I wanted to place the reading time indicator in with the author and creation date.  This requires a little more work.  The good news is that the ground work has been completed and now we need to the finishing touches.

Heading back to Shell, navigate to the templates directory:

cd themes/custom/{your_template}/templates/content

In the content directory you will create a new file title reading-time.html.twig.  How?  Easy, simply type the following:

vim reading-time.html.twig

This command will create the file and have you ready to go.  Add the following line:

<span><i class="fa fa-clock-o" aria-hidden="true"></i> {{ reading_time }}</span>

Press [Esc] key and type wq!

Refresh the front end and as you will see this line adds:

  • The Font Awesome clock icon; and
  • Overrides the reading-time.html.twig layout in the module.

Looking good.

To add the read post script you will need to update the line you entered to become:

<span><i class="fa fa-clock-o" aria-hidden="true"></i> {{ reading_time }} read</span>

You should be getting the hang of it now so I don't need to add the edit and save commands.  If you are not sure, scan above to refresh.  As a prompt (Press [Esc] key and type wq!).

Almost there.  You now need to have the reading time displayed along side the author and date.  To achieve this edit the node.html.twig file.

vi node.html.twig

Depending on your theme, the contents of this may vary.  Generally I have found them to be similar across many themes.  But not all.  As a rule of thumb we create our own or add a sub theme.

There are two steps that need to be completed in this file:

  • Add the reading time so it is after the author and date; and
  • Also remove it from the content area.

The file I'm looking at with the area that I'm wanting to alter is displayed as:

{% if display_submitted %}
  <header class="node-header clear">
    {% if node_author_pic %}
      <div class="author-picture">{{ author_picture }}</div>
    {% endif %}
    <div{{ author_attributes.addClass('node-submitted-details') }}>
      {% set createdDate = node.getCreatedTime|date('j F Y') %}
      {% trans %}<span><i class="theme-color"></i> {{ author_name }}</span> <span><i class="theme-color"></i> {{ createdDate }}</span>{% endtrans %}
      {% if node_tags %}
      {% if content.field_tags %}
        <span><i class="icon-hashtag"></i>
        {% for item in content.field_tags %}
          {% if item['#title'] %}
            <a href="{{ item['#url']}}">{{ item['#title']  }}</a>{{ ',' }}
          {% endif %}
        {% endfor %}
      </span>
      {% endif %}
      {% endif %}
      {{ metadata }}
    </div>
  </header>
{% endif %}

I have highlighted the changes.  You will see Font Awesome references have been brought in as well as the reading time reference (content.reading_time).

{% if display_submitted %}
  <header class="node-header clear">
    {% if node_author_pic %}
      <div class="author-picture">{{ author_picture }}</div>
    {% endif %}
    <div{{ author_attributes.addClass('node-submitted-details') }}>
      {% set createdDate = node.getCreatedTime|date('j F Y') %}
      {% trans %}<span><i class="theme-color fas fa-user-circle"></i>  &nbsp; {{ author_name }}</span> &nbsp; &nbsp; <span><i class="theme-color fas fa-calendar-alt"></i> &nbsp; {{ createdDate }}</span> &nbsp; &nbsp; {% endtrans %}
        {{ content.reading_time }}
      {% if node_tags %}
      {% if content.field_tags %}
        <span><i class="icon-hashtag"></i>
        {% for item in content.field_tags %}
          {% if item['#title'] %}
            <a href="{{ item['#url']}}">{{ item['#title']  }}</a>{{ ',' }}
          {% endif %}
        {% endfor %}
      </span>
      {% endif %}
      {% endif %}
      {{ metadata }}
    </div>
  </header>
{% endif %}

If you save the updates and refresh the front screen, you will notice the reading time reference appears twice.  To remove it 

<div{{ content_attributes.addClass('node-content clear') }}>
  {{ content }}
</div>

Change the content reference by removing the reading_time field.

<div{{ content_attributes.addClass('node-content clear') }}>
  {{ content|without('reading_time') }}
</div>

Save, yes that is correct - Press [Esc] key and type wq!

Refresh the home screen and your work will have been completed.

The reading time now appears on the same line as author and creation date.

{author}        {date created}        {time to read}

 

Created or modified date

You would have noticed that the date on this article has updated in parentheses.  Whereas, your work will show the creation date.  As it makes little sense to only show the creation date rather than a more recent date as a result of the content being updated.

To begin this part, you need to determine whether the creation and changed dates are the same or different.  The current reference to the creation date is

{% set createdDate = node.getCreatedTime|date('j F Y') %}

We are going to change the variable reference from createdDate to setDate.  This will allow changing the date if changed is different and using the correct variable syntax.  To get the changed date the call is very similar to getCreatedTime... yes you are correct it is getChangedTime or the actual call is

{% set changedDate = node.getChangedTime|date('j F Y') %}

Comparing the created and modified times requires an if statement that needs to check if the two are different using !=. This is instead of a greater / less than comparison.

{% set extendDate = "" %}
{% if changedDate != setDate %}
    {% set setDate = changedDate %}
    {% set extendDate = " (updated)" %}
{% endif %}

You will notice in the above code, setDate is updated with the changed date.  This section of code now appears as 

{% if display_submitted %}
  <header class="node-header clear">
    {% if node_author_pic %}
      <div class="author-picture">{{ author_picture }}</div>
    {% endif %}
    <div{{ author_attributes.addClass('node-submitted-details') }}>
      {% set setDate = node.getCreatedTime|date('j F Y') %}
      {% set extendDate = "" %}
      {% set changedDate = getChangedTime|date('j F Y') %}
      {% if changedDate != setDate %}
        {% set setDate = changedDate %}
        {% set extendDate = " (updated)" %}
      {% endif %}
      {% trans %}<span><i class="theme-color fas fa-user-circle"></i>  &nbsp; {{ author_name }}</span> &nbsp; &nbsp; <span><i class="theme-color fas fa-calendar-alt"></i> &nbsp; {{ setDate }}<span class="dategrey">{{ extendDate }}</span></span> &nbsp; &nbsp; {% endtrans %}
        {{ content.reading_time }}
      {% if node_tags %}
      {% if content.field_tags %}
        <span><i class="icon-hashtag"></i>
        {% for item in content.field_tags %}
          {% if item['#title'] %}
            <a href="{{ item['#url']}}">{{ item['#title']  }}</a>{{ ',' }}
          {% endif %}
        {% endfor %}
      </span>
      {% endif %}
      {% endif %}
      {{ metadata }}
    </div>
  </header>
{% endif %}

Remember you will need to add the class .dategrey (or whatever you rename it to) in to your css file only if you want to have the extension text appearing in a different colour.