Implementing Reading Minutes Left | Innoraft Skip to main content

Solr Search

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!