5 minutes 46 seconds average read (1154 words)

So recently I've been building a blog for my partner and I've used Squiz Matrix to do so. I decided it would be a good idea to use my new found JavaScript skills to achieve this. When I finished it I showed it to one of the developers at Squiz and he said: "you know you can do that with Squiz Matrix Keyword Replacements and Modifiers?"

So here I'm going to detail how to achieve the Reading Time with both.

## Part 1 Method

Throughout my learning of JavaScript through Wes Bos's course, I've learn that breaking the problem down into chunks makes it easier to solve, so using this I broke down the task into these blocks:

1. Find out the Average Reading Speed, this varies on:
1. the type of content, technical content takes longer than normal reading considerably
2. the type of reading, skimming is way faster than reading for comprehension
4. I've settled on 200 words per minute in this case, based on this post by the British Psychological Society.
2. Count the words on the page and assign it to a `numWords` variable, I've chosen to use the `<main>` element for the words to count.
3. Divide the `numWords` by WPM to work out the time.
4. Round the time to 2 decimal places.
5. Insert into the page:
1. Time
2. Word Count

## Part 2 Using JavaScript

Set a variable with the average reading speed of 200 WPM, this will be set as a const variable as it is not going to change.

```const wordsPerMinute = 200;
```

### Count words in the `<main>` element

Grab the content of the `<main>` element.

```// grabs all the content in the &lt;main&gt; element
const content = document.querySelector('main'); ```

Count the number of words in the `content` variable splitting it on spaces. This grabs the `innerText` from content, `split`s it into an `array` at each space and then outputs the `length` of the array, how many items are in the array.

```// counts number of words in the content
const numWords = content.innerText.split(' ').length; ```

### Divide `numWords` by `wordsPerMinute`

Create a `result` variable to store the time in minutes, seconds and number of words, this is done with a `let` variable because later it will be updated.

```// sets up a result to inject into the page
let result; ```

check that the `numWords` is not 0 and that there are actually words on the page.

```if(numWords > 0){ // checks to see that there is actuallt some content
//code goes here to be run if numWords is greater than 0 (zero)
}
```

Create a let variable called `time` to store `numWords` divided by `wordsPerMinute` .

`let time = numWords / wordsPerMinute;`

Add the new variables to the result variable

Using backticks and interpolation to create the value of the result variable. In here I'm also rounding `time` to 2 decimal places using `toFixed(2)` .

`result = `~\${time.toFixed(2)} min read (\${numWords} words)`;`

### Insert Result into the page

In the page I have a `span` element with the class `reading-time` .

```<span class="reading-time"></span>
```

I am setting the `innerText` of that element to be the value of `result` variable.

`document.querySelector('.reading-time').innerText = result;`

### Full code block

```// grabs all the content in the element
const content = document.querySelector('main');
//counts number of words in the content
const numWords = content.innerText.split(' ').length;
const wordsPerMinute = 200;
// sets up a result to inject into the page
let result;
// checks to see that there is actually some content
if(numWords > 0){
let time = numWords / wordsPerMinute;
result = `~\${time.toFixed(2)} min read (\${numWords} words)`;
}
```

## Part 3 Using Squiz Matrix Keyword Replacements and Modifiers

### Count words in the `<main>` element

In Squiz Matrix, this is the contents of the asset, in the way I've built the blog so I can use the keyword `%globals_asset_contents_raw%` , this keyword shows just the contents with no Paint Layout applied, with the keyword modifier `^wordcount` .

`%globals_asset_contents_raw^wordcount%`

### Divide `numWords` by `wordsPerMinute` to get the minutes

This time I'm going to grab only the minutes and grab the seconds later. To do this I'm going to use `^divide` and `^floor` modifiers.

The `^divide` modifier takes a number to divide by, and I'm using the WPM, so `^divide:200` .

The `^floor` modifier rounds the number down to the integer, with on decimal places, hence giving us the minutes.

`%globals_asset_contents_raw^wordcount^divide:200^floor%`

### Grab the remainder and convert to seconds

To achieve this I'm going to get the raw value of minutes as seen in the step previously without using `^floor` and then `^subtract` the minutes from it. This will give me a fraction of minutes, which I can then ^multiple by 60 to get the value in seconds.

#### Get full time

```%globals_asset_contents_raw^wordcount^divide:200%
```

#### `^Subtract` minutes from it

Here I am subtracting the previous value using the `^subtract` modifier, because I am inserting a keyword into another keyword I need to do this with curly brackets `{}` .

```^subtract:{globals_asset_contents_raw^wordcount^divide:200^floor}
```
##### Full Keyword so far
```%globals_asset_contents_raw^wordcount^divide:200%^subtract:{globals_asset_contents_raw^wordcount^divide:200^floor}
```

#### ^multiply by 60 to get the seconds

Here I am `^multiply` ing the value by 60 and then using the `^round` keyword modifier to either round the number up or down to an integer.

```^multiply:60^round
```

#### Full Keyword

`%globals_asset_contents_raw^wordcount^divide:200^subtract:{globals_asset_contents_raw^wordcount^divide:200^floor}^multiply:60^round%`

### Insert into the page

Now that I have everything I can insert it into the page, inside a ` <span class="reading-time"></span> ` element.

This will output minutesseconds word count, e.g. 2 minutes 30 seconds (500 words):

```%globals_asset_contents_raw^wordcount^divide:200^floor% minutes %globals_asset_contents_raw^wordcount^divide:200^subtract:{globals_asset_contents_raw^wordcount^divide:200^floor}^multiply:60^round%

### Conditions

I have decided to put in some conditions to check:

1. if the minutes are greater than or equal to 1, if so show the minutes, if not only show the seconds
2. if the number of minutes is greater than 1 add an 's' to the end of the word minute making it minutes

#### Number of minutes is Greater than or equal to 1

```%begin_globals_asset_contents_raw^wordcount^divide:200^floor^gte:1%
If True // show minutes and seconds
%else_globals_asset_contents%
If False // show seconds only
%end_globals_asset_contents%
```

#### Number of seconds is Greater than 1

```  minute // print the word minute
%begin_globals_asset_contents_raw^wordcount^divide:200^floor^gt:1%
s // if there are more than 1 minute add an 's'
%end_globals_asset_contents% ```

#### Full keywords with conditions

```// Greater than or equal to 1 true
%begin_globals_asset_contents_raw^wordcount^divide:200^floor^gte:1%
%globals_asset_contents_raw^wordcount^divide:200^floor% minute
// minutes greater than 1 true
%begin_globals_asset_contents_raw^wordcount^divide:200^floor^gt:1%
s // print 's'
%end_globals_asset_contents%
%globals_asset_contents_raw^wordcount^divide:200^subtract:{globals_asset_contents_raw^wordcount^divide:200^floor}^multiply:60^round%