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

Proxy Quick DOM

  1. const spec = {
  2.   get(o, key) {
  3.     return o[key] != null ? 
  4.       o[key] : o[key] = (...args) => {
  5.         const el = document.createElement(key);
  6.         args.forEach(arg => { 
  7.           if (typeof arg === 'string') {
  8.             const span = document.createElement('span');
  9.             span.innerHTML = arg;
  10.             el.appendChild(span);
  11.           } else if (typeof arg === 'object') {
  12.             if (arg.tagName != null) {
  13.               el.appendChild(arg);
  14.             } else {
  15.               for (let i in arg) {
  16.                 el.setAttribute(i, arg[i]);
  17.               }
  18.             }
  19.           }
  20.         });
  21.         return el;
  22.       }
  23.   },
  24.   set(o, key, v) {
  25.     o[key] = v;
  26.   }
  27. }
  28.  
  29. const dom = new Proxy({}, spec);
  30.  
  31. document.body.appendChild(
  32.   dom.div(
  33.     dom.button('cool'), 
  34.     dom.h2('some text', { style: 'font-style: italic' }), 
  35.     dom.br(), 
  36.     dom.input({ placeholder: 'zevan' })
  37.   )
  38. );
  39.  
  40. const { div, input, label } = dom;
  41. document.body.appendChild(
  42.   div(
  43.     label(
  44.       'Slider:',
  45.       { 
  46.         for: 'slider', 
  47.         style: 'padding:1em;display:block' 
  48.       },
  49.       input({ id: 'slider', type: 'range' })
  50.     )
  51.   )
  52. );

In this snippet a proxy is used that makes all html node tagNames valid methods. Each method can take strings and HTMLElements as arguments in any order to create a dom structure. This may look familiar to people who have looked a bit deeper into the inner workings of some of the popular UI libraries of the last decade.

// dom // hacks // javascript // proxies // tricks // ui

Add Getter Setter to Object

  1. const target = {}
  2.  
  3. let value = null;
  4. Object.defineProperties(target, {
  5.   magic: {
  6.     get() {
  7.       console.log('- getter called::', value);
  8.       return value;
  9.     },
  10.     set(val) {
  11.       document.body.innerHTML += val + '<br>';
  12.       value = val;
  13.     }
  14.   }
  15. });
  16.  
  17. target.magic = 'xyz';
  18. target.magic = 'snippet';
  19. target.magic = 'zone';
  20. target.magic = '- last value';
  21.  
  22. console.log('getting', target.magic);

This snippet shows a way to add getters and setters to a specific key of an existing object. This is powerful for decorating configuration objects with special behaviors. This kind of thing can easily be created with a little more abstraction:

  1. const image = view({
  2.   tag: 'img', 
  3.   src: 'myImage.jpg',
  4.   x: '20%', 
  5.   y: '20%',
  6.   size: '50%'
  7. });
  8. const prev = view({
  9.   tag: 'button',
  10.   x: () => image.x,
  11.   y: () => image.bottom
  12. });
  13. const next = view({
  14.   tag: 'button',
  15.   x: () => image.right - this.width,
  16.   y: () => image.bottom
  17. });

Nonsense Logs

  1. const SPEED = 700;
  2.  
  3. const addKeys = obj => {
  4.   obj.keys = Object.keys(obj)
  5.   return obj
  6. }
  7.  
  8. const wordParts = {
  9.   start: addKeys({
  10.     z: .3,
  11.     zim: .1,
  12.     zz: .1,
  13.     zzz: .1,
  14.     ziz: .05,
  15.     zoo: .1,
  16.     koe: .05,
  17.     kob: .05,
  18.     'cow cow': .1,
  19.     'how ': .02,
  20.     sl: .1,
  21.     ko: .05
  22.   }),
  23.  
  24.   mid: addKeys({
  25.     i: .1,
  26.     oo: .1,
  27.     a: .1,
  28.     e: .3,
  29.     oe: .1,
  30.     ebobe: .1,
  31.     y: .1
  32.   }),
  33.  
  34.   end: addKeys({
  35.     z: .3,
  36.     n: .1,
  37.     t: .05,
  38.     rat: .1,
  39.     '!': .05,
  40.     '?': .05,
  41.     '': .1
  42.   })
  43. };
  44.  
  45. const wordPart = (
  46.     type,
  47.     dupeOdds = .1,
  48.     dupeMax = 8,
  49.     capOdds = .05
  50.   ) => {
  51.  
  52.   let result = '';
  53.   const part = wordParts[type];
  54.   while (result === '') {
  55.     const choice = part.keys[
  56.       Math.floor(Math.random() * part.keys.length)
  57.     ];
  58.     if (Math.random() < part[choice]) {
  59.       result = choice;
  60.       if (Math.random() < dupeOdds) {
  61.         const dupes = Math.round(
  62.           Math.random() * Math.random() * dupeMax
  63.         );
  64.         result = result.repeat(dupes);
  65.       }
  66.     }
  67.   }
  68.   wordPart.accum += result;
  69.  
  70.   if (Math.random() < capOdds) {
  71.     wordPart.accum = wordPart.accum.toUpperCase()
  72.   }
  73.   return wordPart;
  74. }
  75. wordPart.accum  = '';
  76.  
  77. const word = () =>
  78.   wordPart('start')('mid')('end').accum + ' '
  79.  
  80. document.body.style.fontSize="2em";
  81. setInterval(() => {
  82.   document.body.innerHTML += word();
  83.   wordPart.accum = ''
  84. }, SPEED);

Sometimes to entertain myself I will write nonsense style print/log statements. Things like console.log('cowcow'). This snippet generates a variety of these kinds of phrases.

Random Hex Color (semi-golfed)

  1. document.body.innerHTML += 'click anywhere...'
  2.  
  3. onclick = () =>
  4.   document.body.style.background = 
  5.     `#${Math.random().toString(16).substr(-6)}`

I golfed this snippet slightly for no reason in particular. I recently posted a nice readable way to make random hsl colors. This snippet generates a random hexidecimal color.

How it works:

  1. Math.random() // random number between 0 and 1
  2.  
  3. .toString(16) // convert to hex string (something like "0.2d6bcee4198d4")
  4.  
  5. .substr(-6) // grab the last 6 characters

Here is a non-golfed version:

  1. const instructionsEl = document.createElement('p');
  2. instructionsEl.innerHTML = 'click anywhere...';
  3. document.body.appendChild(instructionsEl);
  4.  
  5. const randomHexColor = () => 
  6.   `#${Math.random().toString(16).substr(-6)}`;
  7.  
  8. document.addEventListener('click', () => {
  9.   document.body.style.background = randomHexColor();
  10. });
// codegolf // color // css // golfed // hex // javascript

Proxies and Dynamic Methods

  1. const spec = {
  2.   get(o, key) {
  3.     console.log(key, ':: key');
  4.     return o[key] != null ? 
  5.       o[key] : o[key] = () => {
  6.         document.body.innerHTML += `<div>${key}!</div>`;
  7.         return anyMethod();
  8.       }
  9.   },
  10.   set(o, key, v) {
  11.     o[key] = v;
  12.   }
  13. };
  14.  
  15. const anyMethod = () => new Proxy({}, spec);
  16.  
  17. anyMethod().now()
  18.   .this().is()
  19.   .pretty()
  20.   .cool()
  21.   .confusing()
  22.   .evil()?.or()
  23.   .maybe().powerful()
  24.   ['... what <b>do</b> <i>you</i><br>']()
  25.   .think();

Proxies can be used for all manner of strange “magic”. I can actually see some uses for this, might post in the next few days…

snippet.zone ~ 2021-24 /// {s/z}