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

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

Upload Image

  1. const uploadInput = document.body.appendChild(
  2.   Object.assign(document.createElement('input'), {
  3.     type: 'file',
  4.     accept: 'image/png, image/jpeg'
  5.   })
  6. );
  7.  
  8. const imageEl = document.body.appendChild(
  9.   Object.assign(document.createElement('img'), {
  10.     style: `
  11.             display:block;
  12.             width: 100%;
  13.           `
  14.   })
  15. );
  16.  
  17. const reader = new FileReader();
  18.  
  19. reader.addEventListener('load', () => {
  20.   imageEl.src = reader.result;
  21. });
  22.  
  23. uploadInput.addEventListener('change', e => {
  24.   const file = e.target.files[0];
  25.   if (file != null) {
  26.     reader.readAsDataURL(file);
  27.   }
  28. });

Load an image into memory…

// images // javascript // ui

Snippet Zone Code Highlighter

I wrote a naive syntax highlighter a few weeks ago. Here it is rendering the code for itself. :

This is not a perfect highlighter, but it was fun to create and I will definitely use it in the Snippet Zone Github repository once I get that set up.

There is some css that goes with the highlighter, it’s pretty boring, but here it is anyway:

  1. .hh {
  2.   white-space: pre-wrap;
  3.   font-family: monaco, monospace;
  4.   line-height: 1.5;
  5.   font-size: .8em;
  6.   background: rgb(3, 21, 36);
  7.   color: rgba(156, 221, 254, 1);
  8.   padding: 1em;
  9. }
  10.  
  11. .hh b {
  12.   font-weight: normal;
  13. }
  14.  
  15. .hh i {
  16.   color: #1ad6ae;
  17. }
  18.  
  19. .hh u {
  20.   color: rgb(255, 195, 252);
  21.   text-decoration: none;
  22. }
  23.  
  24. .num {
  25.   color: #b5cea8;
  26. }
  27.  
  28. .str, .str b  {
  29.   color: #ce9178;
  30. }
  31.  
  32. .par {
  33.   color: white;
  34.   font-weight: bold;
  35. }
  36.  
  37. .brk {
  38.   color: white;
  39.   font-weight: bold;
  40. }
  41.  
  42. .o {
  43.   color: rgb(0, 151, 221);
  44. }
  45.  
  46. .obj {
  47.   color: rgb(52, 206, 47);
  48.   font-weight: bold !important;
  49. }
  50.  
  51. .w {
  52.   color: #1ad6ae;
  53.   font-style: italic;
  54. }
  55.  
  56. .k {
  57.   color: aqua;
  58. }
  59.  
  60. .cmt {
  61.   color: gray !important;
  62. }
  63. .cmt b {
  64.   color: gray !important;
  65. }

I have no idea why I used such bad class names there 😛

// css // dom // javascript // meta // strings // ui

Complementary HSL

  1. const a = document.body.appendChild(document.createElement('div')),
  2.       b = document.body.appendChild(document.createElement('div'));
  3. let degA = degB = 0;
  4.  
  5. const size = {
  6.   width: '100px',
  7.   height: '100px'
  8. };
  9. Object.assign(a.style, size);
  10. Object.assign(b.style, size);
  11.  
  12. function loop() {
  13.   degA += 1;
  14.   degB = degA + 180;
  15.   a.style.background = `hsl(${degA}deg, 100%, 50%)`;
  16.   b.style.background = `hsl(${degB}deg, 100%, 50%)`;
  17.   requestAnimationFrame(loop);
  18. }
  19. loop();

In HSL a hue difference of 180 degrees between two values will create a set of complimentary colors.

// animation // color // css // dom // javascript // tricks // ui
snippet.zone ~ 2021-24 /// {s/z}