/ Gists / JavaScript

Gists - JavaScript

On gists

DOM Tricks

JavaScript

tricks.js #

// https://medium.com/@ThinkingLoop/12-dom-tricks-no-libraries-required-61268e398c50

// 1) Query once, act many
const $ = (sel, root = document) => root.querySelector(sel);
const $$ = (sel, root = document) => [...root.querySelectorAll(sel)];

const app = $('#app');
const buttons = $$('.action', app);

buttons.forEach(btn => btn.addEventListener('click', onAction));


// 2) Event delegation (one listener, infinite items)
$('#list').addEventListener('click', e => {
  const btn = e.target.closest('[data-action="remove"]');
  if (!btn) return;
  e.preventDefault();
  btn.closest('li')?.remove();
});

// when we dont want use e.preventDeafult() -> pasive: true, better optimalization
window.addEventListener('scroll', onScroll, { passive: true });


// 3) Build with DocumentFragment (no layout thrash)
const frag = document.createDocumentFragment();
for (const item of data) {
  const li = document.createElement('li');
  li.textContent = item.name;
  frag.appendChild(li);
}
$('#list').appendChild(frag); // one commit


// 4) Render HTML safely with <template>
<template id="row-tpl">
  <li class="row">
    <span class="name"></span>
    <button data-action="remove">×</button>
  </li>
</template>

function renderRow(user) {
  const tpl = $('#row-tpl').content.cloneNode(true);
  tpl.querySelector('.name').textContent = user.name;
  return tpl;
}

const frag = document.createDocumentFragment();
users.forEach(u => frag.appendChild(renderRow(u)));
$('#list').appendChild(frag);



// 5) Class toggles beat inline styles
.card { transition: transform .2s ease; }
.card.is-active { transform: scale(1.02); }
$('.card').classList.toggle('is-active', shouldHighlight);



// 6) dataset for behavior, not style
<button data-action="copy" data-copy-text="Hello!">Copy</button>
document.addEventListener('click', e => {
  const btn = e.target.closest('[data-action="copy"]');
  if (!btn) return;
  navigator.clipboard.writeText(btn.dataset.copyText);
});


// 7) Observe, don’t poll (Intersection/Resize/Mutation)
// IntersectionObserver: lazy-load images
const io = new IntersectionObserver(entries => {
  entries.forEach(({ isIntersecting, target }) => {
    if (!isIntersecting) return;
    target.src = target.dataset.src;
    io.unobserve(target);
  });
}, { rootMargin: '200px' });

$$('img[data-src]').forEach(img => io.observe(img));

// ResizeObserver: reflow grids on size change
const ro = new ResizeObserver(entries => {
  for (const { target } of entries) layout(target);
});
ro.observe($('#grid'));


// 8) Batch mutations with requestAnimationFrame
function highlightRow(row) {
  // READ
  const { top } = row.getBoundingClientRect();

  // Schedule WRITE
  requestAnimationFrame(() => {
    row.style.setProperty('--start', `${top}px`);
    row.classList.add('highlight');
  });
}


// 9) Virtualize long lists with windowing
const viewport = $('#viewport');
const rowHeight = 32;
let start = 0, end = 0;

viewport.addEventListener('scroll', render);
window.addEventListener('resize', render);

function render() {
  const { scrollTop, clientHeight } = viewport;
  start = Math.floor(scrollTop / rowHeight);
  end = start + Math.ceil(clientHeight / rowHeight) + 5;

  const frag = document.createDocumentFragment();
  viewport.innerHTML = ''; // clear (or recycle nodes for extra perf)
  for (let i = start; i < Math.min(end, data.length); i++) {
    const div = document.createElement('div');
    div.className = 'row';
    div.style.top = `${i * rowHeight}px`;
    div.textContent = data[i].name;
    frag.appendChild(div);
  }
  viewport.appendChild(frag);
}

#viewport { position: relative; overflow: auto; height: 400px; }
.row { position: absolute; height: 32px; line-height: 32px; left: 0; right: 0; }


// 10) Custom events for clean boundaries
/ producer
function notifySaved(node, payload) {
  node.dispatchEvent(new CustomEvent('saved', { detail: payload, bubbles: true }));
}

// consumer
document.addEventListener('saved', e => {
  const { id } = e.detail;
  toast(`Saved #${id}`);
});



// 11) Progressive enhancement with feature checks
const supportsClipboard = !!navigator.clipboard?.writeText;

if (supportsClipboard) {
  document.body.classList.add('has-clipboard');
  // enable fancy copy button
} else {
  // use <input> select() + execCommand fallback or plain text
}


// 12) Micro-router: data-route + history.pushState

<nav>
  <a href="/settings" data-route>Settings</a>
  <a href="/reports"  data-route>Reports</a>
</nav>
<main id="view"></main>

const routes = {
  '/settings': () => $('#view').textContent = 'Settings ⚙️',
  '/reports':  () => $('#view').textContent = 'Reports 📈',
};

function go(path) {
  history.pushState({}, '', path);
  routes[path]?.();
}

document.addEventListener('click', e => {
  const link = e.target.closest('a[data-route]');
  if (!link) return;
  e.preventDefault();
  go(new URL(link.href).pathname);
});

window.addEventListener('popstate', () => routes[location.pathname]?.());
routes[location.pathname]?.(); // initial

On gists

Reexport ES exports

JavaScript

ex.js #

// index.js
export * as MathUtils from "./math.js";
export * as StringUtils from "./string-utils.js";

// Usage:
// import { MathUtils, StringUtils } from './index.js';





// modules/index.js
export { default as Calculator } from "./calculator.js";
export { default as Logger } from "./logger.js";
export * from "./math.js";
export * from "./string-utils.js";
export { ApiClient as Client, HTTP_METHODS as Methods } from "./config.js";

On gists

4 ways to dynamically execute JavaScript code on the front end

JavaScript

HOW.JS #

// https://medium.com/@bestowensss/4-ways-to-dynamically-execute-javascript-code-on-the-front-end-01648b4f527a

// 1
/*
Synchronous execution;
The execution context is the current scope .
*/
let a = 1;
function test() {
  let a = 2;
  eval('console.log(a)'); // 2
}
test();


// 2
/*
Synchronous execution;
The execution environment is the global scope .
*/
let a = 1;
function test() {
  let a = 2;
  let fn = new Function('console.log(a)');
  fn(); // 1
}
test();


// 3
// 2
/*
Asynchronous execution;
The execution environment is the global scope .
*/
let a = 1;
function test() {
  let a = 2;
  setTimeout('console.log(a)', 1000); // 1
}
test();


//4 
/*
Synchronous execution;
The execution environment is the global scope .
*/
var a = 1;
let script = document.createElement('script');
script.textContent = 'console.log(1)';
document.body.appendChild(script); // 1

On gists

Advanced Patterns: Mixins and Composition

JavaScript-OOP JavaScript

composition.js #

// https://medium.com/@genildocs/mastering-object-oriented-programming-in-javascript-from-zero-to-hero-c718c3182eba

// Mixin for logging functionality
const LoggerMixin = {
  log(message) {
    console.log(`[${this.constructor.name}] ${message}`);
  },

  logError(error) {
    console.error(`[${this.constructor.name}] ERROR: ${error}`);
  }
};

// Mixin for validation
const ValidatorMixin = {
  validate(data, rules) {
    for (const [field, rule] of Object.entries(rules)) {
      if (!rule(data[field])) {
        return { valid: false, field };
      }
    }
    return { valid: true };
  }
};

class UserService {
  constructor() {
    // Apply mixins
    Object.assign(this, LoggerMixin, ValidatorMixin);
  }

On gists

3 Vanilla-Lite DOM Patterns That Achieve jQuery’s Ease

JavaScript-OOP JavaScript

1.js #

// Pattern 1 — Bind Helper

export function S(selector) {
  const nodes = document.querySelectorAll(selector);
  nodes.forEach(bindAll); // Bind helpers to node(s)

  return nodes.length > 1 ? nodes : nodes[0]; // native node(s) returned
}

export function C(tag) {
  const node = document.createElement(tag);
  return bindAll(node); // Bind helpers to node(s)
}

function bindAll(node) {
  node.addClass = addClass.bind(node);
  node.attr = attr.bind(node);

  return node;
}

//--- Extension functions ---//
function addClass(...cls)   {
  this.classList.add(...cls);
  return this;
}

function attr(key, val) {
  if (val !== undefined) {
    this.setAttribute(key, val);
    return this; 
  }

  return this.getAttribute(key);
}


// Usage:
import { S, C } from './helper.js';

const btn = C('button').addClass('btn', 'primary').attr('type', 'submit');
btn.click(); // native method

S('.card').forEach(el => el.addClass('highlight').attr('data-live', '1'));

On gists

Supertips - 50

JavaScript

supertips.js #

/*
@source: https://javascript.plainenglish.io/50-javascript-shortcuts-that-will-make-you-a-code-wizard-in-2025-14dd7aee319c
*/

// 1. Ternary Operator
const status = loggedIn ? "Welcome!" : "Please login.";
// 2. Default Parameters
function greet(name = "Stranger") {
  return `Hello, ${name}`;
}
// 3. Arrow Functions
const multiply = (a, b) => a * b;
// 4. Destructuring Objects
const { title, year } = movie;
// 5. Destructuring Arrays
const [first, second] = topResults;
// 6. Template Literals
const greeting = `Hey, ${user.name}!`;
// 7. Spread Operator
const newTeam = [...oldTeam, "Alice"];
// 8. Rest Parameters
function logAll(...args) {
  console.log(args);
}
// 9. Optional Chaining
const city = user?.address?.city;
// 10. Nullish Coalescing
const nickname = inputName ?? "Anonymous";
// 12. Logical OR Assignment
settings.volume ||= 50;
// 13. Logical AND Assignment
user.isAdmin &&= false;
// 14. Object Property Shorthand
const age = 24;
const person = { name, age };
// 15. Computed Property Names
const field = "score";
const stats = { [field]: 100 };
// 16. For-of Loop
for (const char of name) {
  console.log(char);
}
// 17. forEach
tags.forEach(tag => console.log(`#${tag}`));
// 18. map()
const lengths = names.map(n => n.length);
// 19. filter()
const passed = grades.filter(g => g >= 60);
// 20. reduce()
const sum = numbers.reduce((a, b) => a + b, 0);
// 21. includes()
if (items.includes("🚀")) launch();
// 22. Unique Array with Set
const unique = [...new Set(tags)];
// 23. Object.entries()
Object.entries(data).forEach(([k, v]) => console.log(k, v));
// 24. Object.values()
const values = Object.values(config);
// 25. Object.keys()
const keys = Object.keys(settings);
// 26. Array Method Chaining
data.filter(a => a.active).map(a => a.name);
// 27. Flatten Arrays
const flat = nested.flat(2);
// 28. String.trim()
const cleaned = input.trim();
// 29. padStart()
const padded = id.padStart(5, "0");
// 30. Format Numbers
const price = new Intl.NumberFormat().format(1234567);
// 31. Dynamic Import
const module = await import("./utils.js");
// 32. Promise.all()
await Promise.all([loadUser(), loadPosts()]);
// 33. Async/Await
const getData = async () => {
  const res = await fetch(url);
  return await res.json();
};
// 34. Optional Function Params
function log(message, level = "info") {
  console[level](message);
}
// 35. Number Conversion with +
const num = +"42";
// 36. Boolean Conversion with !!
const isValid = !!userInput;
// 37. Swap Values
[a, b] = [b, a];
// 38. String to Array
const chars = [..."dev"];
// 39. Clone Object
const copy = { ...original };
// 40. Debounce
const debounce = (fn, delay) => {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
};
// 41. Named Capture Groups in Regex
const url = "https://dev.to";
const match = url.match(/(?<protocol>https?):\/\/(?<host>.+)/);
console.log(match.groups);
// 42. ??= Operator
data.username ??= "guest";
// 43. Numeric Separators
const big = 1_000_000_000;
// 44. Top-Level await (in modules)
const user = await fetchUser();
// 45. Array.from with Map
const numbers = Array.from(new Set([1, 2, 2, 3]));
// 46. Group Array by Property
const grouped = data.reduce((acc, obj) => {
  acc[obj.type] = acc[obj.type] || [];
  acc[obj.type].push(obj);
  return acc;
}, {});
// 47. isFinite()
if (isFinite(num)) { /* safe to use */ }
// 48. Abort Fetch Request
const controller = new AbortController();
fetch(url, { signal: controller.signal });
controller.abort();
// 49. toLocaleString()
(1234567.89).toLocaleString("en-US", {
  style: "currency",
  currency: "USD"
});
// 50. StructuredClone
const clone = structuredClone(myObj);

On gists

Object iteration ways ...

JavaScript

object.js #

const user = { name: "Alice", age: 30 };

// 1. for...in loop - iteruje přes všechny enumerable vlastnosti
console.log("1. for...in loop:");
for (let key in user) {
  console.log(`${key}: ${user[key]}`);
}

// 2. Object.keys() - vrací pole klíčů
console.log("\n2. Object.keys():");
Object.keys(user).forEach(key => {
  console.log(`${key}: ${user[key]}`);
});

// 3. Object.values() - vrací pole hodnot
console.log("\n3. Object.values():");
Object.values(user).forEach(value => {
  console.log(value);
});

// 4. Object.entries() - vrací pole párů [klíč, hodnota]
console.log("\n4. Object.entries():");
Object.entries(user).forEach(([key, value]) => {
  console.log(`${key}: ${value}`);
});

// 5. Object.entries() s for...of
console.log("\n5. Object.entries() s for...of:");
for (let [key, value] of Object.entries(user)) {
  console.log(`${key}: ${value}`);
}

// 6. Object.keys() s for...of
console.log("\n6. Object.keys() s for...of:");
for (let key of Object.keys(user)) {
  console.log(`${key}: ${user[key]}`);
}

// 7. Object.getOwnPropertyNames() - včetně non-enumerable vlastností
console.log("\n7. Object.getOwnPropertyNames():");
Object.getOwnPropertyNames(user).forEach(key => {
  console.log(`${key}: ${user[key]}`);
});

// 8. Reflect.ownKeys() - všechny vlastnosti včetně Symbolů
console.log("\n8. Reflect.ownKeys():");
Reflect.ownKeys(user).forEach(key => {
  console.log(`${key}: ${user[key]}`);
});

// 9. Map() pro transformaci
console.log("\n9. Map() pro transformaci:");
const transformed = Object.entries(user).map(([key, value]) => `${key.toUpperCase()}: ${value}`);
console.log(transformed);

// 10. Reduce() pro akumulaci
console.log("\n10. Reduce() pro akumulaci:");
const result = Object.entries(user).reduce((acc, [key, value]) => {
  acc[key.toUpperCase()] = value;
  return acc;
}, {});
console.log(result);

// 11. Filter() pro filtrování
console.log("\n11. Filter() pro filtrování:");
const filtered = Object.entries(user).filter(([key, value]) => typeof value === 'string');
console.log(filtered);

// 12. Some() a Every() pro testování
console.log("\n12. Some() a Every():");
const hasString = Object.values(user).some(value => typeof value === 'string');
const allStrings = Object.values(user).every(value => typeof value === 'string');
console.log(`Obsahuje string: ${hasString}`);
console.log(`Všechny jsou stringy: ${allStrings}`);

// 13. JSON.stringify() s replacer funkcí
console.log("\n13. JSON.stringify() s replacer:");
JSON.stringify(user, (key, value) => {
  if (key !== '') console.log(`${key}: ${value}`);
  return value;
});

// 14. Object.hasOwnProperty() check
console.log("\n14. for...in s hasOwnProperty:");
for (let key in user) {
  if (user.hasOwnProperty(key)) {
    console.log(`${key}: ${user[key]}`);
  }
}

// 15. Destrukturování s rest operátorem
console.log("\n15. Destrukturování:");
const { name, ...rest } = user;
console.log(`name: ${name}`);
console.log('zbytek:', rest);

// 16. Použití s async/await (pokud by byly hodnoty Promise)
console.log("\n16. Async iterace (příklad):");
async function asyncIteration() {
  for (let [key, value] of Object.entries(user)) {
    // Simulace async operace
    await new Promise(resolve => setTimeout(resolve, 100));
    console.log(`Async: ${key}: ${value}`);
  }
}
// asyncIteration(); // odkomentuj pro spuštění

On gists

Scrolling on desktop with mouse in overflowed element (JS)

JavaScript

demo.html #

<!--
https://jsbin.com/bihofirugo/2/edit?html,css,output
-->

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>

	
	
	<div class="container">
    <img src="https://picsum.photos/id/237/200/300" alt="Foto 1">
		<img src="https://picsum.photos/id/237/200/300" alt="Foto 1">
		<img src="https://picsum.photos/id/237/200/300" alt="Foto 1">
		<img src="https://picsum.photos/id/237/200/300" alt="Foto 1">
		<img src="https://picsum.photos/id/237/200/300" alt="Foto 1">
		<img src="https://picsum.photos/id/237/200/300" alt="Foto 1">
		<img src="https://picsum.photos/id/237/200/300" alt="Foto 1">
		<img src="https://picsum.photos/id/237/200/300" alt="Foto 1">

</div>

<style>
.container {
    white-space: nowrap;
    overflow-x: auto;
    cursor: grab;
    user-select: none; /* Zabrání výběru textu nebo obrázků při tažení */
}

.container img {
    display: inline-block;
    width: 200px;
    height: 150px;
    pointer-events: none; /* Zabrání interakci s obrázky (např. drag-and-drop obrázků) */
}

.container.grabbing {
    cursor: grabbing;
}
</style>

<script>
const container = document.querySelector('.container');
let isDragging = false;
let startX;
let scrollLeft;

container.addEventListener('mousedown', (e) => {
    isDragging = true;
    container.classList.add('grabbing');
    startX = e.pageX - container.offsetLeft;
    scrollLeft = container.scrollLeft;
    e.preventDefault(); // Zabrání výchozímu chování (např. výběr textu)
});

container.addEventListener('mousemove', (e) => {
    if (!isDragging) return;
    e.preventDefault(); // Zabrání výchozímu chování při pohybu
    const x = e.pageX - container.offsetLeft;
    const walk = (x - startX) / 0.5; // Rychlost scrollování
    container.scrollLeft = scrollLeft - walk;
});

container.addEventListener('mouseup', () => {
    isDragging = false;
    container.classList.remove('grabbing');
});

container.addEventListener('mouseleave', () => {
    if (isDragging) {
        isDragging = false;
        container.classList.remove('grabbing');
    }
});

// Pro jistotu přidáme globální posluchač na mouseup, aby se tažení ukončilo i mimo kontejner
document.addEventListener('mouseup', () => {
    if (isDragging) {
        isDragging = false;
        container.classList.remove('grabbing');
    }
});
</script>
	
</body>
</html>

On gists

Smarter if

JavaScript Vue.js

code.js #

// Noob
const eventHandler = e => {
  if (e.key === 'Escape') {
    this.closeGallery()
  }
  if (e.key === 'ArrowLeft') {
    this.prevMedia()
  }
  if (e.key === 'ArrowRight') {
    this.nextMedia()
  }
}

// Profi
const eventHandler = e => {
  const keyActions = {
    Escape: closeGallery,
    ArrowLeft: prevMedia,
    ArrowRight: nextMedia
  }

  keyActions[e.key]?.()
}

On gists

All events in javascript

JavaScript

code.js #

Object.keys(window).forEach(key => {
  if (/^on/.test(key)) {
    window.addEventListener(key.slice(2), event => {
      console.log(event);
    });
  }
});