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

Conic Gradient CSS

  1. <div></div>
  2. <style>
  3.   div {
  4.     width: 200px;
  5.     height: 200px;
  6.     background: conic-gradient(red, yellow, lime, aqua, blue, magenta, red);
  7.   }
  8. </style>


CSS conic gradient. I got this snippet from CSS Tricks article… 😀

// css // gradients // graphics // html

Interesting Color Picker

  1. document.addEventListener('touchmove', e => e.preventDefault(), {
  2.   passive: false
  3. });
  4.  
  5. document.body.innerHTML += `
  6. <style>
  7.   * {
  8.     -moz-user-select: none;
  9.     -webkit-user-select: none;
  10.     -ms-user-select: none;
  11.     user-select: none;
  12.   }
  13.   body {
  14.     background: #333;
  15.   }
  16.   .select-box {
  17.     border: 1px solid white;
  18.     outline: 1px solid black;
  19.   }
  20.   .swatch {
  21.     border: none;
  22.     outline: none;
  23.   }
  24. </style>
  25. `;
  26.  
  27. const col = document.body.appendChild(document.createElement('div'));
  28. Object.assign(col.style, {
  29.   position: 'absolute',
  30.   left: 0,
  31.   top: 0,
  32.   width: '100%',
  33.   height: '200px',
  34.   background:
  35.     `linear-gradient(0, black 0%, transparent 50%, transparent 50%, white 100%), 
  36.      linear-gradient(90deg, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)`
  37. });
  38.  
  39. const swatches = document.body.appendChild(document.createElement('div'));
  40. Object.assign(swatches.style, {
  41.   position: 'absolute',
  42.   top: '200px',
  43.   left: 0,
  44.   width: '100%'
  45. });
  46.  
  47. function box(x, y, cls = 'select-box', parent = document.body) {
  48.   const box = parent.appendChild(document.createElement`div`);
  49.   box.classList.add(cls);
  50.   Object.assign(box.style, {
  51.     position: 'absolute',
  52.     left: `${x}%`,
  53.     top: `${y}px`,
  54.     width: '40px',
  55.     height: '40px',
  56.     background: 'none',
  57.     transform: 'translate(-50%, -50%)',
  58.     cursor: 'pointer',
  59.  
  60.     color: 'white'
  61.   });
  62.   return box;
  63. }
  64.  
  65. function touch(e) {
  66.   let x = e.clientX;
  67.   let y = e.clientY;
  68.   if (e.touches != null && e.touches.length > 0) {
  69.     x = e.touches[0].clientX;
  70.     y = e.touches[0].clientY;
  71.   }
  72.   return { x, y };
  73. }
  74.  
  75. document.addEventListener('touchstart', onDown);
  76. document.addEventListener('touchmove', onMove);
  77. document.addEventListener('touchend', onUp);
  78. document.addEventListener('mousedown', onDown);
  79. document.addEventListener('mousemove', onMove);
  80. document.addEventListener('mouseup', onUp);
  81.  
  82. let down = false;
  83. let currBox;
  84. let currSwatch;
  85. let swatchHeight = 30;
  86. let id = 0;
  87.  
  88. function toHSL(x, y) {
  89.   let deg = x * 360;
  90.   return `hsl(${deg}deg, 100%, ${100 - y / 2}%)`;
  91. }
  92.  
  93. function onDown(e) {
  94.   let { x, y } = touch(e);
  95.   down = true;
  96.   let hPercent = x / innerWidth;
  97.   let color = toHSL(hPercent, y);
  98.   if (e.target.classList.contains('swatch')) {
  99.     e.target.style.outline = '2px solid red';
  100.     e.target.style.zIndex = 999;
  101.     down = false;
  102.     setTimeout(() => {
  103.       if (confirm('Would you like to remove this swatch?')) {
  104.         currBox = document.querySelector(
  105.           `.select-box[data-id="${e.target.dataset.id}"]`
  106.         );
  107.  
  108.         if (currBox != null) {
  109.           currBox.parentNode.removeChild(currBox);
  110.           e.target.parentNode.removeChild(e.target);
  111.         }
  112.       } else {
  113.         e.target.style.outline = null;
  114.         e.target.style.zIndex = null;
  115.       }
  116.     }, 250);
  117.   } else if (e.target.classList.contains('select-box')) {
  118.     currBox = e.target;
  119.     c = document.querySelector(`.swatch[data-id="${currBox.dataset.id}"]`);
  120.   } else {
  121.     currBox = box(hPercent * 100, y);
  122.     currBox.dataset.id = id++;
  123.     currSwatch = box(0, 0, 'swatch', swatches);
  124.     currSwatch.dataset.id = currBox.dataset.id;
  125.     Object.assign(currSwatch.style, {
  126.       width: '100%',
  127.       position: 'relative',
  128.       height: `${swatchHeight}px`,
  129.       transform: 'none',
  130.       background: color
  131.     });
  132.   }
  133. }
  134.  
  135. function onMove(e) {
  136.   if (down) {
  137.     let { x, y } = touch(e);
  138.     let hPercent = x / innerWidth;
  139.     let color = toHSL(hPercent, y);
  140.     Object.assign(currBox.style, {
  141.       left: `${hPercent * 100}%`,
  142.       top: `${y}px`
  143.     });
  144.     currSwatch.style.background = color;
  145.   }
  146. }
  147.  
  148. function onUp(e) {
  149.   down = false;
  150.   currBox = null;
  151. }

Click anywhere on the spectrum to add a color… color boxes can be dragged, color swatches can be deleted by clicking on them…

Just something that popped into my head awhile back so figured I’d do a speed-coded prototype. I’d like to revisit this and add more to it.

Animate to Target

  1. function box(x, y, col = 'red', cursor){
  2.   const box = document.body.appendChild(
  3.     document.createElement`div`
  4.   )
  5.   box.classList.add(col + '-box')
  6.   Object.assign(box.style, {
  7.     position: 'absolute', 
  8.     left: `${x}%`,
  9.     top: `${y}%`,
  10.     width: '30px',
  11.     height: '30px',
  12.     background: col,
  13.     cursor: cursor || 'pointer',
  14.     color: 'white'
  15.   })
  16.   return box
  17. }
  18.  
  19. const NUM = 10;
  20. for (let i = 0; i < NUM; i++) 
  21.   box(
  22.     Math.random() * 100, 
  23.     Math.random() * 100)
  24.  
  25.  
  26. let destX = destY = x = y = 0;
  27. const blue = box(destX, destY, 'blue', 'default')
  28. const info = box(0, 30, 'gray')
  29. info.innerHTML = 'click the red boxes'
  30. Object.assign(info.style, {
  31.   width: '100%', 
  32.   padding: '.5em',
  33.   fontFamily: 'sans-serif'
  34. })
  35.  
  36. document.addEventListener('click', e => {
  37.   const curr = e.target
  38.   if (curr.classList.contains('red-box')) {
  39.     destX = curr.offsetLeft
  40.     destY = curr.offsetTop
  41.     curr.style.background = 'black'
  42.     setTimeout(() => curr.style.background = 'red', 700)
  43.     if (info.parentNode != null) { 
  44.       info.parentNode.removeChild(info);
  45.     }
  46.   }
  47. })
  48.  
  49. function loop() {
  50.   x += (destX - x) / 12
  51.   y += (destY - y) / 12
  52.   blue.style.transform = `translate3d(${x}px, ${y}px, 0)`
  53.   requestAnimationFrame(loop)
  54. }
  55. loop()

Click a red box, watch the blue box animate…

Speed Coded HTML Templating Thoughts

  1. const tmpl = `
  2.   main
  3.     h1 Welcome
  4.     hr
  5.     nav
  6.       button one
  7.       button two
  8.       button three
  9.     hr
  10.     p this is a test
  11.     p this is another test
  12.     textarea hello
  13.     ul 
  14.       li alpha
  15.       li beta
  16.       li zeta
  17.         ul 
  18.           li organize
  19.           li things
  20.       li and stuff
  21.   hr
  22.   footer 2022
  23. `
  24.  
  25. let htm = parse(tmpl);
  26. document.body.innerHTML += htm
  27. console.log(htm)
  28.  
  29. function isTag(tag) { 
  30.   return !/Unknown/.test(document.createElement(tag) + '')
  31. }
  32.  
  33. function parse(input) {
  34.   let lines = input.split(/\n/)
  35.   let html = []
  36.   let closeTags = []
  37.   let lastIndent = 0;
  38.  
  39.   for (let i = 1; i < lines.length; i++) {
  40.     let indent = 0;
  41.     let tag = '';
  42.     let content = ''
  43.     let line = lines[i]
  44.     let mode = 'start';
  45.  
  46.     for (let j = 0; j < line.length; j++) {
  47.       const char = line[j]
  48.       if (char == ' ' && mode === 'start') {
  49.         indent++;
  50.       } else if (char != ' ' && mode != 'content') {
  51.         mode = 'tag'
  52.         tag += char
  53.       } else {
  54.         mode = 'content'
  55.         content += char;
  56.       }
  57.     }
  58.  
  59.     if (indent <= lastIndent && closeTags.length > 0) {
  60.         let back = lastIndent
  61.         while(back >= indent) {
  62.           html.push(closeTags.pop())
  63.           back -= 2
  64.         }
  65.     }
  66.  
  67.     if (tag.length > 0) { 
  68.       let xtra = ''
  69.       let origTag = tag; 
  70.  
  71.       if (!isTag(tag)) {
  72.         tag = 'div'
  73.         xtra = ` class="${origTag}" `
  74.       }
  75.       closeTags.push(`</${tag}>`)
  76.       html.push(`<${tag + xtra}>`)
  77.       if (content.length > 0) html.push(content)
  78.     }
  79.  
  80.     lastIndent = indent;
  81.   }
  82.  
  83.   return [...html, ...closeTags.reverse()].join('')
  84. }

Parse a minimalistic html template inspired by the likes of jade, haml, pug etc… This is very speed-coded. I may revisit the same thing with a bit more of an elegant approach in the future.

// html // javascript // strings // ui

Check if HTML Tag is Valid

  1. const isTag = tag => { 
  2.   return !/Unknown/.test(document.createElement(tag) + '')
  3. }
  4.  
  5. console.log('section:', isTag('section'))
  6. console.log('div:', isTag('div'))
  7. console.log('nav:', isTag('nav'))
  8. console.log('banana:', isTag('banana'))

Check if a tagName is a valid html element.

When casting a dom node to a string, you’ll get a class name like this:

  1. document.createElement('div') + ''
  2. // '[object HTMLDivElement]'
  3.  
  4. // you can cast to a string with `toString` if 
  5. // you want things to be more readable
  6. document.createElement('section').toString()
  7. // '[object HTMLElement]'
  8.  
  9. document.createElement('input') + ''
  10. // '[object HTMLInputElement]'

When you try to create something with an unknown tagName you’ll end up with:

  1. document.createElement('banana') + ''
  2. // '[object HTMLUnknownElement]'

So, testing for the presence of the string Unknown is an easy way to check if a tagName is valid in a given browser. This is the perfect kind of thing to memoize:

  1. const tags = {}
  2. const isTag = tag => { 
  3.   if (tags[tag] != null) {
  4.     // already calculated
  5.     console.log('loking up: ', tag, tags[tag]);
  6.     return tags[tag]
  7.   }
  8.   const result = !/Unknown/.test(document.createElement(tag) + '')
  9.   tags[tag] = result
  10.   return result
  11. }
  12.  
  13. console.log('calculator', isTag('calculator'))
  14. console.log('calculator', isTag('calculator'))
  15.  
  16. console.log('strong', isTag('strong'))
  17. console.log('strong', isTag('strong'))
// dom // html // javascript // regex // strings // tricks // ui
snippet.zone ~ 2021-24 /// {s/z}