reading minutes left banner
2021 05 Jan

Implementing Reading Minutes Left

The following is a step by step instruction for implementing reading minutes left for a particular article, blog, or similar, just like we see on medium.com.

 

 

 

The JS file

  • I have used this JS library.
  • Place this code in a JS file named read-remaining-minutes.js and place it in the corresponding theme.
(function($) {
  $.fn.readingTimeLeft = function (options) {

    var s = $.extend({}, {
      stepSelector: '*',
      wordPerMinute: 100,
      eventName: 'timechange'
    }, options);

    var $this   = $(this)
    , $window = $(window)
    , $steps  = $this.find(s.stepSelector);

  // For each step element, store the quantity of words to come
  $steps.each(function (i, el) {
    var textAhead =  $steps.slice(i, $steps.length).text();
    $(el).data('words-left', textAhead.trim().split(/\s+/g).length);
  });

  // Filters elements that are in viewport
  $.fn.filterVisible = function () {
    var wW = $window.width(), wH = $window.height();
    return this.filter(function(i, e){
      var rect = e.getBoundingClientRect();
      return rect.top >= 0 && rect.right <= wW &&
      rect.bottom <= wH && rect.left >= 0;
    });
  }

  function throttle (fn, limit) {
    var wait = false;
    return function () {
      if (wait) return;
      fn.call(); wait = true;
      setTimeout(function () { wait = false; }, limit);
    }
  };

  var triggerOn = 'scroll.' + s.eventName + ' resize.' + s.eventName;

  // Throttle updating to 50ms
  $(window).on(triggerOn, throttle(function (e) {
    var wordsLeft = $steps.filterVisible().last().data('words-left');
    $this.trigger(s.eventName, wordsLeft / s.wordPerMinute);
  }, 50));

  // Destroy function
  $this.on('destroy.readingTimeLeft', function (e) {
    $(window).off(triggerOn);
    $steps.removeData('words-left');
  });
  return $this;

};
}(jQuery))

Initialization and modification in custom JS

  • Next in the template.php file for your corresponding theme, you need to add the above JS file for the particular content type. You can do something like this below:
if ($vars['node']->type == 'article'') {
        drupal_add_js(drupal_get_path('theme','my_theme') . '/js/read-remaining-minutes.js');
}
  • After you have told Drupal to add the JS file, through the above code, your JS code will be ready for the page.
  • Now you need to specify where you want to add this functionality.
  • For that, I have a custom JS named “my-custom-js-code.js” file, in this same theme itself, where I usually write all my custom JS. Here I will specify my custom JS code.
// Reading time left for a blog post
    // #calculable-content is the id of the content on which we want to apply the calculation for reading time
    $('#calculatable-content').readingTimeLeft()
      .on('timechange', function(e, minutesLeft) {
        if(isNaN(minutesLeft)) {
          // .time-left is the class belonging to the read remaining div
          $('.time-left').hide();
        }
        else {
          // If less than 1 min remains then display "Content Finished" else show the minutes left
          var text = Math.round(minutesLeft) < 1? $('.time-left').text('Content Finished') : $('.time-left').text(Math.round(minutesLeft) + ' min left');
          $('.time-left').show();
        }
      })
    $(window).trigger('scroll');
  • Here I am considering that when the scroll reaches the end, it will show “Content Finished”. I will explain the id and the class used below.

Modifying .tpl.php

  • We have placed our JS codes as needed. Now we need to link it to the class in HTML so that it appears on the page.
  • I have a .tpl.php file which is responsible for rendering all the HTML content for the particular page named “custom-template.tpl.php”
  • In this .tpl.php file, at the place where you want this read remaining minutes block of text to appear,  you have to specify the HTML for it.
<div class="time-left qtip-link" title="Time remaining to finish reading the article"></div> 
<article id="calculatable-content" class="article-body"><?php print $content['body'][0]['#markup']; ?></article>
  • The time-left class is the wrapper class for the block, that is the entire block of the text itself.
  • The id calculatable-content is what we are using to calculate the time left, which will dynamically change while you scroll through the page.

Implementing CSS

  • We need to add a decent enough css so that it appears on the page without hurting the eyes!
  • You can use the following css, using this will place the block of text at the right top section of the page.
.time-left {
  position: fixed;
  right: 0;
  top: 176px;
  padding: 10px 10px 10px 40px;
  background: #068bb8;
  color: #fff;
  font-size: 15px;
  line-height: 19px;
  cursor: default;
  border-bottom: 0px;
  z-index: 999;
  &:before {
    content: url('../../../../../sites/all/themes/my_theme/images/time-left-white.png');
    position: absolute;
    top: 12px;
    left: 15px;
    @media screen and (max-width: 767px) {
      top: 8px;
      left: 10px;
    }
  }
  @media screen and (max-width: 767px) {
    padding: 6px 6px 6px 35px;
    font-size: 12px;
  }
}

Final approach

Now you just need to hit the cache clear, sit back and enjoy. Observe how the time changes as you scroll through the page!

Latest Blogs

php8-part-3

PHP 8 new features and changes - Part 3

This is part 3 of the blog. Here we will continue our discussions on the other features and changes in PHP 8.

Read More

drupal

UNDERSTANDING THE MOBILE APP DEVELOPMENT LIFECYCLE

Mobile app development is not rocket science in today's day and age.

Read More