<?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: Kevin Cameron</title>
    <description>The latest articles on Forem by Kevin Cameron (@kevinkace).</description>
    <link>https://forem.com/kevinkace</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%2F88823%2F8bee0a70-3a6c-4bf7-a9e7-43ec469d1037.png</url>
      <title>Forem: Kevin Cameron</title>
      <link>https://forem.com/kevinkace</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kevinkace"/>
    <language>en</language>
    <item>
      <title>Simple Input Mask</title>
      <dc:creator>Kevin Cameron</dc:creator>
      <pubDate>Wed, 23 Oct 2019 04:32:44 +0000</pubDate>
      <link>https://forem.com/kevinkace/simple-input-mask-b7m</link>
      <guid>https://forem.com/kevinkace/simple-input-mask-b7m</guid>
      <description>&lt;p&gt;An input mask will format an input value to better represent the data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;credit card: &lt;code&gt;4455-4455-1234-1234&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;SSN: &lt;code&gt;123-12-1234&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;phone number (NA): &lt;code&gt;123-123-1234&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, extract the pattern by finding the indexes of the spaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getPattern&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;dashIdxs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&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="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&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="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;dashIdxs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&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="nx"&gt;dashIdxs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Two additional functions as handlers for &lt;code&gt;oninput&lt;/code&gt; and &lt;code&gt;keydown&lt;/code&gt; events. &lt;code&gt;value&lt;/code&gt; is the our masked value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;onkeydown&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;})&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;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backspace&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;dashIdxs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&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="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;oninput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;currentTarget&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;dashIdxs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A working example built with &lt;a href="https://mithril.js.org/"&gt;Mithril.js&lt;/a&gt;.&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/kevinkace/embed/ZEzrLNP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;br&gt;
This is a pretty trivial implementation, and not production ready. It would at least need to support copy/paste.&lt;/p&gt;




&lt;p&gt;cover image: @theonlynoonan - &lt;a href="https://unsplash.com/photos/QM_LE41VJJ4"&gt;https://unsplash.com/photos/QM_LE41VJJ4&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>input</category>
      <category>form</category>
      <category>data</category>
    </item>
    <item>
      <title>Modals and Scrollbars</title>
      <dc:creator>Kevin Cameron</dc:creator>
      <pubDate>Mon, 29 Apr 2019 15:05:47 +0000</pubDate>
      <link>https://forem.com/kevinkace/modals-and-scrollbars-66l</link>
      <guid>https://forem.com/kevinkace/modals-and-scrollbars-66l</guid>
      <description>&lt;p&gt;Today while building a modal I experimented with a different layout that solves a few issues with the scrollbar, in a simple way. Jump to the final version, or read on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Modal
&lt;/h2&gt;

&lt;p&gt;The most basic modal is 2 &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;an overlay &lt;code&gt;position: fixed;&lt;/code&gt; in the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;and the content, nested in the overlay&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h2&gt;
  
  
  Scrollbar
&lt;/h2&gt;

&lt;p&gt;There's an issue with this simple modal: the vertical scrollbar of the main content persists when the modal is opened.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/PkEYdfMJXwffgF8eTw/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/PkEYdfMJXwffgF8eTw/giphy.gif" alt="main content scrolling behind modal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Opening a modal should fully switch context away from the underlying content to the modal. Scrolling presentation and interaction need to follow this context switch.&lt;/p&gt;

&lt;p&gt;A common solution is to add &lt;code&gt;overflow: hidden&lt;/code&gt; on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;, removing the scrollbar entirely. This also works if the modal content is scrollable.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Content Shift
&lt;/h2&gt;

&lt;p&gt;Removing the scrollbar fixes one problem, but introduces another: the underlying content shifts position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/RgyO9SIWdyFS1SgmjG/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/RgyO9SIWdyFS1SgmjG/giphy.gif" alt="content shifting behind modal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the scrollbar is removed, the content takes up that extra width, leading to text and content reflowing, and backgrounds repositioning.&lt;/p&gt;

&lt;p&gt;In the past I've solved this in two ways: adding &lt;code&gt;padding&lt;/code&gt;/&lt;code&gt;margin&lt;/code&gt; on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;, or setting the &lt;code&gt;width&lt;/code&gt; of &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;These values have to be recalculated and updated when the &lt;code&gt;window&lt;/code&gt; is resized, or as content is added/removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modal Over Everything
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So today as I was building a modal I got to this stage and thought about why the modal exists within the scrollable content. It should be fully separate, and &lt;em&gt;on top&lt;/em&gt; of the scrollbar. This is possible by restructuring the document.&lt;/p&gt;

&lt;p&gt;The modal has to be outside the scrollable content; it's added to the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; and can't be any higher up the DOM, so the scrollable content will need to be a child of &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;What I like about this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;no code to remove/add scrollbars&lt;/li&gt;
&lt;li&gt;no code to set width/margin to account for the scrollbar&lt;/li&gt;
&lt;li&gt;no recalculations when resized&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It just works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lastly
&lt;/h2&gt;

&lt;p&gt;One drawback with this setup is that it's atypical. Any other code expecting &lt;code&gt;overflow&lt;/code&gt; to be on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; will need to be refactored. This and other issues likely wouldn't be hard to resolve.&lt;/p&gt;

&lt;p&gt;I plan to test this solution further for browser and device compatibility, and hopefully it proves out.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>css</category>
    </item>
  </channel>
</rss>
