<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Knowledge Base (Posts about javascript)</title><link>https://bgstack15.ddns.net/blog/</link><description></description><atom:link href="https://bgstack15.ddns.net/blog/categories/javascript.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2025 &lt;a href="mailto:bgstack15@gmail.com"&gt;bgstack15&lt;/a&gt; 
&lt;a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.html"&gt;
&lt;img alt="GNU General Public License v3.0"
style="border-width:0; margin-bottom:12px;"
src="https://bgstack15.ddns.net/.images/gplv3-127x51.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Thu, 04 Sep 2025 13:30:43 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Redirect http to https in html (well, javascript)</title><link>https://bgstack15.ddns.net/blog/posts/2025/03/28/redirect-http-to-https-in-html-well-javascript/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I wanted to redirect an http page to https, without changing virtual hostname. And I was able to find this on &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/stackoverflow.com/questions/4954768/automatic-redirection-to-https/4954784#4954784"&gt;the Internet&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;&amp;lt;!-- from https://stackoverflow.com/questions/4954768/automatic-redirection-to-https/4954784#4954784 --&amp;gt;&lt;/span&gt;
var loc = window.location.href+'';
if (loc.indexOf('http://')==0){
    window.location.href = loc.replace('http://','https://');
}
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So as long as you reach this index.html, it will then redirect you to the webapp hosted only on the TLS-enabled virtual host.&lt;/p&gt;</description><category>html</category><category>javascript</category><category>web</category><guid>https://bgstack15.ddns.net/blog/posts/2025/03/28/redirect-http-to-https-in-html-well-javascript/</guid><pubDate>Fri, 28 Mar 2025 13:28:00 GMT</pubDate></item><item><title>Troubleshooting problem in Infcloud, my web calendar solution</title><link>https://bgstack15.ddns.net/blog/posts/2024/06/30/troubleshooting-problem-in-infcloud-my-web-calendar-solution/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I've written about my web calendar solution. Over time I've noticed that my web calendar malfunctions and doesn't always hide/display my calendars when I check and uncheck the box.&lt;/p&gt;
&lt;p&gt;I spent a bunch of time debugging this, and learned that it might be a commit where I forcefully set a variable at login time in commit &lt;a href="https://bgstack15.ddns.net/blog/cgit/radicaleinfcloud/commit/radicale_infcloud/web/webdav_protocol.js?h=stackrpms&amp;amp;id=d9ddf89b32a1514248f0943e72f704a8bcb523e4"&gt;d9ddf89b32a1514248f0943e72f704a8bcb523e4&lt;/a&gt; to file &lt;code&gt;webdav_protocol.js&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="err"&gt;@@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;747&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;772&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;netFindResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inputResourceIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;forceLoad&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;indexR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;globalSettings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activecalendarcollections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;globalVisibleCalDAVCollections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="n"&gt;globalDefaultCalendarCollectionActiveAll&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stackrpms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;forces&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;calendars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;globalDefaultCalendarCollectionActiveAll&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;globalDefaultCalendarCollectionActiveAll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;globalResourceCalDAVList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I think even if a calendar is off, but I set that value to true, it misleads the variable &lt;code&gt;globalVisibleCalDAVCollections&lt;/code&gt;. I found that using the java console to reset that value makes this work better.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;globalVisibleCalDAVCollections=[]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So I haven't made any changes to the code, at this time. By just resetting that array with 5,445 entries (of the 11 calendars I have in production), my web calendar started behaving better.&lt;/p&gt;</description><category>calendar</category><category>infcloud</category><category>javascript</category><guid>https://bgstack15.ddns.net/blog/posts/2024/06/30/troubleshooting-problem-in-infcloud-my-web-calendar-solution/</guid><pubDate>Sun, 30 Jun 2024 12:50:25 GMT</pubDate></item><item><title>enable paste on website with javascript</title><link>https://bgstack15.ddns.net/blog/posts/2024/02/27/enable-paste-on-website-with-javascript/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I'm directly quoting/ripping off &lt;a href="https://stackoverflow.com/questions/32784487/script-to-enable-paste-on-website/68414487#68414487"&gt;https://stackoverflow.com/questions/32784487/script-to-enable-paste-on-website/68414487#68414487&lt;/a&gt; here. Because it's incredibly useful.&lt;/p&gt;
&lt;p&gt;I found this simple script did work [for enabling "paste" on website]:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;document&lt;/span&gt;.&lt;span class="nv"&gt;addEventListener&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paste&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;, &lt;span class="nv"&gt;function&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; {
  &lt;span class="nv"&gt;e&lt;/span&gt;.&lt;span class="nv"&gt;stopImmediatePropagation&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
}, &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Which was found here: &lt;a href="https://www.howtogeek.com/251807/how-to-enable-pasting-text-on-sites-that-block-it/"&gt;https://www.howtogeek.com/251807/how-to-enable-pasting-text-on-sites-that-block-it/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Edit: May need to stop propagation for keydown as well for some websites.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;document&lt;/span&gt;.&lt;span class="nv"&gt;addEventListener&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;keydown&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;, &lt;span class="nv"&gt;function&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; {
  &lt;span class="nv"&gt;e&lt;/span&gt;.&lt;span class="nv"&gt;stopImmediatePropagation&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
}, &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Paste that into the console of devtools (&lt;code&gt;F12&lt;/code&gt;) and carry on with business.&lt;/p&gt;</description><category>clipboard</category><category>javascript</category><guid>https://bgstack15.ddns.net/blog/posts/2024/02/27/enable-paste-on-website-with-javascript/</guid><pubDate>Tue, 27 Feb 2024 13:42:58 GMT</pubDate></item><item><title>Sample colorized icon in desktop notification from browser</title><link>https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I am considering adding desktop notifications to my fork of InfCloud, and to do that I had to learn how to send desktop notifications. MDN did not disappoint!&lt;/p&gt;
&lt;p&gt;You'll see that I do some very basic find-button logic to add the click function. Of course this is boilerplate and won't look exactly the same whenever I get around to adding it to InfCloud/CalDAVZap.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bgstack15.ddns.net/blog/files/2023/11/listings/notifications.html.html"&gt;files/2023/11/listings/notifications.html&lt;/a&gt;  &lt;a href="https://bgstack15.ddns.net/blog/files/2023/11/listings/notifications.html"&gt;(Source)&lt;/a&gt;&lt;/p&gt;&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-1"&gt;&lt;code data-line-number=" 1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;html&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-2"&gt;&lt;code data-line-number=" 2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;header&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-3"&gt;&lt;code data-line-number=" 3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;title&amp;gt;Example page&amp;lt;/title&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-4"&gt;&lt;code data-line-number=" 4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;script src="notifications.js"&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-5"&gt;&lt;code data-line-number=" 5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-6"&gt;&lt;code data-line-number=" 6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;/header&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-7"&gt;&lt;code data-line-number=" 7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;body&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-8"&gt;&lt;code data-line-number=" 8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;h1&amp;gt;example&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-9"&gt;&lt;code data-line-number=" 9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;Lorem ipsum, etc.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-10"&gt;&lt;code data-line-number="10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;button&amp;gt;Notify me!&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-11"&gt;&lt;code data-line-number="11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-12"&gt;&lt;code data-line-number="12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;footer&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-13"&gt;&lt;code data-line-number="13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;/footer&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-14"&gt;&lt;code data-line-number="14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;a href="https://bgstack15.ddns.net/blog/files/2023/11/listings/notifications.js.html"&gt;files/2023/11/listings/notifications.js&lt;/a&gt;  &lt;a href="https://bgstack15.ddns.net/blog/files/2023/11/listings/notifications.js"&gt;(Source)&lt;/a&gt;&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-1"&gt;&lt;code data-line-number="  1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;// vim: set et ts=3 sw=3 sts=3:
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-2"&gt;&lt;code data-line-number="  2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;// Startdate: 2023-11-09 18:36
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-3"&gt;&lt;code data-line-number="  3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;// Purpose: Reference implementation for sending a notification with a colorized image from this server
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-4"&gt;&lt;code data-line-number="  4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;// Reference:
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-5"&gt;&lt;code data-line-number="  5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;//    https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-6"&gt;&lt;code data-line-number="  6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;//    https://www.w3docs.com/snippets/html/how-to-display-base64-images-in-html.html
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-7"&gt;&lt;code data-line-number="  7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;//    https://stackoverflow.com/questions/28450471/convert-inline-svg-to-base64-string
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-8"&gt;&lt;code data-line-number="  8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-9"&gt;&lt;code data-line-number="  9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;const img = "/calendar/images/banner_calendar.svg";
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-10"&gt;&lt;code data-line-number=" 10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;const notification_attempts = 10;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-11"&gt;&lt;code data-line-number=" 11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;const notification_ms = 200;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-12"&gt;&lt;code data-line-number=" 12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;// Due to how browsers/css work with colors, you can pass #000000 or web safe color names.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-13"&gt;&lt;code data-line-number=" 13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;var colors = Array("red","orange","yellow","green","blue","purple","black","white","brown");
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-14"&gt;&lt;code data-line-number=" 14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-15"&gt;&lt;code data-line-number=" 15"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;function colorizeSvg(inSvg, oldColor, newColor) {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-16"&gt;&lt;code data-line-number=" 16"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   // In case we have to do more than `s//g` in the future.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-17"&gt;&lt;code data-line-number=" 17"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   return inSvg.replaceAll(oldColor, newColor);
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-18"&gt;&lt;code data-line-number=" 18"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;}
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-19"&gt;&lt;code data-line-number=" 19"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-20"&gt;&lt;code data-line-number=" 20"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;function SendColorizedNotification(_title, _body, _icon, _tag, _color) {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-21"&gt;&lt;code data-line-number=" 21"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   // given _icon as path on server, get contents and adjust the main color in it to desired color.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-22"&gt;&lt;code data-line-number=" 22"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   // The 585858 is the specific color of the calendar.svg we intend to replace.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-23"&gt;&lt;code data-line-number=" 23"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   const xhr = new XMLHttpRequest();
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-24"&gt;&lt;code data-line-number=" 24"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   xhr.open("GET",_icon);
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-25"&gt;&lt;code data-line-number=" 25"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   xhr.onload = () =&amp;gt; {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-26"&gt;&lt;code data-line-number=" 26"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      newSvg = colorizeSvg(xhr.responseText,"#585858",_color);
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-27"&gt;&lt;code data-line-number=" 27"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      encodedData = window.btoa(newSvg); // turn it into the base64 stream
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-28"&gt;&lt;code data-line-number=" 28"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      encodedData = "data:image/svg+xml;base64," + encodedData; // prepend the type of stream
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-29"&gt;&lt;code data-line-number=" 29"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      SendNotification(_title, _body, encodedData, _tag, _color);
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-30"&gt;&lt;code data-line-number=" 30"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   }
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-31"&gt;&lt;code data-line-number=" 31"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   xhr.send();
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-32"&gt;&lt;code data-line-number=" 32"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;}
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-33"&gt;&lt;code data-line-number=" 33"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-34"&gt;&lt;code data-line-number=" 34"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;function SendNotification(_title, _body, _icon, _tag) {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-35"&gt;&lt;code data-line-number=" 35"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   // From: https://developer.mozilla.org/en-US/docs/Web/API/notification
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-36"&gt;&lt;code data-line-number=" 36"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   if (!("Notification" in window)) {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-37"&gt;&lt;code data-line-number=" 37"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // Check if the browser supports notifications
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-38"&gt;&lt;code data-line-number=" 38"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      alert("This browser does not support desktop notification");
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-39"&gt;&lt;code data-line-number=" 39"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   } else if (Notification.permission === "granted") {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-40"&gt;&lt;code data-line-number=" 40"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // Check whether notification permissions have already been granted;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-41"&gt;&lt;code data-line-number=" 41"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // if so, create a notification
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-42"&gt;&lt;code data-line-number=" 42"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      const notification = new Notification(String(_title), { tag: _tag, body: _body, icon: _icon });
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-43"&gt;&lt;code data-line-number=" 43"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // …
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-44"&gt;&lt;code data-line-number=" 44"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   } else if (Notification.permission !== "denied") {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-45"&gt;&lt;code data-line-number=" 45"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // We need to ask the user for permission
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-46"&gt;&lt;code data-line-number=" 46"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      Notification.requestPermission().then((permission) =&amp;gt; {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-47"&gt;&lt;code data-line-number=" 47"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         // If the user accepts, let's create a notification
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-48"&gt;&lt;code data-line-number=" 48"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         if (permission === "granted") {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-49"&gt;&lt;code data-line-number=" 49"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            const notification = new Notification(String(_title), { tag: _tag, body: _body, icon: _icon });
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-50"&gt;&lt;code data-line-number=" 50"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            // …
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-51"&gt;&lt;code data-line-number=" 51"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         }
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-52"&gt;&lt;code data-line-number=" 52"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      });
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-53"&gt;&lt;code data-line-number=" 53"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   }
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-54"&gt;&lt;code data-line-number=" 54"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   // At last, if the user has denied notifications, and you
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-55"&gt;&lt;code data-line-number=" 55"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   // want to be respectful there is no need to bother them anymore.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-56"&gt;&lt;code data-line-number=" 56"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;}
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-57"&gt;&lt;code data-line-number=" 57"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-58"&gt;&lt;code data-line-number=" 58"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;function SendNotificationManyTimes(_title, _body, _icon, _tag) {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-59"&gt;&lt;code data-line-number=" 59"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   // From: https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-60"&gt;&lt;code data-line-number=" 60"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   if (Notification?.permission === "granted") {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-61"&gt;&lt;code data-line-number=" 61"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // If the user agreed to get notified
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-62"&gt;&lt;code data-line-number=" 62"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // Let's try to send ten notifications
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-63"&gt;&lt;code data-line-number=" 63"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      let i = 0;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-64"&gt;&lt;code data-line-number=" 64"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // Using an interval cause some browsers (including Firefox) are blocking notifications if there are too much in a certain time.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-65"&gt;&lt;code data-line-number=" 65"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      const interval = setInterval(() =&amp;gt; {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-66"&gt;&lt;code data-line-number=" 66"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         // Thanks to the tag, we should only see the "Hi! 9" notification
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-67"&gt;&lt;code data-line-number=" 67"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         const n = new Notification(String(_title), { tag: _tag, body: _body, icon: _icon });
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-68"&gt;&lt;code data-line-number=" 68"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         //const n = new Notification(`Hi! breakfast ${i}`, { tag: "soManyNotification", body: "this is body?", icon: img });
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-69"&gt;&lt;code data-line-number=" 69"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         if (i === (notification_attempts-1)) {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-70"&gt;&lt;code data-line-number=" 70"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            clearInterval(interval);
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-71"&gt;&lt;code data-line-number=" 71"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         }
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-72"&gt;&lt;code data-line-number=" 72"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         i++;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-73"&gt;&lt;code data-line-number=" 73"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      }, notification_ms);
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-74"&gt;&lt;code data-line-number=" 74"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   } else if (Notification &amp;amp;&amp;amp; Notification.permission !== "denied") {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-75"&gt;&lt;code data-line-number=" 75"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // If the user hasn't told if they want to be notified or not
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-76"&gt;&lt;code data-line-number=" 76"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // Note: because of Chrome, we are not sure the permission property
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-77"&gt;&lt;code data-line-number=" 77"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // is set, therefore it's unsafe to check for the "default" value.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-78"&gt;&lt;code data-line-number=" 78"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      Notification.requestPermission().then((status) =&amp;gt; {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-79"&gt;&lt;code data-line-number=" 79"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         // If the user said okay
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-80"&gt;&lt;code data-line-number=" 80"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         if (status === "granted") {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-81"&gt;&lt;code data-line-number=" 81"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            let i = 0;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-82"&gt;&lt;code data-line-number=" 82"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            // Using an interval cause some browsers (including Firefox) are blocking notifications if there are too much in a certain time.
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-83"&gt;&lt;code data-line-number=" 83"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            const interval = setInterval(() =&amp;gt; {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-84"&gt;&lt;code data-line-number=" 84"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               // Thanks to the tag, we should only see the "Hi! 9" notification
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-85"&gt;&lt;code data-line-number=" 85"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               const n = new Notification(String(_title), { tag: _tag, body: _body, icon: _icon });
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-86"&gt;&lt;code data-line-number=" 86"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               if (i === (notification_attempts-1)) {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-87"&gt;&lt;code data-line-number=" 87"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  clearInterval(interval);
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-88"&gt;&lt;code data-line-number=" 88"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               }
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-89"&gt;&lt;code data-line-number=" 89"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               i++;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-90"&gt;&lt;code data-line-number=" 90"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            }, notification_ms);
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-91"&gt;&lt;code data-line-number=" 91"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         } else {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-92"&gt;&lt;code data-line-number=" 92"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            // Otherwise, we can fallback to a regular modal alert
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-93"&gt;&lt;code data-line-number=" 93"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            alert(String(_title)+": "+String(_body));
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-94"&gt;&lt;code data-line-number=" 94"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         }
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-95"&gt;&lt;code data-line-number=" 95"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      });
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-96"&gt;&lt;code data-line-number=" 96"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   } else {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-97"&gt;&lt;code data-line-number=" 97"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      // If the user refuses to get notified, we can fallback to a regular modal alert
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-98"&gt;&lt;code data-line-number=" 98"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      alert(String(_title)+": "+String(_body));
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-99"&gt;&lt;code data-line-number=" 99"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   }
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-100"&gt;&lt;code data-line-number="100"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;}
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-101"&gt;&lt;code data-line-number="101"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-102"&gt;&lt;code data-line-number="102"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;function getRandomColor() {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-103"&gt;&lt;code data-line-number="103"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   return colors[Math.floor(Math.random()*colors.length)];
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-104"&gt;&lt;code data-line-number="104"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;}
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-105"&gt;&lt;code data-line-number="105"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-106"&gt;&lt;code data-line-number="106"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;window.addEventListener("load", () =&amp;gt; {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-107"&gt;&lt;code data-line-number="107"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   const button = document.querySelector("button");
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-108"&gt;&lt;code data-line-number="108"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   button.addEventListener("click", () =&amp;gt; {
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-109"&gt;&lt;code data-line-number="109"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      SendColorizedNotification("sample calendar appointment","in 10 minutes",img,"",getRandomColor());
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-110"&gt;&lt;code data-line-number="110"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   });
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/#-111"&gt;&lt;code data-line-number="111"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;});
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;</description><category>browser</category><category>desktop</category><category>javascript</category><category>notifications</category><guid>https://bgstack15.ddns.net/blog/posts/2023/11/11/sample-colorized-icon-in-desktop-notification-from-browser/</guid><pubDate>Sat, 11 Nov 2023 14:28:50 GMT</pubDate></item><item><title>Infcloud improvement: keyboard shortcuts dialog</title><link>https://bgstack15.ddns.net/blog/posts/2023/04/22/infcloud-improvement-keyboard-shortcuts-dialog/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I added a dialog to &lt;a href="https://bgstack15.ddns.net/blog/cgit/radicaleinfcloud/log/?h=stackrpms"&gt;my fork&lt;/a&gt; of &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/inf-it.com/open-source/clients/infcloud/"&gt;Infcloud&lt;/a&gt;! This application originally had zero keyboard navigation, and I've slowly been adding some to make it more usable to me.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bgstack15.ddns.net/blog/2023/04/keyboard-shortcuts-dialog.png"&gt;&lt;img alt="" src="https://bgstack15.ddns.net/blog/2023/04/keyboard-shortcuts-dialog.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Right now the contents of the help dialog are hard-coded, but perhaps someday I will attempt to have the section that adds the keyboard shortcuts add their own text description to a variable that is used to populate this field.&lt;/p&gt;
&lt;p&gt;All the work this time is in one &lt;a href="https://bgstack15.ddns.net/blog/cgit/radicaleinfcloud/commit/?h=stackrpms&amp;amp;id=d5bc9bfd4f6a45e766b2371cc97108f31d4ff09e"&gt;merge commit&lt;/a&gt;.&lt;/p&gt;</description><category>calendar</category><category>infcloud</category><category>javascript</category><guid>https://bgstack15.ddns.net/blog/posts/2023/04/22/infcloud-improvement-keyboard-shortcuts-dialog/</guid><pubDate>Sat, 22 Apr 2023 12:34:02 GMT</pubDate></item><item><title>Infcloud: auto login my way</title><link>https://bgstack15.ddns.net/blog/posts/2022/08/17/infcloud-auto-login-my-way/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I have now added to InfCloud the ability to use the browser localStorage feature to store username, password, and chosen locale. To be more precise, it can load these values if present. InfCloud does not set them yet. I haven't bothered to write that part.&lt;/p&gt;
&lt;p&gt;To use this feature, you need to run a few commands in the javascript console of your web browser. Not all of my browsers work correctly, even though localStorage object exists.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;localStorage.setItem("user","bgstack15");
localStorage.setItem("pass","plaintexthere");
localStorage.setItem("locale","English (24h)");
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The locale value is the contents of the text box, and not the shortcode such as &lt;em&gt;en_BS&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If these values are set, when you refresh the page it should auto-login right away.&lt;/p&gt;
&lt;p&gt;See the &lt;a href="https://bgstack15.ddns.net/cgit/radicaleinfcloud/commit/?h=stackrpms&amp;amp;id=e83095bd0c444a7a792fae63e0c8e7138c2685cf"&gt;commit&lt;/a&gt; that includes the functionality.&lt;/p&gt;</description><category>infcloud</category><category>javascript</category><guid>https://bgstack15.ddns.net/blog/posts/2022/08/17/infcloud-auto-login-my-way/</guid><pubDate>Wed, 17 Aug 2022 13:27:00 GMT</pubDate></item><item><title>Infcloud with event import feature</title><link>https://bgstack15.ddns.net/blog/posts/2022/08/13/infcloud-with-event-import-feature/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I've previously discussed my &lt;a href="https://bgstack15.ddns.net/blog/categories/infcloud/"&gt;self-hosted calendar solution&lt;/a&gt;, and I have an update for it!&lt;/p&gt;
&lt;p&gt;I have now added a working upload feature! See commit &lt;a href="https://gitlab.com/bgstack15/RadicaleInfCloud/-/commit/81431ce6cce507535d871020fcb4c9b3844ffd4a"&gt;81431ce6cce507535d871020fcb4c9b3844ffd4a&lt;/a&gt;. I spent a long time to add these very short lines.&lt;/p&gt;
&lt;p&gt;Now, in the new-event form, you can drag-and-drop a .ics file onto the "Import" button, and it will add the new event for you! I was not aware of any previous import/upload feature in InfCloud, so I wrote my own.&lt;/p&gt;
&lt;p&gt;I started with duplicates of multiple, large internal functions. In the end though, it was a lot shorter than I thought it would be.&lt;/p&gt;</description><category>git</category><category>infcloud</category><category>javascript</category><guid>https://bgstack15.ddns.net/blog/posts/2022/08/13/infcloud-with-event-import-feature/</guid><pubDate>Sat, 13 Aug 2022 12:51:16 GMT</pubDate></item><item><title>Javascript blink a select option input if trying to add it again</title><link>https://bgstack15.ddns.net/blog/posts/2021/12/20/javascript-blink-select-option-if-adding-again/</link><dc:creator>bgstack15</dc:creator><description>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;As part of an up-and-coming project that will be discussed at a future date, I have been working in javascript and html again. I want a form with a list of attributes, to which the user can add and remove entries. I wanted a way to show that the requested entry was already in the list. Here's what I've got so far.&lt;/p&gt;
&lt;h2&gt;The code&lt;/h2&gt;
&lt;p&gt;This one html template file includes css, javascript, and the html form itself.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;{{ title }}&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
@-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
@-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
@keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
.fadeIn {
  -webkit-animation: fadeIn 1s ease-in-out 0s;
  -moz-animation: fadeIn 1s ease-in-out 0s;
  -o-animation: fadeIn 1s ease-in-out 0s;
   animation: fadeIn 1s ease-in-out 0s;
}
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"edit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Title:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;accesskey=&lt;/span&gt;&lt;span class="s"&gt;"t"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{ title }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"tag"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Tag entry:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"tag"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"tag"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'button'&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'add to list'&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'add'&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'button'&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;'remove from list'&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'remove'&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"tags"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Tags:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"tags"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"tags"&lt;/span&gt; &lt;span class="na"&gt;multiple=&lt;/span&gt;&lt;span class="s"&gt;'multiple'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
{% for i in tags %}&lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"opt_{{ i }}"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{ i }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ i }}&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;{% endfor %}&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;accesskey=&lt;/span&gt;&lt;span class="s"&gt;"s"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
let tag = document.getElementById("tag");
let tags = document.getElementById("tags");
// blink function depends on css above
function blink_once(item) {
   //var item = document.getElementById(item);
   console.log(`Want to blink ${item} with ${item.value}`);
   item.classList.add('fadeIn');
   // remove the class, after the delay, so that the item can blink again if necessary.
   setTimeout(function(){item.classList.remove('fadeIn')},1000);
}
function add_option() {
   let text = tag.value;
   if (text != "" &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; text.match('[0-9a-zA-Z]') ) {
      var optexists = document.getElementById("opt_"+text);
      if (optexists) {
         // it already exists
         blink_once(optexists);
         } else {
         // need to add it
         var opt = document.createElement('option');
         opt.value = text; opt.innerHTML = text; opt.id = "opt_" + text;
         tags.appendChild(opt);
         tag.value = "";
         return 0;
      }
   }
   return 1;
};
function remove_option() {
   let text = tag.value;
   let opt = document.getElementById("opt_"+text);
   if (opt) { opt.remove(); };
   console.log(`Want to remove item "${text}" from list?`);
};
// When the tags list selection is changed, update the value of the tag entry field
function set_option() {
   let text = tags[tags.selectedIndex].value;
   console.log(`text is "${text}"`);
   tag.value = text;
}
// Behavior of the add and remove buttons
document.getElementById("add").onclick = function(){add_option()};
document.getElementById("remove").onclick = function(){remove_option()};
// Behavior of the tags list
tags.onclick = function(){set_option()};
tags.onchange = function(){set_option()};
tags.onfocus = function(){this.selectedIndex = -1};
// when press enter, run the "add" event.
tag.onkeypress = function(event,value) {
   if (13 == event.which) {
      event.preventDefault(); // this blocks the Enter key from submitting the form, for this field only!
      console.log("Enter was pressed!");
      if (0 == add_option()) {
         console.log("Successful addition!")
      } else {
         console.log(`failed to add "${document.getElementById("tag").value}".`);
      }
   };
}
function submitform() {
   console.log("The submit button was pressed!");
};
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Walkthrough&lt;/h2&gt;
&lt;p&gt;I set up a text field, "Tag entry." This value changes to the currently-selected option from the select field. When the user presses enter, the javascript adds the tag to the list of tags. If the tag already exists, it will blink once.&lt;/p&gt;
&lt;p&gt;The submit behavior is not complete yet, but that's a separate story for another day.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Principal work comes from two answers on the same SO question:
javascript - Making a div flash just once
&lt;a href="https://stackoverflow.com/questions/38370854/making-a-div-flash-just-once/38370873#38370873"&gt;Praveen Kumar Prushothaman's answer&lt;/a&gt;
&lt;a href="https://stackoverflow.com/questions/38370854/making-a-div-flash-just-once/38371229#38371229"&gt;Srikanth Reddy's answer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/8674618/adding-options-to-select-with-javascript/8674667#8674667"&gt;https://stackoverflow.com/questions/8674618/adding-options-to-select-with-javascript/8674667#8674667&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/33758595/html-form-run-javascript-on-enter/33758792#33758792"&gt;https://stackoverflow.com/questions/33758595/html-form-run-javascript-on-enter/33758792#33758792&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/647282/is-there-an-onselect-event-or-equivalent-for-html-select/12404521#12404521"&gt;https://stackoverflow.com/questions/647282/is-there-an-onselect-event-or-equivalent-for-html-select/12404521#12404521&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>blink</category><category>fade</category><category>form</category><category>html</category><category>javascript</category><category>select</category><guid>https://bgstack15.ddns.net/blog/posts/2021/12/20/javascript-blink-select-option-if-adding-again/</guid><pubDate>Mon, 20 Dec 2021 14:18:22 GMT</pubDate></item><item><title>Use login form for Jira even when SAML auth is primary</title><link>https://bgstack15.ddns.net/blog/posts/2020/04/23/use-login-form-for-jira-even-when-saml-auth-is-primary/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;If you use SAML authentication as primary auth for Jira, but it malfunctions,
you can still get in with a local account. Use this URL:
https://jira.example.com/login.jsp?auth_fallback. The auth_fallback parameter
will skip the redirection for unauthenticated users.&lt;/p&gt;
&lt;h3&gt;How to enable this feature&lt;/h3&gt;
&lt;p&gt;You have to tell Jira to listen for this parameter. Hit this REST endpoint:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl -vvv -X PUT https://jira.example.com/rest/authconfig/1.0/sso -H 'Content-Type: application/json' -d '{"allow-redirect-override": true}' -u 'internalapplications'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can also append a colon and the password in the -u parameter.&lt;/p&gt;
&lt;h2&gt;Bonus content&lt;/h2&gt;
&lt;p&gt;Use the Announcement banner for a "Login with SSO" button, and even a
redirection to the login form, if the user visits anything other than the
login page while unauthenticated.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
if(jQuery('#header-details-user-fullname').text().indexOf(" ")==-1 &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; window.location.href.indexOf("login.jsp")==-1)
{ window.location = "/login.jsp" }

if(window.location.href.indexOf("login.jsp") != -1) {
  jQuery(document).ready(function(){
    jQuery( "&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'aui-button aui-button-primary'&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;'/plugins/servlet/external-login'&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'SSOLogin'&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;'_parent'&lt;/span&gt; &lt;span class="na"&gt;resolved=&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Use SSO Login&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;" ).insertAfter( '#login-form-submit' );
  });
}
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img alt='jira login form for manual entry, with additional "Use SSO Login"
button' src="https://bgstack15.ddns.net/blog/2020/04/jira-login-form.png"&gt;&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;h3&gt;Weblinks&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://confluence.atlassian.com/jirakb/bypass-saml-authentication-for-jira-data-center-869009810.html"&gt;Bypass SAML authentication for Jira Data Center - Atlassian Documentation&lt;/a&gt; refers to a command that is not valid for Jira Software 8.7.1. &lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl -vvv -XPUT /rest/authconfig/1.0/saml -H 'Content-Type: application/json' -d '{"allow-saml-redirect-override": true}' -u admin_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Other&lt;/h3&gt;
&lt;p&gt;Original research with REST API browser&lt;/p&gt;</description><category>auth</category><category>javascript</category><category>jira</category><category>saml</category><guid>https://bgstack15.ddns.net/blog/posts/2020/04/23/use-login-form-for-jira-even-when-saml-auth-is-primary/</guid><pubDate>Thu, 23 Apr 2020 13:14:43 GMT</pubDate></item></channel></rss>