<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>javascript &amp;mdash; Nat Knight</title>
    <link>http://natknight.xyz/tag:javascript</link>
    <description>Reflections, diversions, and opinions from a progressive ex-physicist programmer dad with a sore back.</description>
    <pubDate>Sat, 09 May 2026 05:59:20 -0700</pubDate>
    <item>
      <title>TIL: Copying to the clipboard from a webpage is easy now</title>
      <link>http://natknight.xyz/til-copying-to-the-clipboard-from-a-webpage-is-easy-now</link>
      <description>&lt;![CDATA[#til #webdev #javascript #clipboard&#xA;&#xA;I remember a time when there were whole libraries dedicated to clipboard management.&#xA;&#xA;Turns out in browsers released after ~2020 you can do it with one line:&#xA;&#xA;navigator.clipboard.writeText(text).then(console.log).catch(console.error);&#xA;&#xA;!--more--&#xA;&#xA;Some caveats:&#xA;&#xA;this only works in a secure context (which mostly means either &#34;a site served over HTTPS&#34; or localhost).&#xA;the user needs to have interacted with the page before you can actually call the method.&#xA;this was only added to certain browsers in 2020, so it&#39;s new enough that it might cause problems if your constituents have older devices or don&#39;t update often.&#xA;&#xA;Usually when I do this I&#39;m implementing something like a &#34;copy to clipboard&#34; button:&#xA;&#xA;span id=&#39;copy-target&#39;This text is going into a clipboard/span&#xA;button onclick=&#39;copyToClipboard(&#34;copy-target&#34;)&#39;Copy/button&#xA;script&#xA;    const copyToClipboard = (target) =  {&#xA;        const element = document.getElementById(target);&#xA;        const value = element?.innerText&#xA;        if (value) {&#xA;            navigator.clipboard.writeText(value).then(console.log).catch(console.error);&#xA;        }&#xA;    }&#xA;/script&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="http://natknight.xyz/tag:til" class="hashtag"><span>#</span><span class="p-category">til</span></a> <a href="http://natknight.xyz/tag:webdev" class="hashtag"><span>#</span><span class="p-category">webdev</span></a> <a href="http://natknight.xyz/tag:javascript" class="hashtag"><span>#</span><span class="p-category">javascript</span></a> <a href="http://natknight.xyz/tag:clipboard" class="hashtag"><span>#</span><span class="p-category">clipboard</span></a></p>

<p>I remember a time when there were <a href="https://github.github.com/clipboard-copy-element/">whole</a> <a href="https://clipboardjs.com/">libraries</a> dedicated to clipboard management.</p>

<p>Turns out in <a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/clipboard#browser_compatibility">browsers released after ~2020</a> you can do it with one line:</p>

<pre><code class="language-javascript">navigator.clipboard.writeText(text).then(console.log).catch(console.error);
</code></pre>



<p>Some caveats:</p>
<ul><li>this only works in a <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts">secure context</a> (which mostly means either “a site served over HTTPS” or <code>localhost</code>).</li>
<li>the user needs to have interacted with the page before you can actually call the method.</li>
<li>this was only added to certain browsers in 2020, so it&#39;s new enough that it might cause problems if your constituents have older devices or don&#39;t update often.</li></ul>

<p>Usually when I do this I&#39;m implementing something like a “copy to clipboard” button:</p>

<pre><code class="language-html">&lt;span id=&#39;copy-target&#39;&gt;This text is going into a clipboard&lt;/span&gt;
&lt;button onclick=&#39;copyToClipboard(&#34;copy-target&#34;)&#39;&gt;Copy&lt;/button&gt;
&lt;script&gt;
    const copyToClipboard = (target) =&gt; {
        const element = document.getElementById(target);
        const value = element?.innerText
        if (value) {
            navigator.clipboard.writeText(value).then(console.log).catch(console.error);
        }
    }
&lt;/script&gt;
</code></pre>
]]></content:encoded>
      <guid>http://natknight.xyz/til-copying-to-the-clipboard-from-a-webpage-is-easy-now</guid>
      <pubDate>Mon, 10 Mar 2025 21:19:49 +0000</pubDate>
    </item>
    <item>
      <title>TIL: Accessing Content in Custom HTML Elements</title>
      <link>http://natknight.xyz/til-accessing-content-in-custom-html-elements</link>
      <description>&lt;![CDATA[#til #javascript #webdev #customelements&#xA;&#xA;I was working on a custom element today that replaces a textarea with CodeMirror in the UI while still updating the textarea in the background so that it can be submitted in a form. I ran across a wild footgun in custom elements.&#xA;&#xA;sStackOverflow eventually provided the solution./s There&#39;s a solution on stack overflow, but Danny Engleman wrote up a more thorough explanation.&#xA;&#xA;!--more--&#xA;&#xA;When you&#39;re creating a custom element you do most of your setup in a method called connectedCallback. Here you can read the content of the custom element, replace it with different elements, set up callback handlers, etc.&#xA;&#xA;Or so I thought.&#xA;&#xA;You can read the attributes of the node just fine, but if you try to read its contents you&#39;ll find they aren&#39;t there. The reason is that the connectedCallback fires when the opening tag of the custom element is parsed, so the contents aren&#39;t in the DOM yet.&#xA;&#xA;The solution is breathtakingly simple and silly: call setTimeout to defer initialization until after the DOM has been fully parsed.&#xA;&#xA;export class MyCustomElement extends HTMLElement {&#xA;  initialize () {&#xA;    // Fancy custom element stuff goes here; you can safely access&#xA;    // this.innerHTML and stuff.&#xA;  }&#xA;&#xA;  connectedCallback() {&#xA;    // Be sure to use an arrow function here or &#39;this&#39; will be&#xA;    // messed up in `initialize.&#xA;    setTimeout(() =  this.initialize(), 0)&#xA;  }&#xA;}&#xA;`]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="http://natknight.xyz/tag:til" class="hashtag"><span>#</span><span class="p-category">til</span></a> <a href="http://natknight.xyz/tag:javascript" class="hashtag"><span>#</span><span class="p-category">javascript</span></a> <a href="http://natknight.xyz/tag:webdev" class="hashtag"><span>#</span><span class="p-category">webdev</span></a> <a href="http://natknight.xyz/tag:customelements" class="hashtag"><span>#</span><span class="p-category">customelements</span></a></p>

<p>I was working on a custom element today that replaces a <code>textarea</code> with <a href="https://codemirror.net/">CodeMirror</a> in the UI while still updating the <code>textarea</code> in the background so that it can be submitted in a form. I ran across a <em>wild</em> footgun in custom elements.</p>

<p><s>StackOverflow eventually provided <a href="https://stackoverflow.com/questions/64169068/obtain-this-textcontent-during-custom-element-construction">the solution</a>.</s> There&#39;s a solution on stack overflow, but Danny Engleman wrote up a <a href="https://dev.to/dannyengelman/web-component-developers-do-not-connect-with-the-connectedcallback-yet-4jo7">more thorough explanation</a>.</p>



<p>When you&#39;re creating a custom element you do most of your setup in a method called <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#using_a_custom_element"><code>connectedCallback</code></a>. Here you can read the content of the custom element, replace it with different elements, set up callback handlers, etc.</p>

<p><em>Or so I thought.</em></p>

<p>You can read the <em>attributes</em> of the node just fine, but if you try to read its <em>contents</em> you&#39;ll find they aren&#39;t there. The reason is that the <code>connectedCallback</code> fires when the <em>opening</em> tag of the custom element is parsed, so the contents aren&#39;t in the DOM yet.</p>

<p>The solution is breathtakingly simple and silly: call <code>setTimeout</code> to defer initialization until after the DOM has been fully parsed.</p>

<pre><code class="language-javascript">export class MyCustomElement extends HTMLElement {
  initialize () {
    // Fancy custom element stuff goes here; you can safely access
    // `this.innerHTML` and stuff.
  }

  connectedCallback() {
    // Be sure to use an arrow function here or &#39;this&#39; will be
    // messed up in `initialize.
    setTimeout(() =&gt; this.initialize(), 0)
  }
}
</code></pre>
]]></content:encoded>
      <guid>http://natknight.xyz/til-accessing-content-in-custom-html-elements</guid>
      <pubDate>Sun, 09 Mar 2025 21:59:00 +0000</pubDate>
    </item>
  </channel>
</rss>