## DEV Community

Andy Carmona

Posted on • Updated on

# Adding estimated reading time to posts in Jigsaw

This post was originally published on my personal blog

There is scientific evidence that shows that this is true, and as explained in The New Yorker:

In 2011, the psychologists Claude Messner and Michaela Wänke investigated what, if anything, could alleviate the so-called “paradox of choice”
— the phenomenon that the more information and options we have, the worse we feel. They concluded that …
the faster we decide on something, whether it’s what we’re going to eat or what we’re going to read, the happier we become
[…] The more we know about something — including precisely how much time it will consume — the greater the chance we will commit to it.

## Words Per Minute (WPM)

According to Wikipedia, Words per minute is

a measure of words processed in a minute, often used as a measurement of the speed of typing, reading or Morse code sending and receiving.

There have been studies that demonstrates that the average silent reading rate for adults in english is 238 wpm for non-fiction and 260 wpm for fiction.

## How to calculate Estimated Reading Time

It is a really simple algorithm:

1. Find your total word count. Let’s say it’s 938 words.
2. Divide your total word count by an estimated Words per minute quantity, Eg. 200. In this case, 4.69.
3. The first part of your decimal number is your minutes. In this case 4.
4. Take the second part — the decimal points — and multiply that by 0.60. Those are your seconds.

The result? 938 words = a 4 minute, 41 second read.

## Time to code

So, enough of the theory and let's get our hands dirty.

With our algorithm in place we are going to create a function that will help us calculate the estimated reading time for each of our posts. Let's base our function on this gist (https://coderwall.com/p/y1yhwg/estimate-reading-time](https://coderwall.com/p/y1yhwg/estimate-reading-time)

``````/**
* Returns an estimated reading time in a string
* @param  string \$content the content to be read
* @param int \$wpm
* @return string          estimated read time eg. 1 minute, 30 seconds
**/
private function getEstimateReadingTime(\$content, \$wpm = 200) {
\$wordCount = str_word_count(strip_tags(\$content));

\$minutes = (int) floor(\$wordCount / \$wpm);
\$seconds = (int) floor(\$wordCount % \$wpm / (\$wpm / 60));

\$str_minutes = (\$minutes === 1) ? 'minute' : 'minutes';
\$str_seconds = (\$seconds === 1) ? 'second' : 'seconds';

if (\$minutes === 0) {
return "{\$seconds} {\$str_seconds}";
}
else {
return "{\$minutes} {\$str_minutes}, {\$seconds} {\$str_seconds}";
}
}
``````

This function is part of the listener that we are going to create next:

``````namespace App\Listeners;

use TightenCo\Jigsaw\Jigsaw;

{
public function handle(Jigsaw \$jigsaw)
{
\$jigsaw->getCollection('posts')->map(function (\$post)
{
});
}
}
``````

Here we get the `posts` collection, iterate through all the items in that collection, and add a new property called `estimated_reading_time` which will contain the proper value. Once our listener has been created we need to hook it to an event. In Jigsaw, every time we build our site, several events are fired, those events are:

• beforeBuild
• afterCollection
• afterBuild

The one we are interested on is the afterCollection event. This event is fired after all collections have been processed but before any output files are written to disk. so let's go ahead and register our listener. We do this in the `bootstrap.php` file as mentioned before.

``````\$events->afterCollections(App\Listeners\GenerateEstimateReadingTime::class);
``````

## Update the views.

With all this in place, the only thing missing is the adding this newly created value to our views. Let's add it to the `index.blade.php` file.

``````<span class="inline-block bg-grey-300 hover:bg-grey-400 leading-loose tracking-wide text-grey-700 uppercase text-xs font-semibold rounded mt-2 md:ml-2 px-3 pt-px">{{ \$post->estimated_reading_time }}</span>
``````