)
}
}
)
(
}
{
)
)
(
)
(
(
{
}
)
(
)
}
)
)
{
(
(
)
)
}
)
(
}

Hacky Polish Notation

  1. const f = (o, ...a) => eval(a.join(o));
  2.  
  3. const polish = eq => eval(
  4.     eq.replace(/\s+/g, ' ')
  5.       .replace(/(\))\s([0-9])/g, '$1,$2')
  6.       .replace(/([0-9]+)[^\)]/g, '$1,')
  7.       .replace(/\(\s?([\+\-\*\\/])/g, 'f(`$1`,')
  8.   );
  9.  
  10. console.log(polish('(* 2 2)'));
  11. console.log(polish('(* 2 2 (+ 3 2 1))'));
  12. console.log(polish('(- 10 3)'));
  13. console.log(polish('(/ (+ 10 10 (* 2 2)) 3)'));

Hacky way to parse polish notation. This uses regular expressions to transform polish notation into javascript that can be run with eval. Just a weird/fun idea…

What is the current element? (document.activeElement)

  1. console.log(document.activeElement);

I use document.activeElement constantly when I do accessibility work (getting things to work with screenreaders like NVDA, JAWS or VoiceOver). document.activeElement contains the current element that is in focus on a page.

You can easily debug it with a live expression in the chrome console:

Here is a small demo to play with – try clicking or tabbing around the buttons and inputs:

  1. const el = document.createElement('el');
  2. el.innerHTML = `
  3.   <button class="one">one</button>
  4.   <button class="two">two</button>
  5.   <button class="three">three</button>
  6.   <button class="four">four</button>
  7.   <hr>
  8.   <input type="text" placeholder="type...">
  9.   <hr>
  10.   <input type="range">
  11. `;
  12. document.body.appendChild(el);
  13.  
  14. let lastActive;
  15. setInterval(() => {
  16.   if (document.activeElement != lastActive) {
  17.     lastActive = document.activeElement;
  18.     console.log(lastActive.outerHTML);
  19.   }
  20.  
  21. // no need to update 60fps
  22. }, 100);

Hijack Focus

  1.  
  2. const el = document.body.appendChild(
  3.   document.createElement('div')
  4. );
  5.  
  6. el.innerHTML = `
  7. <button>one</button>
  8. <button>two</button>
  9. <button>three</button>
  10. `;
  11.  
  12. document.addEventListener('click', e => {
  13.   e.target.focus();
  14. });
  15.  
  16. const origFocus = HTMLElement.prototype.focus
  17. HTMLElement.prototype.focus = function() {
  18.   console.log(this.outerHTML, 'focus was called');
  19.   origFocus.call(this);
  20. };
  21.  
  22. el.firstElementChild.focus();

Easy way to debug many calls to focus.

SVG Drawing Program

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.   <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  6.  
  7.     <title>Drawing</title>
  8.     <style>
  9.       body,
  10.       html {
  11.         user-select: none;
  12.         height: 100%;
  13.         margin: 0;
  14.         font-family: sans-serif;
  15.         background: white;
  16.       }
  17.  
  18.       body {
  19.         position: fixed;
  20.         top: 0;
  21.       }
  22.  
  23.       .ui {
  24.         position: fixed;
  25.         display: flex;
  26.         bottom: 0;
  27.         width: 100%;
  28.         margin-bottom: .2em;
  29.       }
  30.  
  31.       .ui .tool {
  32.         font-size: 2em;
  33.         flex: 1;
  34.         text-align: center;
  35.       }
  36.  
  37.       .tool span {
  38.         cursor: pointer;
  39.         display: inline-block;
  40.         transform: scale(0.7);
  41.         transition: transform 250ms ease-out;
  42.       }
  43.  
  44.       .tool span.selected {
  45.         transform: scale(1);
  46.       }
  47.  
  48.       svg {
  49.         overflow: visible;
  50.         height: 100%;
  51.         width: 100%;
  52.         margin: 0;
  53.         padding: 0;
  54.       }
  55.  
  56.       input[type=color] {
  57.         position: absolute;
  58.         left: 0;
  59.         top: 0;
  60.         height: 100%;
  61.         opacity: 0;
  62.         cursor: pointer;
  63.       }
  64.  
  65.       .message {
  66.         position: fixed;
  67.         left: 0;
  68.         top: 0;
  69.         padding: 1em;
  70.         width: 100%;
  71.         text-align: center;
  72.         font-size: 1.2em;
  73.         transition: opacity 250ms ease-out;
  74.         pointer-events: none;
  75.       }
  76.  
  77.       .message.hide {
  78.         opacity: 0;
  79.       }
  80.     </style>
  81.   </head>
  82.   <body>
  83.  
  84.     <svg class="paper" width="100%" height="100%">
  85.       <style>
  86.         path {
  87.           stroke-linecap: round;
  88.           stroke-linejoin: round;
  89.           fill: none;
  90.         }
  91.       </style>
  92.     </svg>
  93.     <div class="ui">
  94.       <div class="tool"><span class="pencil" class="pencil icon selected">&#9999;&#65039;</span></div>
  95.       <div class="tool"><span class="brush icon">&#128396;&#65039;</span></div>
  96.       <div class="tool"><span class="colors icon">&#x1f3a8;
  97.         <input class="color" type="color"></span></div>
  98.     </div>
  99.     <div class="message">
  100.       click/tap and drag to draw
  101.     </div>
  102.  
  103.     <script>
  104.       (() => { 
  105.         // no scrolling on mobile
  106.         document.addEventListener('touchmove', e => e.preventDefault(), {
  107.           passive: false
  108.         });
  109.  
  110.         function touchify(e) {
  111.           const touch = [];
  112.           touch.x = touch.y = 0;
  113.  
  114.           if (e.touches != null && e.touches.length > 0) {
  115.             touch.x = e.touches[0].clientX;
  116.             touch.y = e.touches[0].clientY;
  117.             for (let i = 0; i < e.touches.length; i++) {
  118.               touch[i] = e.touches[i];
  119.             }
  120.           } else {
  121.             touch.x = e.clientX;
  122.             touch.y = e.clientY;
  123.             touch[0] = { clientX: e.clientX, clientY: e.clientY };
  124.           }
  125.           return touch;
  126.         }
  127.  
  128.         const els = {};
  129.  
  130.         [...document.querySelectorAll('[class]')].forEach(el => {
  131.           els[el.classList[0]] = el;
  132.         });
  133.  
  134.         const { paper, pencil, color, brush, message } = els;
  135.  
  136.         let lastSelected = pencil;
  137.         let strokeWidth = 1;
  138.         let downCount;
  139.         let down;
  140.         let currPath;
  141.         let pathPoints;
  142.  
  143.         const onDown = e => {
  144.           down = true;
  145.           downCount = 0;
  146.           pathPoints = [];
  147.         };
  148.  
  149.         const onMove = e => {
  150.           const touch = touchify(e);
  151.  
  152.           if (down) {
  153.             downCount++;
  154.  
  155.             if (downCount === 1) {
  156.               currPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  157.               currPath.setAttribute('stroke', color.value);
  158.               currPath.setAttribute('stroke-width', strokeWidth);
  159.               currPath.setAttribute('d', `M ${touch.x} ${touch.y}`);
  160.               pathPoints.push([touch.x, touch.y]);
  161.               paper.appendChild(currPath);
  162.             } else {
  163.               let path = `M ${pathPoints[0][0]} ${pathPoints[0][1]} L `;
  164.               pathPoints.push([touch.x, touch.y]);
  165.               for (let i = 1; i < pathPoints.length; i++) {
  166.                 path += `${pathPoints[i][0]} ${pathPoints[i][1]} `;
  167.               }
  168.               currPath.setAttribute('d', path);
  169.             }
  170.  
  171.             if (downCount === 10) {
  172.               message.classList.add('hide');
  173.             }
  174.           }
  175.         };
  176.  
  177.         const onUp = e => {
  178.           down = false;
  179.         };
  180.  
  181.         const onClick = e => {
  182.           if (e.target.classList.contains('pencil')) {
  183.             strokeWidth = 1;
  184.           } else if (e.target.classList.contains('brush')) {
  185.             strokeWidth = 10;
  186.           }
  187.           if (e.target.classList.contains('icon')) {
  188.             if (lastSelected) lastSelected.classList.remove('selected');
  189.             e.target.classList.add('selected');
  190.             lastSelected = e.target;
  191.           }
  192.         };
  193.  
  194.         document.addEventListener('mousedown', onDown);
  195.         document.addEventListener('touchstart', onDown);
  196.  
  197.         document.addEventListener('mousemove', onMove);
  198.         document.addEventListener('touchmove', onMove);
  199.  
  200.         document.addEventListener('mouseup', onUp);
  201.         document.addEventListener('touchend', onUp);
  202.  
  203.         document.addEventListener('click', onClick);
  204.         document.addEventListener('touchend', onClick);
  205.       })();
  206.     </script>
  207.   </body>
  208. </html>

SVG based drawing program.

// css // javascript // svg // ui

Easy Hex Color Invert

  1. let color = 0xFFFF00;
  2.  
  3. function toHexString(col) { 
  4.   return '#' + ('000000' + col.toString(16)).substr(-6);
  5. }
  6.  
  7. function onClick() {
  8.   // invert the color
  9.   color ^= 0xFFFFFF;
  10.   document.body.style.background = toHexString(color);
  11. }
  12.  
  13. onClick();
  14.  
  15. document.addEventListener('click', onClick);
  16.  
  17. console.log('try a different initial color');
  18. console.log('click anywhere to invert background...');

Easily invert a hex color. Expanding on yesterdays post – just one of many reasons you may want to work with colors in their integer form.

// color // hex // javascript // math // tricks
snippet.zone ~ 2021-24 /// {s/z}