Jekyll2021-09-28T12:52:56+00:00https://davidyoung.tech/feed.xmlDavid YoungDavid Young is a Web Developer based in Brisbane, Australia with a keen interest in Website Development and Design.Caching Dynamic Resources With Service Workers2021-09-06T02:00:00+00:002021-09-06T02:00:00+00:00https://davidyoung.tech/caching-dynamic-resources-with-service-workers<p>When using service workers you may know some of the routes you want to cache, but if you want to cache some more complex resources that are requested dynamically later, and the resultant URL of the resource you want to cache is not clear up front, there is a way to get those working offline.</p>
<h1 id="google-fonts-as-a-dynamic-resource">Google fonts as a dynamic resource</h1>
<p>When caching Google fonts for example there are a couple of routes that you will want to cache, so the resultant behaviour while offline is the same while online. This involves a couple of parts, caching the request to the initial font page and the redirect then served to the actual font file.</p>
<p>Initially when you add google fonts to a webpage you include a link like the one below;</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans">
</code></pre></div></div>
<p>That URL is the first route we will need to cache, but it doesn’t actually return the font file itself, it serves a redirect to the actual font resource. We could store this route initially since we know it ahead of time but then the redirect would not work while offline.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># initial request to the font family endpoint serves redirect
https://fonts.googleapis.com/css?family=Open+Sans
# actual font resource we get redirected to
https://fonts.gstatic.com/s/opensans/v23/mem8YaGs126MiZpBA-UFVZ0bf8pkAg.woff2
</code></pre></div></div>
<p>That second request will load the font Open Sans font file into the page and you can make use of it. We could add that route to our list of items to cache, but at this point we can consider some generalised logic to handle it for us.</p>
<h1 id="custom-service-worker-fetch-cases">Custom service worker fetch cases</h1>
<p>Given that we know the two origins that requests for font files go out to, we can create a more generic piece of functionality to cache these resources on the fly. We can extend this to any resource you might want to download and cache after the install step, Google fonts are just an interesting example and a common workflow on webpages.</p>
<p>We can create a list of domains we would like to cache all requests to and then check what resource we are requesting in the <code class="language-plaintext highlighter-rouge">fetch</code> step each time.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">resourcesToCacheLater</span> <span class="o">=</span> <span class="p">[</span>
<span class="dl">'</span><span class="s1">fonts.googleapis.com</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">fonts.gstatic.com</span><span class="dl">'</span>
<span class="p">];</span>
</code></pre></div></div>
<p>If the request is one we want to cache, we can put a clone of the response in the cache as we go, so we have it ready in the service worker next time, and also pass the response back to the browser.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">fetch</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">requestUrl</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">URL</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">.</span><span class="nx">url</span><span class="p">);</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">respondWith</span><span class="p">(</span>
<span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_NAME</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">cache</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">match</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">match</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">match</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// is this a route we want to cache?</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">resourcesToCacheLater</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">requestUrl</span><span class="p">.</span><span class="nx">host</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// put resource in the cache while we have it</span>
<span class="nx">cache</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">,</span> <span class="nx">response</span><span class="p">.</span><span class="nx">clone</span><span class="p">());</span>
<span class="p">}</span>
<span class="c1">// pass the resource back to the browser</span>
<span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
<span class="p">}).</span><span class="k">catch</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="c1">// we didn't cache it, they're offline and it failed</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="na">status</span><span class="p">:</span> <span class="mi">404</span><span class="p">});</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">})</span>
<span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>When we find that the resource we want does not have a match in the cache, and we go to fetch it from the network, we check to see if it is a resource we want to add to our cache dynamically. If we have it, we serve the resource up from the cache, otherwise we go out and get the resource while also storing a copy of it in our cache.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// is this a route we want to cache?</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">resourcesToCacheLater</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">requestUrl</span><span class="p">.</span><span class="nx">host</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// put resource in the cache while we have it</span>
<span class="nx">cache</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">,</span> <span class="nx">response</span><span class="p">.</span><span class="nx">clone</span><span class="p">());</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Note that we need to create a <code class="language-plaintext highlighter-rouge">.clone()</code> of the response to put in the cache, we can’t store the request in the cache and also send the same one back to the browser.</p>
<h1 id="wrapping-up">Wrapping up</h1>
<p>This is just one way service workers can provide custom functionality for your needs. They are impressive in that they essentially let you put custom logic in the middle of all of your fetch requests, and can be extended in a number of different ways to match your needs.</p>When using service workers you may know some of the routes you want to cache, but if you want to cache some more complex resources that are requested dynamically later, and the resultant URL of the resource you want to cache is not clear up front, there is a way to get those working offline.Serving Jekyll Sites Offline2021-09-04T02:00:00+00:002021-09-04T02:00:00+00:00https://davidyoung.tech/serving-jekyll-sites-offline<p>When I put this new blog together with Jekyll I added a service worker to the build process, generating the required URL’s to cache using liquids templating language. I was then able to include those generated links in my service workers code to save me needing to manaully update the list over time.</p>
<h1 id="creating-a-list-of-pages-in-the-jekyll-site">Creating a list of pages in the Jekyll site</h1>
<p>In a <a href="/simple-service-worker-setup">previous post</a> I show a simple service worker setup where some URL’s are specified for caching. When building the site with Jekyll, it is good to not have to keep a list of every page up to date in the service workers set of routes to cache, so we can instead use liquid within our service workers file to generate the routes we need to cache at build time.</p>
<p>The following captures a set of resources into a variable called <code class="language-plaintext highlighter-rouge">asset_urls</code> for inserting into the routes we want to cache JavaScript variable later.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="o">%</span> <span class="nx">capture</span> <span class="nx">asset_urls</span> <span class="o">%</span><span class="p">}</span>
<span class="p">{</span><span class="o">%</span> <span class="k">for</span> <span class="nx">page</span> <span class="k">in</span> <span class="nx">site</span><span class="p">.</span><span class="nx">html_pages</span> <span class="o">%</span><span class="p">}</span>
<span class="dl">'</span><span class="s1">{{ page.url | remove: </span><span class="dl">'</span><span class="p">.</span><span class="nx">html</span><span class="dl">'</span><span class="s1"> }}</span><span class="dl">'</span><span class="p">,</span>
<span class="p">{</span><span class="o">%</span> <span class="nx">endfor</span> <span class="o">%</span><span class="p">}</span>
<span class="p">{</span><span class="o">%</span> <span class="k">for</span> <span class="nx">post</span> <span class="k">in</span> <span class="nx">site</span><span class="p">.</span><span class="nx">posts</span> <span class="o">%</span><span class="p">}</span>
<span class="dl">'</span><span class="s1">{{ post.url }}</span><span class="dl">'</span><span class="p">,</span>
<span class="p">{</span><span class="o">%</span> <span class="nx">endfor</span> <span class="o">%</span><span class="p">}</span>
<span class="p">{</span><span class="o">%</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">site</span><span class="p">.</span><span class="nx">static_files</span> <span class="o">%</span><span class="p">}</span>
<span class="p">{</span><span class="o">%</span> <span class="k">if</span> <span class="nx">file</span><span class="p">.</span><span class="nx">path</span> <span class="nx">contains</span> <span class="dl">'</span><span class="s1">/images</span><span class="dl">'</span> <span class="nx">or</span> <span class="nx">file</span><span class="p">.</span><span class="nx">path</span> <span class="nx">contains</span> <span class="dl">'</span><span class="s1">manifest</span><span class="dl">'</span> <span class="nx">or</span> <span class="nx">file</span><span class="p">.</span><span class="nx">path</span> <span class="nx">contains</span> <span class="dl">'</span><span class="s1">css</span><span class="dl">'</span> <span class="o">%</span><span class="p">}</span>
<span class="dl">'</span><span class="s1">{{ file.path }}</span><span class="dl">'</span><span class="p">,</span>
<span class="p">{</span><span class="o">%</span> <span class="nx">endif</span> <span class="o">%</span><span class="p">}</span>
<span class="p">{</span><span class="o">%</span> <span class="nx">endfor</span> <span class="o">%</span><span class="p">}</span>
<span class="p">{</span><span class="o">%</span> <span class="nx">endcapture</span> <span class="o">%</span><span class="p">}</span>
</code></pre></div></div>
<p>The above script tracks pages which are our main routes like <code class="language-plaintext highlighter-rouge">/</code> and <code class="language-plaintext highlighter-rouge">/contact</code>. It also tracks each post like the one you are reading right now and adds it to the list. Finally it also adds static files, like images and other Jekyll pages without front matter that are not processed. We can then push this as mentioned into a list of routes we want to cache with the service worker.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">urlsToCache</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{{</span> <span class="nx">asset_urls</span> <span class="o">|</span> <span class="nx">normalize_whitespace</span> <span class="p">}}</span>
<span class="p">];</span>
</code></pre></div></div>
<p>We can also leverage some more liquid templating to help update our service worker each time we rebuild the site. We can use the available liquid tags <code class="language-plaintext highlighter-rouge">{{ site.time | date_to_xmlschema }}</code> as part of the caching key, to keep our cache name unique each time we rebuild the site, so when publishing the old cache is removed and replaced with the new list of resources.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">CACHE_NAME</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">{{ site.url }}-site-{{ site.time | date_to_xmlschema }}';
</span></code></pre></div></div>
<p>Some static resources had to be added manually with the above setup, so a few resources were included in the list already.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">urlsToCache</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{{</span> <span class="nx">asset_urls</span> <span class="o">|</span> <span class="nx">normalize_whitespace</span> <span class="p">}},</span>
<span class="dl">'</span><span class="s1">/manifest.json</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// manually added</span>
<span class="dl">'</span><span class="s1">/js/validate.js</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// manually added</span>
<span class="dl">'</span><span class="s1">/css/main.css</span><span class="dl">'</span> <span class="c1">// manually added</span>
<span class="p">];</span>
</code></pre></div></div>
<h1 id="installing-the-generated-routes">Installing the generated routes</h1>
<p>These routes are injected inside the declared variable <code class="language-plaintext highlighter-rouge">urlsToCache</code> and then when we go to cache these URL’s with a service worker we pass these <code class="language-plaintext highlighter-rouge">urlsToCache</code> to the <code class="language-plaintext highlighter-rouge">install</code> step and they are added to our cache.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Perform install steps</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">install</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">waitUntil</span><span class="p">(</span>
<span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_NAME</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">cache</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">addAll</span><span class="p">(</span><span class="nx">urlsToCache</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nb">self</span><span class="p">.</span><span class="nx">skipWaiting</span><span class="p">());</span>
<span class="p">})</span>
<span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>The install step inserts these resources into the browsers cache and subsequent loads of these resources intercepted by the service worker will use the cached asset over reaching out to the network, so the site will start working offline.</p>
<h1 id="wrapping-up">Wrapping up</h1>
<p>This is just a short demonstration of how you can make use of the liquid templating made available to build out the resources to cache dynamically for a Jekyll site. As more posts get added to the blog they’ll automatically become part of the cached list of assets without manual work keeping the service worker up to date.</p>When I put this new blog together with Jekyll I added a service worker to the build process, generating the required URL’s to cache using liquids templating language. I was then able to include those generated links in my service workers code to save me needing to manaully update the list over time.Detecting Page Scroll Distance2021-08-31T02:00:00+00:002021-08-31T02:00:00+00:00https://davidyoung.tech/detecting-page-scroll-distance<p>Checking when a user has scrolled to the end of a page can be useful for a number of different features. You may want to load more information once a user has scrolled to the end to create infinite scrolling, or find out that a user has read your whole article.</p>
<h1 id="listening-for-the-scroll-event">Listening for the scroll event</h1>
<p>We can listen for the user scrolling the page by attaching a <code class="language-plaintext highlighter-rouge">scroll</code> listener to the <code class="language-plaintext highlighter-rouge">document</code> object.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">document</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">scroll</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// perform logic when a user scrolls</span>
<span class="p">});</span>
</code></pre></div></div>
<p>This event will trigger each time the user scrolls the page, and the frequency that it reports information is quite high. It is common to debounce this triggered function which will be explained further on.</p>
<h1 id="detecting-the-bottom-of-the-page">Detecting the bottom of the page</h1>
<p>There are some properties on the <code class="language-plaintext highlighter-rouge">window</code> and <code class="language-plaintext highlighter-rouge">document</code> objects that help us know whether the user has scrolled to the end of the page. First useful property is the height of the page in total which you can get from the <code class="language-plaintext highlighter-rouge">document</code>.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">scrollHeight</span><span class="p">);</span> <span class="c1">// height in px</span>
</code></pre></div></div>
<p>Then we can work out how far down the page a user has scrolled so far using some properties on the <code class="language-plaintext highlighter-rouge">window</code> object.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">innerHeight</span><span class="p">);</span> <span class="c1">// how tall is the current window?</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">pageYOffset</span><span class="p">);</span> <span class="c1">// how far from the top of the page, is our current view?</span>
</code></pre></div></div>
<p>Combining these properties we can create a test for checking if we have reached the end.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// have we scrolled to the end of the page?</span>
<span class="kd">function</span> <span class="nx">testHeight</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">window</span><span class="p">.</span><span class="nx">pageYOffset</span> <span class="o">+</span> <span class="nb">window</span><span class="p">.</span><span class="nx">innerHeight</span> <span class="o">>=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">scrollHeight</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h1 id="example-including-debounce">Example including debounce</h1>
<p>In the following codepen I have produced an example and the <code class="language-plaintext highlighter-rouge">scroller</code> object is a module that could be included in any webpage. When the bottom of the page has been reached, an event is triggered.</p>
<iframe height="400" style="width: 100%;" scrolling="no" src="https://codepen.io/dayvidwhy/embed/oNWPYMM?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> <a href="https://codepen.io/dayvidwhy/pen/oNWPYMM">See the Pen</a> by David Young (<a href="https://codepen.io/dayvidwhy">@dayvidwhy</a>) on <a href="https://codepen.io">CodePen</a>. </iframe>Checking when a user has scrolled to the end of a page can be useful for a number of different features. You may want to load more information once a user has scrolled to the end to create infinite scrolling, or find out that a user has read your whole article.Stuck In A Bind2017-06-12T01:53:28+00:002017-06-12T01:53:28+00:00https://davidyoung.tech/stuck-in-a-bind<p>In JavaScript it can be advantageous to override the default <code class="language-plaintext highlighter-rouge">this</code> context when dealing with function callbacks where you want to abstract these out into their own named functions. Using a plain <code class="language-plaintext highlighter-rouge">.bind</code> on the end of your function can be one way of dealing with this.</p>
<p>Let us consider the following event handler which prints a message and adds a class. We’re going to alter this code a few times to illustrate how else we could write it, and the pros and cons of each.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">startListening</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Print out this message!</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">button</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">button</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">button</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">className</span> <span class="o">+=</span> <span class="dl">'</span><span class="s1"> clicked-style</span><span class="dl">'</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">startListening</span><span class="p">();</span>
</code></pre></div></div>
<p>Here we are calling a simple function <code class="language-plaintext highlighter-rouge">startListening</code> that will listen for a click on our button, print out our message and add some class that indicates to the user they clicked our button. In the callback function for a click event listener, <code class="language-plaintext highlighter-rouge">this</code> is the button itself, so we can directly alter it’s <code class="language-plaintext highlighter-rouge">className</code> attribute.</p>
<h1 id="named-functions">Named Functions</h1>
<p>As your code grows in size it can be useful to abstract out anonymous functions and give them names to better separate your logic. The above could be rewritten as.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">startListening</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Print out this message!</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">button</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">button</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">button</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="nx">buttonClicked</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">buttonClicked</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span> <span class="c1">// undefined error</span>
<span class="k">this</span><span class="p">.</span><span class="nx">className</span> <span class="o">+=</span> <span class="dl">'</span><span class="s1">clicked-style</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">startListening</span><span class="p">();</span>
</code></pre></div></div>
<p>Here we pass the function <code class="language-plaintext highlighter-rouge">buttonClicked</code> by name which will get called later when we click on the button. Note that we do not put <code class="language-plaintext highlighter-rouge">( )</code> brackets on the end of the event listeners second argument, as we don’t want to invoke the function, only pass reference to it. The issue that then arises is when the button is clicked, you will get an error saying <code class="language-plaintext highlighter-rouge">message</code> is undefined.</p>
<p>This is because of <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Closures#Lexical_scoping">lexical scope</a> in JavaScript and the fact that variables are function scoped. This means that any given function only has access to variables within the function or outside of it’s own closure.</p>
<h1 id="global-variable">Global Variable</h1>
<p>We could solve this problem by making that variable more global and lift it out of that functions scope</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// global variable</span>
<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Print out this message!</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">startListening</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">button</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">button</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">button</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="nx">buttonClicked</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">buttonClicked</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span> <span class="c1">// no problem</span>
<span class="k">this</span><span class="p">.</span><span class="nx">className</span> <span class="o">+=</span> <span class="dl">'</span><span class="s1">clicked-style</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">startListening</span><span class="p">();</span>
</code></pre></div></div>
<p>But now we are leaking variables and the entire document would have access to this variable which we might not want.</p>
<h1 id="wrapping-the-function">Wrapping the Function</h1>
<p>To get this <code class="language-plaintext highlighter-rouge">message</code> variable into out extra function we could wrap an anonymous function around it and make our button clicked function take an extra argument.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">startListening</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Print out this message!</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">button</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">button</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">button</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// take a couple of extra argument here</span>
<span class="nx">buttonClicked</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="nx">message</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">buttonClicked</span><span class="p">(</span><span class="nx">event</span><span class="p">,</span> <span class="nx">button</span><span class="p">,</span> <span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span> <span class="c1">// works!</span>
<span class="nx">button</span><span class="p">.</span><span class="nx">className</span> <span class="o">+=</span> <span class="dl">'</span><span class="s1">clicked-style</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">startListening</span><span class="p">();</span>
</code></pre></div></div>
<p>But now we’ve reintroduced our anonymous function which is what we were hoping to avoid and you’ll also notice I needed to pass the button itself down by passing <code class="language-plaintext highlighter-rouge">this</code>.</p>
<h1 id="bring-in-bind">Bring in Bind</h1>
<p><code class="language-plaintext highlighter-rouge">.bind</code> is a javascript directive that lets you manipulate the <code class="language-plaintext highlighter-rouge">this</code> context within a callback function. It’s a method on functions that return a new function that acts a bit differently.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">startListening</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Print out this message!</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">button</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">button</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">button</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="nx">buttonClicked</span><span class="p">.</span><span class="nx">bind</span><span class="p">({</span>
<span class="na">innerMessage</span><span class="p">:</span> <span class="nx">message</span>
<span class="p">}));</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">buttonClicked</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// this is an object now, not the button itself</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">innerMessage</span><span class="p">);</span> <span class="c1">// works!</span>
<span class="k">this</span><span class="p">.</span><span class="nx">className</span> <span class="o">+=</span> <span class="dl">'</span><span class="s1">clicked-style</span><span class="dl">'</span><span class="p">;</span> <span class="c1">// doesn't work :(</span>
<span class="p">}</span>
<span class="nx">startListening</span><span class="p">();</span>
</code></pre></div></div>
<p>The issue here is we lose context of the button itself so our class change no longer works. This is fine if you didn’t really want to access the button directly, it really just depends on your use case.</p>
<p>For some more examples see this pen.</p>
<iframe height="400" style="width: 100%;" scrolling="no" src="https://codepen.io/dayvidwhy/embed/rKVaYy?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> <a href="https://codepen.io/dayvidwhy/pen/rKVaYy">See the Pen</a> by David Young (<a href="https://codepen.io/dayvidwhy">@dayvidwhy</a>) on <a href="https://codepen.io">CodePen</a>. </iframe>
<h1 id="wrapping-up">Wrapping up</h1>
<p>You’ve seen 4 ways of getting our message into the callback function, and which one you use really depends on your use case.</p>
<p>If you don’t need direct access to the button itself in the callback, then binding <code class="language-plaintext highlighter-rouge">this</code> into something else can be entirely reasonable.</p>In JavaScript it can be advantageous to override the default this context when dealing with function callbacks where you want to abstract these out into their own named functions. Using a plain .bind on the end of your function can be one way of dealing with this.Simple Service Worker Setup2017-01-09T00:20:00+00:002017-01-09T00:20:00+00:00https://davidyoung.tech/simple-service-worker-setup<p>If you’ve been paying attention to new technologies on the web one thing you have not missed is <a href="https://developer.mozilla.org/en/docs/Web/API/Service_Worker_API">Service Workers</a>. They’re a new take on the idea of <em>progressive enhancement</em> and I think they’re going to stick around for a while yet.</p>
<h1 id="workers-on-the-page">Workers on the page</h1>
<p>The idea of a <a href="http://www.w3schools.com/html/html5_webworkers.asp">web worker</a> is not new, and is currently used to help move large amounts of computation off the main thread. People tend to use them when they want to do large calculations in the background without affecting render performance.</p>
<p>Web workers are just JavaScript as well which makes them very easy to understand and start using. If you have not looked into the idea of a promise in the browser I would suggest <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise">this</a> resource from Mozilla.</p>
<h1 id="simple-service-worker">Simple service worker</h1>
<p>Here’s a really simple service worker that will work on any page if you add the basic assets in the array that gets cached. You also need to add the install script to the webpage that gets served to your users on their initial visit.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// index.html - install the service worker</span>
<span class="k">if</span> <span class="p">(</span><span class="dl">'</span><span class="s1">serviceWorker</span><span class="dl">'</span> <span class="k">in</span> <span class="nb">navigator</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">load</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nb">navigator</span><span class="p">.</span><span class="nx">serviceWorker</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="dl">'</span><span class="s1">/sw.js</span><span class="dl">'</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">registration</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">ServiceWorker registration successful with scope: </span><span class="dl">'</span><span class="p">,</span> <span class="nx">registration</span><span class="p">.</span><span class="nx">scope</span><span class="p">);</span>
<span class="p">}).</span><span class="k">catch</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">ServiceWorker registration failed: </span><span class="dl">'</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This checks to see if the browser supports the API and then installs the service worker from <code class="language-plaintext highlighter-rouge">/sw.js</code>. It also removes the old cache if you bump up the version number ensuring your users download new assets if you want to make an update.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// sw.js</span>
<span class="kd">var</span> <span class="nx">SITE_NAME</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">your-site</span><span class="dl">'</span>
<span class="kd">var</span> <span class="nx">CACHE_NAME</span> <span class="o">=</span> <span class="nx">SITE_NAME</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">-1</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">urlsToCache</span> <span class="o">=</span> <span class="p">[</span>
<span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">/index.html</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">/css/style.css</span><span class="dl">'</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">/js/main.js</span><span class="dl">'</span>
<span class="p">];</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">install</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Perform install steps</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">waitUntil</span><span class="p">(</span>
<span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_NAME</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">cache</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">addAll</span><span class="p">(</span><span class="nx">urlsToCache</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nb">self</span><span class="p">.</span><span class="nx">skipWaiting</span><span class="p">());</span>
<span class="p">})</span>
<span class="p">);</span>
<span class="p">});</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">activate</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">waitUntil</span><span class="p">(</span>
<span class="nx">caches</span><span class="p">.</span><span class="nx">keys</span><span class="p">().</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">cacheNames</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span>
<span class="nx">cacheNames</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">cacheName</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">CACHE_NAME</span> <span class="o">!==</span> <span class="nx">cacheName</span>
<span class="o">&&</span> <span class="nx">cacheName</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="nx">SITE_NAME</span><span class="p">))</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">caches</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">cacheName</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">);</span>
<span class="p">})</span>
<span class="p">);</span>
<span class="p">});</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">fetch</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">event</span><span class="p">.</span><span class="nx">respondWith</span><span class="p">(</span>
<span class="nx">caches</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">)</span>
<span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>This will install a service worker that serves up your <code class="language-plaintext highlighter-rouge">index.html</code> and main CSS and JavaScript assets. Next time you load the page it will appear offline. The key events are installing the cache, an activate event that clears the old cache, and a fetch event that interrupts network requests.</p>
<h1 id="updating-the-worker">Updating the worker</h1>
<p>You will find yourself wanting to update assets at some point and might be frustrated when your service worker refuses to download the new version of things. It is possible to do a background fetch for new resources and replace that item in the cache, but there is a simpler way.</p>
<p>You can just bump up the version of the <code class="language-plaintext highlighter-rouge">sw.js</code> at the top such as:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">SITE_NAME</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">your-site</span><span class="dl">'</span>
<span class="kd">var</span> <span class="nx">CACHE_NAME</span> <span class="o">=</span> <span class="nx">SITE_NAME</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">-1</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p>Becomes;</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">SITE_NAME</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">your-site</span><span class="dl">'</span>
<span class="kd">var</span> <span class="nx">CACHE_NAME</span> <span class="o">=</span> <span class="nx">SITE_NAME</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">-2</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p>This works because when the browser checks the <code class="language-plaintext highlighter-rouge">sw.js</code> file and whether it should install the new version, it checks to see if they are byte equivalent. Changing a number will prompt a reinstall.</p>
<h1 id="finally">Finally</h1>
<p>This technology is really new, and there’s a <a href="https://github.com/GoogleChrome/sw-toolbox">bunch of tools</a> made by google that substantially extend the functionality by adding offline support for messaging and even google analytics. You can also add support for caching fonts based on the response from google and even CDN based resources.</p>
<p>The point of this post is to show that it’s <em>very</em> easy to add a simple service worker to your site. Hopefully in the future all sites will have some sort of offline ability, and with phones having more and more storage space, it wouldn’t be unreasonable for you to cache your most visited sites to have an uninterrupted experience on the web.</p>If you’ve been paying attention to new technologies on the web one thing you have not missed is Service Workers. They’re a new take on the idea of progressive enhancement and I think they’re going to stick around for a while yet.Loops, Closures and Ajax2016-12-30T05:21:00+00:002016-12-30T05:21:00+00:00https://davidyoung.tech/loops-closures-and-ajax<p>Scope in JavaScript is one of its more peculiar features that tends to trip up developers as they get started with the language. One issue that came up again and again while I was teaching last semester was the issue of performing asynchronous callbacks in loops, and why things were acting funny.</p>
<h1 id="strange-syntax">Strange syntax</h1>
<p>To be fair, this syntax does come across as strange, and even when I first saw it, I wasn’t quite sure how it was solving the problem.</p>
<p>Let’s consider the contrived example below where we have an array of elements, and for some reason we are going to make a get request to the index page a number of times asynchronously, and within each loop print the <code class="language-plaintext highlighter-rouge">i</code>-th member of the array from within the callback function. That looks like the following.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">items</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">cat</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">dog</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">cow</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">rabbit</span><span class="dl">'</span><span class="p">];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">index.html</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">items</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span> <span class="c1">// What is i?</span>
<span class="p">});</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Would you believe that the above example prints out <code class="language-plaintext highlighter-rouge">undefined</code> four times? Why does it not print out each element of the array as we go through the loop?</p>
<h1 id="how-javascript-is-asynchronous">How JavaScript is asynchronous</h1>
<p>The issue lies with the fact that we are performing an <code class="language-plaintext highlighter-rouge">XHR</code> request, which we’ve abstracted away from ourselves by using jQuery’s <code class="language-plaintext highlighter-rouge">$.get</code>. These requests, if they return, won’t execute their function callbacks until the callstack is empty, after our loop is well and truly <em>over</em>.</p>
<p>One thing that needs to be understood is that an <code class="language-plaintext highlighter-rouge">XHR</code> or <code class="language-plaintext highlighter-rouge">$.get</code> request is asynchronous, and most people get that. But what can be confusing is the way the <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop">event loop</a> works and how javascript somehow magically managed to do something asynchronously, when it’s supposedly a single threaded language.</p>
<p>Essentially once the callstack has cleared, that being our loop has ended and fired off all of the requests, our value of <code class="language-plaintext highlighter-rouge">i</code> is actually 4. We go through the loop performing 4 asynchronous requests, and then once <code class="language-plaintext highlighter-rouge">i</code> becomes 4 we exit the loop.</p>
<p>Once the stack is cleared, finished requests are given a chance to execute their callback functions. Since our loop is long finished, <code class="language-plaintext highlighter-rouge">i</code> is happily holding the value <code class="language-plaintext highlighter-rouge">4</code> meaning we are trying to look up <code class="language-plaintext highlighter-rouge">items[4]</code>, which is obviously undefined.</p>
<h1 id="solving-the-problem">Solving the problem</h1>
<p>There is a well-defined solution to the problem, although performing it can be utterly confusing and to be honest, I have to write out my closures carefully. As we make each <code class="language-plaintext highlighter-rouge">$.get</code> request in the loop, we need to <em>rescope</em> <code class="language-plaintext highlighter-rouge">i</code>, so that when our request returns, <code class="language-plaintext highlighter-rouge">i</code> is what we expect it to be. We sort of make a copy of it, making sure it remains at the correct value for each request.</p>
<p>Closures are an interesting way of forcing variables to take on new scope and ensuring that in the context of your callback function, they are what you expect them to be. The example below correctly prints out each element of the array.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">items</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">cat</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">dog</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">cow</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">rabbit</span><span class="dl">'</span><span class="p">];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">index.html</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">items</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">})(</span><span class="nx">i</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This prints out each animal, in an undefined order, because the requests could come back in any order, but alas it prints them all. The key different is how we wrote our callback function. Here’s the original <code class="language-plaintext highlighter-rouge">$.get</code> request again.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">index.html</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">items</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>The humble <code class="language-plaintext highlighter-rouge">$.get</code> function provided by jQuery takes two parameters, the URL to request, and the callback function. So we need to pass in something as the second parameter that returns the type of function it expects, and also copies in our index <code class="language-plaintext highlighter-rouge">i</code>.</p>
<p>We can’t simply do something like pass in the index, such as <code class="language-plaintext highlighter-rouge">function(data, i)</code>. That doesn’t work so we need to look at our solution that uses the closure to rescope the variable. Here’s the request making use of the closure again, but I’m going to remove the outer request and focus on the closure.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// what $.get wants</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">items</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">})(</span><span class="nx">i</span><span class="p">)</span>
</code></pre></div></div>
<p>The first thing that looks strange is probably that fact that we start with a <code class="language-plaintext highlighter-rouge">(</code> and appear to be wrapping our function in another closing bracket. We then immediately have <code class="language-plaintext highlighter-rouge">(i)</code> at the end and this supposedly returns the inner function we want.</p>
<p>This is a self-calling function, that after defined, since we have the <code class="language-plaintext highlighter-rouge">(i)</code> at the end, calls itself with those parameters. This creates new scope for the variable <code class="language-plaintext highlighter-rouge">i</code> and we are able to use it as we expect. We can even call the inner value something else for clarity such as.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">otherI</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">items</span><span class="p">[</span><span class="nx">otherI</span><span class="p">]);</span> <span class="c1">// use the scoped index</span>
<span class="p">}</span>
<span class="p">})(</span><span class="nx">i</span><span class="p">)</span> <span class="c1">// pass in the current value of i in the loop</span>
</code></pre></div></div>
<p>By passing in our value <code class="language-plaintext highlighter-rouge">i</code>, the insides of the braces, our <em>closure</em> has new scope on the variable and the array is accessed as you expect.</p>
<h1 id="is-there-another-way">Is there another way</h1>
<p>This can take time to understand and at first can be very frustrating. This is different to how other languages behave and led to the proposal for a type of variable with block scope. If we change the index to use the <code class="language-plaintext highlighter-rouge">let</code> identifier, we can use our original logic.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">items</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">cat</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">dog</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">cow</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">rabbit</span><span class="dl">'</span><span class="p">];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// using let</span>
<span class="nx">$</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">index.html</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">items</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span> <span class="c1">// works</span>
<span class="p">});</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The above code prints out each element of the array, like our closure solution did. You can check out the <a href="http://caniuse.com/#search=let">current support</a> and it’s all quite green, but still in production you need to accept that some people are on older versions of IE or on Opera Mini.</p>
<h1 id="finally">Finally</h1>
<p>Closures are a complicated part of the language, but if you come to understand their function you can make powerful use of them to ensure pieces of code do not interfere with each other.</p>
<p>Hopefully this brief look into their function makes it easier to understand why your piece of code did not work the way you hoped at first. Maybe you’ll use a closure, or start using <code class="language-plaintext highlighter-rouge">let</code>. Either way you’ve tapped into a cool part of the language that I’ll probably write more about in the future.</p>Scope in JavaScript is one of its more peculiar features that tends to trip up developers as they get started with the language. One issue that came up again and again while I was teaching last semester was the issue of performing asynchronous callbacks in loops, and why things were acting funny.Live HTMLCollection2016-12-14T02:00:15+00:002016-12-14T02:00:15+00:00https://davidyoung.tech/live-htmlcollection<p>For most of the time I’ve been writing JavaScript I’ve had jQuery there to hold me up, providing an assortment of helper functions and methods that I <em>think</em> make life easier. I mean I’m fairly sure they’re supposed to, that’s what it says in their documentation. I realised I had never really tried to make a proper web application without it, so decided it was about <a href="https://dayvidwhy.github.io/local-to-do/">time to do so</a>.</p>
<h1 id="where-are-you-jquery">Where are you jQuery?</h1>
<p>I decided that a to-do type application that made use of local storage to remember tasks would be a good starting point, it would let me play with a web API and do some UI state management that’s incredibly easy to do in jQuery.</p>
<p>A lot of what this blog post wants to address comes from me trying to be somewhat clever. I have become incredibly used to the typical jQuery style selectors like <code class="language-plaintext highlighter-rouge">$(".class")</code> and figured how hard could that be to reproduce in a simple function. Behold.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">$</span><span class="p">(</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">element</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">#</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">element</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">.</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="nx">element</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nx">element</span><span class="p">.</span><span class="nx">length</span><span class="p">));</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">getElementsByTagName</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Seems good right? If we want an ID based element we use this <code class="language-plaintext highlighter-rouge">querySelector</code> method, or for a class we make use of <code class="language-plaintext highlighter-rouge">getElementsByClassName</code> to return some sort of collection of all elements with that class.</p>
<p>I figured I was set and continued upon my efforts, until I encountered something interesting. I had discovered that <code class="language-plaintext highlighter-rouge">DOM</code> elements contain a list of classes they currently have, a fancy new feature that has great support, and figured what an excellent way to toggle the visibility than to add and remove a <code class="language-plaintext highlighter-rouge">show</code> class from this set.</p>
<p><img src="images/htmlcollection-error.png" alt="Error from indexOf" title="Error from indexOf" /></p>
<p>But it’s an array? Arrays have an <code class="language-plaintext highlighter-rouge">indexOf</code> function? This is when I started thinking I’d lost my touch a bit, but after a quick search around I discovered the culprit was that fact that this is <em>not</em> an array, but a <a href="https://developer.mozilla.org/en/docs/Web/API/DOMTokenList">DOMTokenList</a>.</p>
<p>There are some specific methods here for class management, which jQuery handles really well for us with their <code class="language-plaintext highlighter-rouge">.addClass</code> and <code class="language-plaintext highlighter-rouge">.removeClass</code> methods, that have fairly strict browser requirements. I started using <code class="language-plaintext highlighter-rouge">.add</code> and <code class="language-plaintext highlighter-rouge">.remove</code> and everything worked as expected avoiding <code class="language-plaintext highlighter-rouge">.replace</code> since chrome does not support it.</p>
<h1 id="collections-from-selections">Collections from selections</h1>
<p>My efforts picked up again after this, having felt as if I learned something, so I pressed on. The next issue I encountered was an oddly shrinking array. Having become very used to how jQuery style selectors work, I selected the elements I wanted to hide, those being the ones currently shown, and use <code class="language-plaintext highlighter-rouge">.hide()</code> on them. Image the following scenario.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"show"</span><span class="nt">></span>
<span class="nt"><p></span>Content<span class="nt"></p></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"show"</span><span class="nt">></span>
<span class="nt"><p></span>Content<span class="nt"></p></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"hide"</span><span class="nt">></span>
<span class="nt"><p></span>Content<span class="nt"></p></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>I have a couple of div elements currently showing that I would like to hide, so I attempted the following.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">shown</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">.show</span><span class="dl">"</span><span class="p">);</span> <span class="c1">// getElementsByClassName</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">shown</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">shown</span><span class="p">);</span>
<span class="nx">shown</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">classList</span><span class="p">.</span><span class="nx">remove</span><span class="p">(</span><span class="dl">'</span><span class="s1">show</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">shown</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">classList</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="dl">'</span><span class="s1">hide</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">shown</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">shown</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This is where things became interesting. I was looping over this array of 2 elements, removing their <code class="language-plaintext highlighter-rouge">show</code> class and then adding a <code class="language-plaintext highlighter-rouge">hide</code> class to their class lists, but only one element was ever toggling, the second one.</p>
<p>The thing happening here is that <code class="language-plaintext highlighter-rouge">document.getElementsByClassName</code> returns an <code class="language-plaintext highlighter-rouge">HTMLCollection</code>. An <a href="https://developer.mozilla.org/en/docs/Web/API/HTMLCollection">HTMLCollection</a> is a <em>live</em> collection that is <em>updated</em> when the DOM updates.</p>
<p>So what was happening there was as I removed the <code class="language-plaintext highlighter-rouge">show</code> class from the first element, the <code class="language-plaintext highlighter-rouge">shown</code> set of elements suddenly lost a member and went down to a length of 1. Now <code class="language-plaintext highlighter-rouge">shown[i]</code>, or <code class="language-plaintext highlighter-rouge">shown[0]</code> was in fact the <em>second</em> element I had selected since the first one had disappeared from under me. I then exit the array <em>early</em>. That’s confusing, so here’s a code snippet explaining the steps.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">shown</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">.show</span><span class="dl">"</span><span class="p">);</span> <span class="c1">// getElementsByClassName</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">shown</span><span class="p">)</span> <span class="c1">// [0-div1, 1-div2], 0- meaning 0th index</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">shown</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span> <span class="c1">// 2</span>
<span class="c1">// do for loop part</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">shown</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">);</span>
<span class="c1">// i starts at 0</span>
<span class="nx">shown</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">classList</span><span class="p">.</span><span class="nx">remove</span><span class="p">(</span><span class="dl">'</span><span class="s1">show</span><span class="dl">'</span><span class="p">);</span> <span class="c1">// remove class from 0th element</span>
<span class="cm">/* Live updating happens and our shown variable changes */</span>
<span class="nx">shown</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">classList</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="dl">'</span><span class="s1">hide</span><span class="dl">'</span><span class="p">);</span> <span class="c1">// adds the hide class to the second div</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">shown</span><span class="p">);</span> <span class="c1">// [1-div2] // our live collection is now one member shorter</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">shown</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span> <span class="c1">// 1</span>
<span class="c1">// i becomes 1 at end of loop</span>
<span class="c1">// check for loop</span>
<span class="c1">// exit loop since (i < shown.length) becomes (1 < 1)</span>
</code></pre></div></div>
<p>This can be fairly easily remedied by doing the operations in reverse and even using a while loop, I just found it profoundly odd that a live updating collection of elements is something that people would want. Here’s a way you could do it, using the fact that the length updates when a class is removed.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">shown</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">.show</span><span class="dl">"</span><span class="p">);</span> <span class="c1">// getElementsByClassName</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">shown</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// eventually the collection will empty</span>
<span class="nx">shown</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">classList</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="dl">'</span><span class="s1">hide</span><span class="dl">'</span><span class="p">);</span> <span class="c1">// do this first so it's not removed</span>
<span class="nx">shown</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">classList</span><span class="p">.</span><span class="nx">remove</span><span class="p">(</span><span class="dl">'</span><span class="s1">show</span><span class="dl">'</span><span class="p">);</span> <span class="c1">// change and remove from collection</span>
<span class="p">}</span>
</code></pre></div></div>
<p>I ended up revising my original function to leverage the better version of the query selector, <code class="language-plaintext highlighter-rouge">querySelectorAll</code>.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">$</span><span class="p">(</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">element</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">#</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="nx">element</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nx">element</span><span class="p">.</span><span class="nx">length</span><span class="p">));</span>
<span class="p">}</span>
<span class="c1">// fallback that should work for most</span>
<span class="k">return</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This meant I was dealing with <a href="https://developer.mozilla.org/en/docs/Web/API/NodeList">NodeLists</a> instead of the collections and the original logic worked fine, it was just interesting to see how different collections behave in the browser.</p>
<h1 id="types-of-collections-in-javascript">Types of collections in JavaScript</h1>
<p>You are probably now wondering how many collections there are, and if you use jQuery a lot like me, how have you avoided using them for so long? The interesting thing is, and I never thought about it this way, is that all selections of elements are collections.</p>
<p>Even jQuery wraps the elements it selects in a special <a href="https://learn.jquery.com/using-jquery-core/jquery-object/">jQuery object</a> with your favourite methods like <code class="language-plaintext highlighter-rouge">.text()</code> and <code class="language-plaintext highlighter-rouge">.click()</code> giving you access to jQuerys magical box of functionality.</p>
<p>If anything, creating this application made me question more of the inner workings of jQuery and I am now more aware of the type of collection I’m dealing with and the attached methods after using any sort of selector.</p>
<h1 id="finally">Finally</h1>
<p>This held me up a bit yesterday and I felt as if jQuery has slightly altered my understanding of how selectors work, but it was definitely a useful learning experience and I intend to keep attempting to implement more applications without jQuery. The main takeaway being, if it looks like an array in the console, it might not have the method you’re expecting, so double check!</p>For most of the time I’ve been writing JavaScript I’ve had jQuery there to hold me up, providing an assortment of helper functions and methods that I think make life easier. I mean I’m fairly sure they’re supposed to, that’s what it says in their documentation. I realised I had never really tried to make a proper web application without it, so decided it was about time to do so.Useful Web Skills2016-11-11T04:20:00+00:002016-11-11T04:20:00+00:00https://davidyoung.tech/useful-web-skills<p>A few people have asked me recently how I’ve managed to make heads or tails of the current state of the web, and how do you get to a point where this weird online world of development doesn’t freak you out too much. Well quite a lot of it still confuses me, but it’s definitely become easier.</p>
<p>I also feel like I can weigh in on this topic after teaching this past semester and can suggest a few things that would increase anyone’s ability to make effective websites.</p>
<h1 id="build-a-page-from-scratch">Build a Page from Scratch</h1>
<p>If there’s one thing that really accelerated my understanding of, and ability to write for the web, was doing everything from scratch at least a few times. I reached a point where I became frustrated with how many different frameworks there were and the number of CSS templates out there were immense.</p>
<p>I had noticed a lot of developers out there would suggest the use of <a href="https://getbootstrap.com/">bootstrap</a> right away for building pages, only to come to a halt later when some of the classes they used were not working the way they hoped. Often I would ask why they thought this class behaved this way and what CSS rules does it actually apply and they mostly weren’t sure.</p>
<p>I still use frameworks from time to time but I always investigate the behaviour of predefined classes myself before using them and I even built my <a href="https://dayvidwhy.github.io/daygrid/">own grid</a> to ensure I understood the concepts. Don’t always just assume you know how some piece of CSS works, try out its various attributes or value ranges.</p>
<h1 id="learning-semantics">Learning Semantics</h1>
<p>The <a href="https://www.w3.org/standards/semanticweb/">semantic web</a> is a standard that allows the web to start making a lot more sense. A lot of the data we put into pages has meaning beyond just the text we show. We can give our data more meaning quite easily with the proper syntax.</p>
<p>The latest thing I’ve become a fan of is the <code class="language-plaintext highlighter-rouge">itemscope</code> syntax. You can make links to blog posts much more meaningful like so. Here’s a blog link from my <a href="https://davidyoung.tech">portfolio</a> site.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"row"</span> <span class="na">itemscope=</span><span class="s">""</span> <span class="na">itemtype=</span><span class="s">"http://schema.org/Blog"</span> <span class="na">id=</span><span class="s">"blog"</span><span class="nt">></span>
<span class="nt"><article</span> <span class="na">role=</span><span class="s">"article"</span> <span class="na">itemtype=</span><span class="s">"http://schema.org/BlogPosting"</span> <span class="na">itemscope=</span><span class="s">"itemscope"</span><span class="nt">></span>
<span class="nt"><h3</span> <span class="na">itemprop=</span><span class="s">"name"</span><span class="nt">></span>
<span class="nt"><a</span> <span class="na">href=</span><span class="s">"http://blog.davidyoung.tech/software-process"</span> <span class="na">itemprop=</span><span class="s">"url"</span><span class="nt">></span>
Software Process
<span class="nt"></a></span>
<span class="nt"></h3></span>
<span class="nt"><p</span> <span class="na">itemprop=</span><span class="s">"description"</span><span class="nt">></span>
Some description...
<span class="nt"></p></span>
<span class="nt"><a</span> <span class="na">itemprop=</span><span class="s">"url"</span> <span class="na">href=</span><span class="s">"http://blog.davidyoung.tech/software-process"</span> <span class="na">class=</span><span class="s">"blog-link"</span><span class="nt">></span>
Read more..
<span class="nt"></a></span>
<span class="nt"></article></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>This rich semantic mark-up shows that this piece of code actually represents a blog post, and can actually communicate what parts reflect the name, or the description of it. We can specify the <code class="language-plaintext highlighter-rouge">itemscope</code> and tell the web <em>what</em> this thing is, and then say what each part represents. So the web knows that this is a blog post, and that it has a name, a description and a link to it for reading.</p>
<h1 id="accessibility-with-semantics">Accessibility with Semantics</h1>
<p>I recently jumped on the band wagon for making sure my site is readable to everyone. In my opinion every site needs to be a place that doesn’t restrict who can view the content. Semantic tags with implied aria roles help here and the following mark-up demonstrates a common structure you should be adopting for your pages.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- Great semantics! --></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>A title<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><header></span>
Header stuff, like your nav-bar, or top banner.
<span class="nt"></header></span>
<span class="nt"><main></span>
Main content that you want readers to look at.
<span class="nt"></main></span>
<span class="nt"><footer></span>
The thing at the bottom of the page.
<span class="nt"></footer></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>This is much better for screen readers given the good use of semantic tags breaking up the page into three clear body parts, the header, main and the footer. This is vastly better than the following.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- Not so great semantics --></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>A Title<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"cool-top-banner"</span><span class="nt">></span>
Header stuff, like your nav-bar, or top banner.
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"main-stuff"</span><span class="nt">></span>
Main content that you want readers to look at.
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"footer-bit"</span><span class="nt">></span>
The thing at the bottom of the page.
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Mostly because the first one is more readable, but also because of the implied aria labels. The <code class="language-plaintext highlighter-rouge"><header></code> tag has an implicit <code class="language-plaintext highlighter-rouge">role=banner</code> associated with it. It’s possible to give this back with aria labels but why not just use the proper mark-up in the first place?</p>
<p>If you have not done much with aria labels before I highly recommend reading <a href="https://www.w3.org/TR/wai-aria/">the spec</a> or <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute">looking at Mozilla’s guide</a> on the matter.</p>
<h1 id="inspect-everything">Inspect Everything</h1>
<p>One of the best things you can do while learning is to inspect almost every page you come across. Look inside the head tag, look at the properties they gave their <code class="language-plaintext highlighter-rouge"><p></code> tags and look at what classes they used and why. Look at how they lay out their content.</p>
<p>Things that usually interest me are:</p>
<ul>
<li>Did they use a grid or are they using flexbox?</li>
<li>How did they set the background colour of this element, does it cascade down from a higher class for some reason?</li>
<li>What is in the <code class="language-plaintext highlighter-rouge"><head></code> tag? Which usually leads onto the next point.</li>
<li>What framework, if any, are they using?</li>
<li>How are they loading their CSS, in a blob or throughout the HTML? Breaking up CSS has become the cool new thing lately.</li>
<li>Are they using a web-font and how are they loading it? Are they using <a href="https://modernizr.com/">modernizr</a> or lazy loading it?</li>
</ul>
<p>Because it’s pretty interesting to see how some people make their pages, and sometimes they leave small comment messages for you to see.</p>
<h1 id="development-tools">Development Tools</h1>
<p>Learning to use the dev tools provided in Chrome and Firefox will increase your productivity ten-fold. Lately I’ve become a fan of just jamming around in the elements tab manually adjusting some HTML and CSS making the page look the way I want live instead of going back to my editor.</p>
<p>You can try out new ideas fairly rapidly without making huge changes to your code this way. Sure you can make a commit, make some changes and refresh the page to see what it looks like, I just find it very cool that I can change CSS instantly in the browser on the fly.</p>
<p>This is really helpful early on as well for understand what each CSS rule does since you can flick them on and off easily with the checkboxes. Lately I’ve become a bit obsessed with the chrome dev tools, mainly because of the timeline feature.</p>
<h1 id="finally">Finally</h1>
<p>These are just some of the things I wish my teachers had pushed on me a bit more when I was first learning the hypertext mark-up language and I can assure anyone that if you want to get better at making stuff on the web awesome, you need to understand these things.</p>A few people have asked me recently how I’ve managed to make heads or tails of the current state of the web, and how do you get to a point where this weird online world of development doesn’t freak you out too much. Well quite a lot of it still confuses me, but it’s definitely become easier.Software Process2016-11-02T04:20:00+00:002016-11-02T04:20:00+00:00https://davidyoung.tech/software-process<p>Something I have been struggling to understand is why some developers dislike courses that attempt to teach the software process. Apparently these are considered a “waste of time”. I would like to take a moment to give you reasons as to why this is important learning material.</p>
<h1 id="working-together">Working together</h1>
<p>I have reached the end of my time at university and while I have learned so many things, the most important of these is how to work with others to build software. There are a number of courses that teach the basics of languages such as C, Java, Python, JavaScript and other web languages like PHP. I feel like I have come out with a good knowledge of each, but it is important to remember that these languages are really just the <em>tools</em> we use to make great things.</p>
<blockquote>
<p>Languages are the tools for building great things.</p>
</blockquote>
<p>Courses with a focus on teaching these tools are very important but, for the longest time at university I was wondering how people effectively work together to actually get stuff done.</p>
<h1 id="collaborative-process">Collaborative process</h1>
<p>I have been learning a lot about how to collaborate effectively through several courses at University. The biggest improvement to my learning was picking up git and getting started with Github. Git is the defacto “let’s work together” piece of software that everyone knows and loves, but there are more people need to start using early on.</p>
<h1 id="using-tools">Using tools</h1>
<p>I found myself working in a pretty standard manner for each group project in my final year. We would always setup <a href="http://slack.com">Slack</a>, <a href="http://trello.com">Trello</a> and a <a href="https://github.com">GitHub</a> repository and use all of these to work together.</p>
<p>Trello really is invaluable for working together. Github recently introduced their own project slash Trello board like tracking system and it’s amazing. Trello works in a similar way where you can create small tickets that you assign to people, similar to github issues. Being able to look over these tickets is great for tracking your team. Slack is also an incredibly beneficial chat tool to use.</p>
<h1 id="agile-processes">Agile processes</h1>
<p>There are a few courses at university that attempt to teach Agile and the concepts of Scrum. After doing courses like CSSE3002, the software process, and DECO3800/3801, final year design and build, I can safely say I am familiar with Agile. They even put marks towards using your Trello board consistently to operate in this manner.</p>
<p>An interesting thing that I learned this semester was how effective it is to work in short sprints to complete tasks. Setting short periods of time to achieve goals results in goals that are much more reasonable and more likely to be completed. It also gives you a chance to finish a piece of content and get feedback from your client right away.</p>
<p>This links <a href="https://davidyoung.tech/getting-feedback">back to another post</a> I made about the importance of feedback. By developing software in this manner you can get this valuable feedback consistently and most effectively communicate your progress to your client.</p>
<h1 id="agile-feedback">Agile feedback</h1>
<p>I was asked by one of my lecturers towards the end of this semester for feedback on the use of agile for in courses. While I feel that setting goals for to achieve agile usage is very useful, there is always the risk that it won’t be taken seriously enough.</p>
<p>If this was a workplace and people had spent a long time trying to get a job here, the process would be taken a lot more seriously, small checkpoints and sprints would be adhered to. However, I’m still happy to have had the learning experience.</p>
<h1 id="finally">Finally</h1>
<p>Throughout this semester I have had a lot of chances to work with others to accomplish much larger tasks than I would be able to on my own. I firmly believe that these tools and processes have been the reason my group projects have gone so well.</p>Something I have been struggling to understand is why some developers dislike courses that attempt to teach the software process. Apparently these are considered a “waste of time”. I would like to take a moment to give you reasons as to why this is important learning material.Easy jQuery Selectors2016-10-06T05:26:00+00:002016-10-06T05:26:00+00:00https://davidyoung.tech/easy-jquery-selectors<p>The popular web plugin <a href="https://jquery.com/">jQuery</a> is currently in its third version and is still going strong on the internet. Lately it has become less popular as the web platform catches up and DOM altering methods become more standard across browsers, but some parts of it are still very useful to the novice web developer.</p>
<h1 id="jquery">jQuery</h1>
<p>Probably the biggest point I have seen from people that have done some website development before is that jQuery is not helpful, <a href="https://github.com/jquery/jquery.com/issues/88#issuecomment-72400007">and it does have its problems</a> with performance. Many of its functions have big performance hits to do simple things, but it is still a very convenient library to use.</p>
<p>jQuery is well known for being old and clunky with its a large library weighing in at 28kB for the second flavour, and it takes a phones browser about 500ms on average to parse all of the code. Not the greatest.</p>
<p>What you might not have realised is that jQuery actually offer a <a href="https://learn.jquery.com/performance/">section on their website</a> about getting the most out of the library. The biggest one is probably actually reading the jQuery source and not treating it like a magical box. I watched a <a href="https://www.youtube.com/watch?v=i_qE1iAmjFg">video</a> by Paul Irish where he actually goes through the code seeing what can be learned. It is about an older version, but the idea is still relevant.</p>
<h1 id="plain-javascript">Plain JavaScript</h1>
<p>JavaScript has a range of selectors that facilitate grabbing elements on the page and then doing things to them, as follows.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="dl">"</span><span class="s2">class</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByID</span><span class="p">(</span><span class="dl">"</span><span class="s2">id</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">"</span><span class="s2">id</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="dl">"</span><span class="s2">div input</span><span class="dl">"</span><span class="p">);</span> <span class="c1">// all inputs inside a div</span>
</code></pre></div></div>
<p>Now while <code class="language-plaintext highlighter-rouge">querySelector</code> is very easy to use and it’s brother, <code class="language-plaintext highlighter-rouge">querySelectorAll</code> covers a range of bases with complex selectors, jQuery style selectors are still substantially easier to understand.</p>
<p>We can use fully fledged CSS selectors to grab elements even using pseudo selectors like <code class="language-plaintext highlighter-rouge">:first-child</code> and <code class="language-plaintext highlighter-rouge">:not</code></p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">.cool-class</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">#that-id</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">image</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">.sections .headings:not(:first-child)</span><span class="dl">"</span><span class="p">);</span>
</code></pre></div></div>
<p>Probably the most interesting part is how we use the same selection statement, <code class="language-plaintext highlighter-rouge">$('thing')</code> and we can clearly see whether we are selecting an <code class="language-plaintext highlighter-rouge">#id</code> or a <code class="language-plaintext highlighter-rouge">.class</code> thanks to the inclusion of a <code class="language-plaintext highlighter-rouge">.</code> or <code class="language-plaintext highlighter-rouge">#</code>. Of note as well is how easy it is to then iterate over these elements using <code class="language-plaintext highlighter-rouge">$.each()</code> by simply providing a callback function.</p>
<h1 id="iterating-over-class-selections">Iterating Over Class Selections</h1>
<p>One thing that bothers me about <code class="language-plaintext highlighter-rouge">getElementByClassName</code> is how it returns an array and I need to loop over this to do something to each element.</p>
<p>For instance if we grabbed a bunch of navigation elements.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="dl">"</span><span class="s2">nav-links</span><span class="dl">"</span><span class="p">);</span>
</code></pre></div></div>
<p>To change them all to red we need to do something like this.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">x</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">x</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">style</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">red</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>So we have a few concepts here that need to be understood well before that line in the middle makes sense. We need to understand array indexes, and that DOM objects, surprisingly, actually are objects. Accessing the style element of a DOM object seems obvious when you’re more experienced but I suggest that early on he similar jQuery version is much clearer.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">.nav-links</span><span class="dl">"</span><span class="p">).</span><span class="nx">css</span><span class="p">(</span><span class="dl">"</span><span class="s2">color</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">red</span><span class="dl">"</span><span class="p">);</span>
</code></pre></div></div>
<p>I can see that for all things with the class <code class="language-plaintext highlighter-rouge">.nav-links</code> I am changing their color to red.</p>
<h1 id="making-api-requests">Making API Requests</h1>
<p>Making use of API’s in plain JavaScript just isn’t fun as well, and trying to diagnose an issue in the depths of this code.</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">xhttp</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">XMLHttpRequest</span><span class="p">();</span>
<span class="nx">xhttp</span><span class="p">.</span><span class="nx">onreadystatechange</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">==</span> <span class="mi">4</span> <span class="o">&&</span> <span class="k">this</span><span class="p">.</span><span class="nx">status</span> <span class="o">==</span> <span class="mi">200</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//do stuff with this.response</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">xhttp</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="dl">"</span><span class="s2">GET</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">link_to_amaze.json</span><span class="dl">"</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="nx">xhttp</span><span class="p">.</span><span class="nx">send</span><span class="p">();</span>
</code></pre></div></div>
<p>This isn’t making anyone happy. The new <a href="https://developer.mozilla.org/en/docs/Web/API/Fetch_API">fetch</a> API does start making this easier however the old jQuery;</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$</span><span class="p">.</span><span class="nx">getJSON</span><span class="p">(</span><span class="dl">"</span><span class="s2">link_to_amaze.json</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span> <span class="c1">//print the data</span>
<span class="p">});</span>
</code></pre></div></div>
<p>This is a lot easier to get our heads around and start making meaningful web applications that plug in external information sources.</p>
<p>Also specifying the <code class="language-plaintext highlighter-rouge">&callback=?</code> in the URL we pass to <code class="language-plaintext highlighter-rouge">$.getJSON</code> seamlessly deals with <code class="language-plaintext highlighter-rouge">JSONP</code> requests and we don’t have to spend time figuring out how to load JSON as the source of a script tag.</p>
<h1 id="finally">Finally</h1>
<p>jQuery has its weak points and has become less popular, but its <a href="http://api.jquery.com/">developer API</a> is very available if you want to read further. I would highly recommend learning jQuery as an extension of their general JavaScript knowledge.</p>The popular web plugin jQuery is currently in its third version and is still going strong on the internet. Lately it has become less popular as the web platform catches up and DOM altering methods become more standard across browsers, but some parts of it are still very useful to the novice web developer.