<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Noah Glushien</title>
    <description>The latest articles on DEV Community by Noah Glushien (@noahcg).</description>
    <link>https://dev.to/noahcg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F307377%2Fbe3c6718-2d76-4e89-a803-6af384a49337.jpeg</url>
      <title>DEV Community: Noah Glushien</title>
      <link>https://dev.to/noahcg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/noahcg"/>
    <language>en</language>
    <item>
      <title>How to Create a Reading Position Indicator in Vue</title>
      <dc:creator>Noah Glushien</dc:creator>
      <pubDate>Thu, 09 Jan 2020 20:58:26 +0000</pubDate>
      <link>https://dev.to/noahcg/reading-position-indicator-in-vue-5cbd</link>
      <guid>https://dev.to/noahcg/reading-position-indicator-in-vue-5cbd</guid>
      <description>&lt;p&gt;Have you ever seen those reading progress indicators that exist in some online articles? You know the ones that indicate how much of the article you've scrolled. They are often displayed by stretching across the width of the page toward the top of the browser window.&lt;/p&gt;

&lt;p&gt;Have you ever wondered how to create one? Well, if you're anything like me, then you've tried building one yourself without doing any research. Then after a few hours of failed attempts, you realize that you have no idea what you're doing and there is no way your feeble code will ever work. Then after you feel utterly defeated you decide to do some Googling.&lt;/p&gt;

&lt;p&gt;That's when you learn about an HTML element you had no idea existed. Introducing the &lt;code&gt;&amp;lt;progress&amp;gt;&amp;lt;/progress&amp;gt;&lt;/code&gt; tag and its corresponding &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;max&lt;/code&gt; attributes.&lt;/p&gt;

&lt;p&gt;The following is my Vue implementation after finding the solution I was looking for on &lt;a href="https://css-tricks.com/reading-position-indicator/"&gt;CSS-Tricks&lt;/a&gt;. The JavaScript on that article was written in jQuery, so if you're not using jQuery in your project you may need to find another solution. That was the position I was in so maybe you'll find that my solution will also work for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Things First
&lt;/h2&gt;

&lt;p&gt;The first thing we need to do is to place the &lt;code&gt;&amp;lt;progress&amp;gt;&amp;lt;/progress&amp;gt;&lt;/code&gt; tag somewhere in our HTML. I'm not building this out as a Vue component right now although I may do that in the future. For this article, it's okay to just place the tag wherever you want the progress bar to appear in the DOM. If you're using Vue-CLI to build your project scaffolding then you can do all of this directly in the App.vue file. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you chose to install Vue Router while configuring your project in Vue-CLI, you may need to use the Home.vue file instead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When adding the tag to the DOM you'll also want to add an initial &lt;code&gt;value&lt;/code&gt; attribute, and you'll want to assign that a value of 0. Since we're writing this in Vue I decided to add that property to the data object and I called it &lt;strong&gt;progBarValue&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So far my code looks like this &lt;em&gt;(I added a ref attribute for easy referencing later on)&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;progress&lt;/span&gt; &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"progBarValue"&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"prog"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/progress&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;progBarValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting the Max Value
&lt;/h2&gt;

&lt;p&gt;Since the max value needs to be calculated based on the height of the document we're going to scroll, this is where we need to use JavaScript. To do this, I'm going to create another data property to store the value of the height I'm going to calculate. This will allow me to get the value using a method and then use that value as a computed property. If this sounds confusing hopefully looking at my next code example will help clarify.&lt;/p&gt;

&lt;p&gt;For now, I'll just add the new property, &lt;code&gt;clientHeight&lt;/code&gt;, to my data object and give it an initial value of &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, to calculate the height of the scrollable page we just need to subtract the height of the document from the height of the window. But how do we get the height of either of them and where should you place this logic? Here is how I'm doing it.&lt;/p&gt;

&lt;p&gt;The first thing I'm doing is getting the height of the document and I'm writing my logic directly within the &lt;code&gt;mounted()&lt;/code&gt; lifecycle hook. Then I'm assigning that height as the value of my data property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// you may need to use document.body.clientHeight&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then I'm creating a computed method, &lt;code&gt;progBarMax&lt;/code&gt;, to do the subtraction and to also assign the &lt;code&gt;max&lt;/code&gt; attribute on the progress tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;progBarmax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, my updated progress HTML tag looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;progress&lt;/span&gt; &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"progBarValue"&lt;/span&gt; &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"progBarMax"&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"prog"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/progress&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Updating the Value Attribute on Scroll
&lt;/h2&gt;

&lt;p&gt;Now we have a progress tag in the DOM with value and max attributes. So far so good. Next, we need to find a way of updating the value attribute as we scroll down the page. To do that I'm creating a method that I'm calling &lt;code&gt;updateProgressValue&lt;/code&gt;. Then I'll call that method using an event handler later. Be careful not to make the same mistake I did and use an arrow function to create your method or you're going to stare at the console log message stating it can't find the property of undefined wondering what on Earth you could have done wrong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;updateProgressValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;progBarValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageYOffset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All I have to do now is call my new method using the &lt;code&gt;scroll&lt;/code&gt; event handler. I'm also going to do this directly within the &lt;code&gt;mounted()&lt;/code&gt; lifecycle hook. I'm sure an argument can be made to put this somewhere else, but this works for me and the purposes of this article.&lt;/p&gt;

&lt;p&gt;My updated code looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateProgressValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  What About the CSS?
&lt;/h2&gt;

&lt;p&gt;Last but not least we need to style the progress indicator. This CSS was not written by me, it came directly from the source article over on CSS-Tricks as referenced earlier in this article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;progress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Positioning */&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* Dimensions */&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* Reset the appearance */&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nl"&gt;-moz-appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nl"&gt;appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* Get rid of the default border in Firefox/Opera. */&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* Progress bar container for Firefox/IE10+ */&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* Progress bar value for IE10+ */&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;progress&lt;/span&gt;&lt;span class="nd"&gt;::-webkit-progress-bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;progress&lt;/span&gt;&lt;span class="nd"&gt;::-webkit-progress-value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;progress&lt;/span&gt;&lt;span class="nd"&gt;::-moz-progress-bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And that's all there is to it. Hopefully, you found this little tutorial useful and maybe it cleared up some confusion you had around Vue. If you've found any issues with my logic I apologize. I modified this solution to track the height of a specific block of text on my page and to not show/track the reading progress until the user has scrolled to that part of the page. I didn't want to overly complicate this demo so the logic I wrote above is what I remember starting with before all of my specific changes.&lt;/p&gt;

&lt;p&gt;If you have any recommendations for a more efficient implementation then I'm all ears. &lt;/p&gt;

</description>
      <category>vue</category>
      <category>css</category>
      <category>html</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
