<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Paul Facklam</title>
    <description>The latest articles on Forem by Paul Facklam (@pfacklam).</description>
    <link>https://forem.com/pfacklam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F248468%2F1a2f6ad3-a625-4a72-be2e-7c104d4235b9.jpeg</url>
      <title>Forem: Paul Facklam</title>
      <link>https://forem.com/pfacklam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pfacklam"/>
    <language>en</language>
    <item>
      <title>Are you a good developer already?</title>
      <dc:creator>Paul Facklam</dc:creator>
      <pubDate>Tue, 16 Feb 2021 13:09:25 +0000</pubDate>
      <link>https://forem.com/pfacklam/are-you-a-good-developer-already-3j2n</link>
      <guid>https://forem.com/pfacklam/are-you-a-good-developer-already-3j2n</guid>
      <description>&lt;p&gt;As a trainer at &lt;a href="https://dev.to/clicksolutions"&gt;click solutions&lt;/a&gt;, I regularly supervise trainees and students. Through appropriate onboarding and the teaching of technical content they grow from beginners to real developers. Sometimes even really good developers.&lt;/p&gt;

&lt;h1&gt;
  
  
  What are good developers and what distinguishes them?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/aNqEFrYVnsS52/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/aNqEFrYVnsS52/giphy.gif" alt="A good developer? - Cat on a notebook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probably not 😉. I think being a good developer it is definitely not related to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;typing fast (maybe even faster than this cat),&lt;/li&gt;
&lt;li&gt;the number of lines of code per day or&lt;/li&gt;
&lt;li&gt;even the theme on your favorite editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my understanding a good developer...&lt;/p&gt;

&lt;h3&gt;
  
  
  ... writes working code
&lt;/h3&gt;

&lt;p&gt;That comes as a surprise, huh? But yes, good developers make sure that their code works. They do this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;thinking about it in detail&lt;/strong&gt; - What can go wrong? Beginners are usually too optimistic and think too little about the case of failure. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;planning it&lt;/strong&gt; - Do I have all the information? Are there any side effects? Beginners often start typing immediately to get things done quickly. Not always the best way to write good code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;testing it&lt;/strong&gt; - Are all requirements met? Does everything work as expected or am I overlooking something? Beginners sometimes don't test their own piece of code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ... has internalized KISS
&lt;/h3&gt;

&lt;p&gt;Just to clarify. When I say KISS I don't mean the &lt;a href="https://en.wikipedia.org/wiki/Kiss_(band)" rel="noopener noreferrer"&gt;hard rock band from the 80s&lt;/a&gt;. It's more the demand to strive for the simplest solution possible for a certain problem. So, &lt;strong&gt;K&lt;/strong&gt;eep &lt;strong&gt;I&lt;/strong&gt;t &lt;strong&gt;S&lt;/strong&gt;imple, &lt;strong&gt;S&lt;/strong&gt;tupid! Good developers do that (because they are not stupid, right? 😉).&lt;/p&gt;

&lt;h3&gt;
  
  
  ... has understood DRY
&lt;/h3&gt;

&lt;p&gt;Copy &amp;amp; Paste? No, thank you. Rather: &lt;strong&gt;D&lt;/strong&gt;on't &lt;strong&gt;R&lt;/strong&gt;epeat &lt;strong&gt;Y&lt;/strong&gt;ourself. Good developers do repeat themselves, they encapsulate functionality - even if time is running out again. This prevents errors or inconsistencies and increases maintainability at the same time.&lt;/p&gt;

&lt;h3&gt;
  
  
  ... never stops learning
&lt;/h3&gt;

&lt;p&gt;Technologies/Frameworks come and go. The IT sector is determined by constantly changing requirements and innovations. State-of-the-art topics of today may already be outdated tomorrow. Good developers are aware of this fact and educate themselves independently. Ideally, they love to learn for life.&lt;/p&gt;

&lt;h3&gt;
  
  
  ... has learned to work in a team
&lt;/h3&gt;

&lt;p&gt;A good developer has understood that working together is faster, better and makes way more fun than being a lone wolf. They share their code &amp;amp; knowledge, ask for help and help others. Lone wolfs may do a good job, but teams do amazing things.&lt;/p&gt;

&lt;h3&gt;
  
  
  ... wants to get better (every day)
&lt;/h3&gt;

&lt;p&gt;Working in a team brings certain advantages. For example, you always have someone you can ask for advice or feedback. Feedback is a very good way to develop yourself further, as it gives you insight into the way others think and see things, especially about your code or the way you got there. A good developer knows that and asks for feedback to get better (maybe even every day).&lt;/p&gt;

&lt;h3&gt;
  
  
  ... communicates (in time and purposefully)
&lt;/h3&gt;

&lt;p&gt;Problems occur from time to time - they are inevitable. But good developers know when they have lost their way without getting ahead on their own and communicate this before reaching a point of no return (e.g. missing an important deadline). But the same applies when there is something that prevent them from being productive or when they have open questions (e.g. unclear requirements from business side).&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;There are many aspects to being a good developer, but please remember: no one is born a master or is even perfect. Aiming to be a better developer already takes you a big step further. If you take the time and work on yourself, the rest will come naturally.&lt;/p&gt;

&lt;p&gt;Maybe one more not so unimportant thought at the end. To become a good developer, however, you have to do one thing above all: practice, practice, practice... Practice makes perfect! 😄&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do you think? What makes a good developer for you? Let's discuss in the comments!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you liked this post, please give me a ❤️ or even a 🦄 and feel free to follow &lt;a href="https://dev.to/pfacklam/"&gt;me&lt;/a&gt; on dev.to. Appreciate it! ✌️&lt;/p&gt;

&lt;p&gt;Finally a few more articles from me. Check it out!&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/pfacklam" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F248468%2F1a2f6ad3-a625-4a72-be2e-7c104d4235b9.jpeg" alt="pfacklam"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/pfacklam/native-lazy-loading-of-images-with-zero-javascript-3hnf" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Native lazy-loading of images with zero Javascript&lt;/h2&gt;
      &lt;h3&gt;Paul Facklam ・ Feb 8 '21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#html&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/pfacklam" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F248468%2F1a2f6ad3-a625-4a72-be2e-7c104d4235b9.jpeg" alt="pfacklam"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/pfacklam/the-power-of-template-literals-4e7e" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;The power of Template Literals&lt;/h2&gt;
      &lt;h3&gt;Paul Facklam ・ Feb 19 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#codenewbie&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Native lazy-loading of images with zero Javascript</title>
      <dc:creator>Paul Facklam</dc:creator>
      <pubDate>Mon, 08 Feb 2021 12:04:18 +0000</pubDate>
      <link>https://forem.com/pfacklam/native-lazy-loading-of-images-with-zero-javascript-3hnf</link>
      <guid>https://forem.com/pfacklam/native-lazy-loading-of-images-with-zero-javascript-3hnf</guid>
      <description>&lt;h1&gt;
  
  
  About lazy-loading and why you should use it
&lt;/h1&gt;

&lt;p&gt;The worldwide web has evolved over the past decades and today's websites consist not only of text and color, but also of countless media content. First and foremost images.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/path/to/your/image.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Awesome image"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;But what does this have to do with lazy-loading?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lazy-loading is a technique that defers loading of non-critical resources at page load time. Instead, these non-critical resources are loaded at the moment of need. Where images are concerned, "non-critical" is often synonymous with "off-screen".&lt;br&gt;
-- &lt;cite&gt;from &lt;a href="https://web.dev/lazy-loading/" rel="noopener noreferrer"&gt;web.dev/lazy-loading&lt;/a&gt; written by Jeremy Wagner and Rachel Andrew&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means by using lazy-loading we achieve the following benefits over the classic embedding in HTML:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance Gains&lt;/strong&gt; - With lazy-loading we can improve loading speed by reducing the number of images that need to be loaded initially.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost reduction&lt;/strong&gt; - A lazy loaded image may never need to load because the user never reaches the image's position on the page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok, sounds good. How can we make that happen? What do we need for this? Let's get started!&lt;/p&gt;
&lt;h1&gt;
  
  
  The old (Javascript) approach
&lt;/h1&gt;

&lt;p&gt;There are a lot of snippets and scripts like &lt;a href="https://github.com/verlok/vanilla-lazyload" rel="noopener noreferrer"&gt;vanilla-lazyload&lt;/a&gt; out there that enable lazy-loading via javascript. In almost all cases a data attribute is used to prevent upfront image loading.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 html
&amp;lt;img data-src="/path/to/your/image.jpg" alt="Awesome image" /&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;But how is the image loaded at all? To achieve this, one of the following two techniques is usually used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event listeners&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This technique uses event listeners on the scroll, resize and orientationChange events in the browser. If one of the mentioned events is fired and assuming the image enters the viewport the data-src attribute is replaced with the src attribute to trigger the loading call. See it in action:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/imagekit_io/embed/MBNwKB?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Intersection Observer API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike the first method, the image is observed (asynchronously) by using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API" rel="noopener noreferrer"&gt;IntersectionObserver API&lt;/a&gt;. The image is then loaded by changing the &lt;code&gt;data-src&lt;/code&gt; to &lt;code&gt;src&lt;/code&gt; attribute as soon as it enters the viewport.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/imagekit_io/embed/BPXQZZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;But what if I told you that you don't need Javascript at all? 😲 Yes, you heard right! Zero Javascript.&lt;/p&gt;
&lt;h1&gt;
  
  
  The new (HTML) approach
&lt;/h1&gt;

&lt;p&gt;So what does this new way of lazy-loading look like? No worries, it's perfectly simple. You just have to add &lt;code&gt;loading="lazy"&lt;/code&gt; to your image tag and that's it. 😎&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/path/to/your/image.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;With this new loading attribute, you can completely defer the loading of offscreen images (and even iframes in some browsers) to when they enter the viewport. Enough talking, let's see it in action!&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/pfacklam/embed/eYBmeyx?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The attribute comes with three values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;auto&lt;/strong&gt; - (Default) equal to not including the attribute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lazy&lt;/strong&gt; - Defer loading of resources until it enters the viewport.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;eager&lt;/strong&gt; - Load the resource immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What about browser support?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The attribute is supported by almost every popular browser (Chrome, Edge, Opera and Firefox). The implementation for Safari is in &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=200764" rel="noopener noreferrer"&gt;progress and almost done&lt;/a&gt;. If you need more detailed information on cross-browser support &lt;a href="https://caniuse.com/loading-lazy-attr" rel="noopener noreferrer"&gt;caniuse.com&lt;/a&gt; is your friend. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if a browser does not support the attribute?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Browsers that do not support the loading attribute simply ignore it without any side-effects. Fortunately, there is a polyfill at Github available named &lt;a href="https://github.com/mfranzke/loading-attribute-polyfill" rel="noopener noreferrer"&gt;loading-attribute-polyfill&lt;/a&gt; which can be used in those cases.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;HTMLImageElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Cool! The browser supports the loading attribute&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Houston... We need a polyfill!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Are there any limitations?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even though it is pretty cool to let the browser do the lazy-loading work, you should be aware of some limitations that come into play when using the attribute:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlike the Javascript variants, you do not have any influence on the threshold to load the resource. It is part of the browser code and can't be changed for now.&lt;/li&gt;
&lt;li&gt;The attribute can't be used in combination with CSS background images. Maybe it will come in near future but it is definitely not available now.&lt;/li&gt;
&lt;li&gt;If printing the webpage is a real usecase for you, then please notice that there is an &lt;a href="https://bugs.chromium.org/p/chromium/issues/detail?id=875403" rel="noopener noreferrer"&gt;open bug&lt;/a&gt; for the loading attribute.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you liked this post, please give me a ❤️ or even a 🦄 and feel free to follow me on &lt;code&gt;dev.to&lt;/code&gt;. Appreciate it! ✌️&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__248468"&gt;
    &lt;a href="/pfacklam" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F248468%2F1a2f6ad3-a625-4a72-be2e-7c104d4235b9.jpeg" alt="pfacklam image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/pfacklam"&gt;Paul Facklam&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/pfacklam"&gt;Web Developer 💻 | Trainer 💡 | Consultant 📈 | Tech Writer 📝 • 850+ Follower | 850+ Reactions | ~15000 Views • I write about coding tips, thoughts and the web&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>html</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The power of Template Literals</title>
      <dc:creator>Paul Facklam</dc:creator>
      <pubDate>Wed, 19 Feb 2020 18:33:09 +0000</pubDate>
      <link>https://forem.com/pfacklam/the-power-of-template-literals-4e7e</link>
      <guid>https://forem.com/pfacklam/the-power-of-template-literals-4e7e</guid>
      <description>&lt;p&gt;I'm pretty sure you've come across a &lt;em&gt;template literal&lt;/em&gt; before. That's not surprising, since it's been almost 5 years after its release as one of the features of &lt;strong&gt;EMCAScript 6&lt;/strong&gt; in June 2015 (where they were once called template strings). Reasons enough to remind yourself what template literals are and what makes them so powerful and extremely useful.&lt;/p&gt;

&lt;h1&gt;
  
  
  Template Literals
&lt;/h1&gt;

&lt;p&gt;Template literals are a perfectly simple way of creating strings and to perform interpolation on them. I guess that you are quite familiar with the syntax.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Template literals are enclosed by the backtick [...] character instead of double or single quotes.&lt;br&gt;
-- &lt;cite&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;Mozilla Developer Network&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;double_quoted_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is a common string.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// not a literal&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;single_quoted_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Also a common string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;literal_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;``&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I admit there is nothing special about template literals so far compared to normal strings. But there is more. Imagine you want to have a &lt;strong&gt;multi-line string&lt;/strong&gt;. Is this possible with ordinary strings? Sure it is, but it's not fancy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multi_line_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is a common string.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;with more than one line.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// "This is a common string.&lt;/span&gt;
&lt;span class="c1"&gt;// with more than one line."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the trick. If we use a template literal instead, we get this feature out of the box without any workarounds. But keep in mind that any whitespace or newline characters are part of the Template Literal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multi_line_literal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`This is a common string.
with more than one line.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// "This is a common string.&lt;/span&gt;
&lt;span class="c1"&gt;// with more than one line."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not impressed yet? Ok wait, I'll give you another example of how cool template literals can be. Placeholders!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Template literals can contain placeholders. These are indicated by the dollar sign and curly braces.&lt;br&gt;
-- &lt;cite&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;Mozilla Developer Network&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gone are the days when you had to laboriously concatenate strings by hand. Now it is just defining the &lt;strong&gt;placeholder&lt;/strong&gt; via &lt;code&gt;${}&lt;/code&gt; and providing the values. That's it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;square&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`The &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// "The square of 3 is 9"&lt;/span&gt;

&lt;span class="c1"&gt;// ES 5 equivalent&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;output_es5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; of &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// "The square of 3 is 9"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How cool is this? And there is still more! Template Literals give developers the possibility to create complex strings that can be used for templating. Both &lt;strong&gt;nested templates&lt;/strong&gt; and &lt;strong&gt;conditional templating&lt;/strong&gt; are conceivable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;isExpanded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This text can only be seen when expanded.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cssClasses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isExpanded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`collapsible &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isExpanded&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;is-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collapsible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
  &amp;lt;div class="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cssClasses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isExpanded&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
  &amp;lt;/div&amp;gt;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now the grand finale... If I turn my literal for the collapsible into a function (as I did for the CSS classes), I would be able to output a whole list of items instead of a single one with the help of &lt;code&gt;Array.map&lt;/code&gt;. Mind blowing!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;isExpanded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This text can only be seen when expanded.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cssClasses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isExpanded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`collapsible &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isExpanded&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;is-expanded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collapsible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`
  &amp;lt;div class="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cssClasses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isExpanded&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
  &amp;lt;/div&amp;gt;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
  &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;collapsible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="s2"&gt;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Tagged Template Literals
&lt;/h1&gt;

&lt;p&gt;I guess you know what's coming... And you are right. There is still more. 😎 Are you ready for this? Then let's dive in!&lt;/p&gt;

&lt;p&gt;A very powerful feature of template literals (and I guess most developers are not aware of this) is the possibility to &lt;strong&gt;tag&lt;/strong&gt; them. In this case we talk about &lt;em&gt;tagged template literals&lt;/em&gt;. But what does this mean? It means that you can pass a template through a predefined function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The tag function can then perform whatever operations on these arguments you wish, and return the manipulated string.&lt;br&gt;
-- &lt;cite&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;Mozilla Developer Network&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It does not necessarily have to be a string. The result of the function can also be something different. The name of the function is arbitrary and completely up to you. &lt;/p&gt;

&lt;p&gt;The first parameter is of type array and contains the strings. The remaining arguments are related to the expressions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;topic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Template Literals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;topicExp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ratingExp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// "'"&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// "' is an " &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// " topic."&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ratingStr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ratingExp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;ratingStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;awesome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ratingStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;average&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;topicExp&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;str1&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;ratingStr&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;str2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="s2"&gt;`'&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' is an &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; topic.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 'Template Literals' is an awesome topic.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note that this is a just very basic example to demonstrate the mechanisms behind the scenes. There are a lot of use cases where it really makes sense to work with tagged template literals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Escaping HTML tags&lt;/li&gt;
&lt;li&gt;Translation and internationalization&lt;/li&gt;
&lt;li&gt;Highlighting in texts&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;I admit that this was a lot to digest for a basic introduction. Do you remember everything? Time for a recap. Template literals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;are made with backticks &lt;/li&gt;
&lt;li&gt;are multi-line-ready&lt;/li&gt;
&lt;li&gt;can have placeholders and their values can even be funtions&lt;/li&gt;
&lt;li&gt;can be used for conditional and nested templating&lt;/li&gt;
&lt;li&gt;can be used for advanced interpolation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, I would like to thank you for your time and interest in this article. I hope that you enjoyed reading it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Consistent access to browser events with Pointer Events API</title>
      <dc:creator>Paul Facklam</dc:creator>
      <pubDate>Tue, 05 Nov 2019 11:03:12 +0000</pubDate>
      <link>https://forem.com/pfacklam/consistent-access-to-browser-events-with-pointer-events-api-5gh4</link>
      <guid>https://forem.com/pfacklam/consistent-access-to-browser-events-with-pointer-events-api-5gh4</guid>
      <description>&lt;p&gt;Thank god it's christmas! 🌲 Ok, it's not. But if you're a web developer nowadays, it's starting to feel like christmas. And it's because of this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Added support for the Pointer Events API enabling consistent access to mouse, trackpad, touch, and Apple Pencil events.&lt;/p&gt;

&lt;p&gt;-- &lt;cite&gt;Safari 13 Release Notes&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thus the last resistance against the &lt;strong&gt;Pointer Events API&lt;/strong&gt; has fallen with &lt;a href="https://developer.apple.com/documentation/safari_release_notes/safari_13_release_notes"&gt;Safari 13&lt;/a&gt; and it's now available across &lt;a href="https://caniuse.com/#feat=pointer"&gt;all major browsers&lt;/a&gt;. And this is simply &lt;strong&gt;awesome&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;But don't thank Apple! Belive it or not, pointer events (which are not to be mixed up with the CSS property &lt;code&gt;pointer-events&lt;/code&gt;) were originally introduced for the Internet Explorer 10 by Microsoft for their Surface devices. 😳&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Having a single event model for pointers can simplify creating Web sites and applications and provide a good user experience regardless of the user's hardware.&lt;/p&gt;

&lt;p&gt;-- &lt;cite&gt;Mozilla Developer Network&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Roughly speaking, mouse and touch events are summarized by abstracting input devices like mouse and touch pens as pointing devices. So you don't need to specify different event handlers for different device types any longer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousedown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do something on mousedown&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;touchdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do something on touchdown&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead you can now simply apply one handler to &lt;em&gt;rule them all&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pointerdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do something on mousedown or touchdown&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might now ask: "&lt;em&gt;But can I still react to different device types?&lt;/em&gt;" Yes, you can! That's what the &lt;code&gt;pointerType&lt;/code&gt; property of the event is for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pointerdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pointerType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mouse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pointer type detected: mouse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pointer type detected: pen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;touch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pointer type detected: touch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PointerType is unknown or could not be detected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A look at the API
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;PointerEvent&lt;/code&gt; interface extends the &lt;code&gt;MouseEvent&lt;/code&gt; interface and defines 10 different pointer event types that can be mapped to more or less known mouse or touch events and which are well documented at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events"&gt;MDN&lt;/a&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pointer Event&lt;/th&gt;
&lt;th&gt;Mouse Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mouseover&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mouseover&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerenter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mouseenter&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerdown&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mousedown&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointermove&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mousemove&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mouseup&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointercancel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no equivalent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mouseout&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerleave&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mouseleave&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gotpointercapture&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no equivalent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lostpointercapture&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no equivalent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You also have access to the following read-only properties which give you some additional information about the event:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;a unique identifier for the pointer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;width&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;magnitude on the X axis in pixels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;height&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;magnitude on the Y axis in pixels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pressure&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;normalized pressure of the pointer input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tangentialPressure&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;normalized tangential pressure of the pointer input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tiltX&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;angle between the Y-Z plane and the plane containing both the pointer axis and the Y axis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tiltY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;angle between the X-Z plane and the plane containing both the pointer axis and the X axis.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;twist&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the clockwise rotation of the pointer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pointerType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;indicates the device type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isPrimary&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;indicates if the pointer represents the primary pointer of this pointer type&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Polyfill
&lt;/h2&gt;

&lt;p&gt;If you have to support &lt;a href="https://caniuse.com/#feat=pointer"&gt;browsers that haven't yet implemented the Pointer Events API&lt;/a&gt; you can easily use a &lt;a href="https://github.com/jquery/PEP"&gt;polyfill&lt;/a&gt; maintained by the jQuery team. But you can also do some basic feature detection and go with a fallback solution instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PointerEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Hello Pointer Events&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Oh... Hi fallback... it's you.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading this article. I hope you'll enjoy using the Pointer Events API like I do. What are your thoughts about this? Tell me in the comments section below!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
