/ Gists

Gists

On gists

Sticky header and how to solve the indentation?

CSS CSS trick

index.css #

/* 1 */
html {
  scroll-behavior: smooth;
  /* Set this to the height of your header */
  scroll-padding-top: 80px; 
}


/* 2 */
.anchor-section::before {
  content: "";
  display: block;
  /* Negative margin pulls the element back up */
  margin-top: -100px; 
  /* Height creates the "blocker" space */
  height: 100px; 
  visibility: hidden;
  pointer-events: none;
}

/* 3 */
section:target {
  border-top: 80px solid transparent;
  margin-top: -80px;
  background-clip: padding-box;
}

On gists

Prefetch/Preload/Preconnect

index.html #

<!--
https://medium.com/@TusharKanjariya/four-lines-in-head-changed-my-site-speed-449bfeb396a2
-->


<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My App</title>

  <!-- Step 1: Warm up third-party connections first -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link rel="dns-prefetch" href="https://analytics.myapp.com">

  <!-- Step 2: Preload critical current-page assets -->
  <link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
  <link rel="preload" href="/images/hero.webp" as="image">

  <!-- Step 3: Load stylesheets -->
  <link rel="stylesheet" href="/styles/main.css">
  <link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet">

  <!-- Step 4: Prefetch likely next pages (background, no urgency) -->
  <link rel="prefetch" href="/dashboard/bundle.js">
</head>

On gists

Turn off auto domain from selection - AW

AW

selection.php #

<?php 
$tableStructure = $this->connection->getStructure()->getTableStructure($table);
$tableStructure['domain_id']->setDomainFilter($bcId === self::ALL_BC ? false : ($bcId ?? $this->getCurrentBrandCloudId()));
$selection =  $this->connection->table($table, $tableStructure);

On gists

selection.php

selection.php #

<?php 
$tableStructure = $this->connection->getStructure()->getTableStructure($table);
$tableStructure['domain_id']->setDomainFilter($bcId === self::ALL_BC ? false : ($bcId ?? $this->getCurrentBrandCloudId()));
$selection =  $this->connection->table($table, $tableStructure);

On gists

JS news

JavaScript

index.js #

/*
========================================================
Modern JavaScript – Useful New APIs
========================================================

Krátký přehled několika moderních JS funkcí a API,
které zjednodušují async kód, práci s daty a generování ID.

Obsah:
1. crypto.randomUUID()
2. Iterator helpers
3. Promise.withResolvers()
4. Promise.try()
5. AbortSignal.timeout()
6. AbortSignal.any()
7. structuredClone()

========================================================
*/


/*
========================================================
1. crypto.randomUUID()
========================================================

Generuje kryptograficky bezpečný UUID v4.
Není potřeba externí knihovna (např. uuid npm balík).
*/

const id = crypto.randomUUID();

console.log("UUID:", id);
// example: "36b8f84d-df4e-4d49-b662-bcde71a8764f"

/*
Use cases
- generování ID objektů
- correlation id pro requesty
- temporary keys
- client side identifiers
*/



/*
========================================================
2. Iterator Helpers
========================================================

Umožňují lazy operace nad iterátory.

Výhoda:
- nevytváří mezilehlá pole
- efektivnější pro velké datasety
- umožňují nekonečné sekvence
*/


// klasický array chain (vytváří mezivýsledky)

const arrayResult = [1,2,3,4,5]
  .map(x => x * 2)
  .filter(x => x > 5);

console.log("Array result:", arrayResult);


// iterator chain (lazy evaluation)

const iteratorResult =
  Iterator.from([1,2,3,4,5])
    .map(x => x * 2)
    .filter(x => x > 5)
    .toArray();

console.log("Iterator result:", iteratorResult);


// nekonečná sekvence

function* numbers() {
  let i = 0;
  while (true) {
    yield i++;
  }
}

const infiniteExample =
  Iterator.from(numbers())
    .map(x => x * 2)
    .take(5)
    .toArray();

console.log("Infinite sequence:", infiniteExample);




/*
========================================================
3. Promise.withResolvers()
========================================================

Elegantní způsob jak vytvořit Promise s externím
resolve / reject.

Nahrazuje starý "deferred promise" pattern.
*/


// moderní způsob

const { promise, resolve } = Promise.withResolvers();

setTimeout(() => {
  resolve("done");
}, 1000);

promise.then(console.log);



// example: wait for event

function waitForEvent(emitter, event) {

  const { promise, resolve } = Promise.withResolvers();

  emitter.once(event, resolve);

  return promise;

}



/*
========================================================
Async Queue Example
========================================================
*/

class AsyncQueue {

  constructor() {
    this.items = [];
    this.waiter = null;
  }

  push(item) {

    if (this.waiter) {
      this.waiter.resolve(item);
      this.waiter = null;
      return;
    }

    this.items.push(item);

  }

  async pop() {

    if (this.items.length) {
      return this.items.shift();
    }

    this.waiter = Promise.withResolvers();
    return this.waiter.promise;

  }

}



/*
========================================================
4. Promise.try()
========================================================

Pomáhá sjednotit sync a async funkce.

Automaticky zachytí chyby a vrátí rejected Promise.
*/


Promise.try(() => {
  return 5;
}).then(console.log);


// error handling

Promise.try(() => {
  throw new Error("boom");
}).catch(console.error);



// wrapper pattern

function run(handler) {
  return Promise.try(handler);
}

run(() => 5);
run(async () => fetch("/api"));
run(() => { throw "error"; });



/*
========================================================
5. AbortSignal.timeout()
========================================================

Jednoduché řešení timeoutů pro async operace.
Typicky se používá s fetch.
*/


async function fetchWithTimeout(url) {

  const response = await fetch(url, {
    signal: AbortSignal.timeout(5000)
  });

  return response.json();

}




/*
========================================================
6. AbortSignal.any()
========================================================

Kombinuje více abort signálů.

Operace se zruší pokud kterýkoliv signal abortne.
*/


async function fetchWithCancel(url) {

  const controller = new AbortController();

  const signal = AbortSignal.any([
    controller.signal,
    AbortSignal.timeout(5000)
  ]);

  const request = fetch(url, { signal });

  return {
    request,
    cancel: () => controller.abort()
  };

}



// example usage

async function example() {

  const { request, cancel } = fetchWithCancel("/api/data");

  setTimeout(cancel, 1000);

  try {
    const res = await request;
    console.log(await res.json());
  } catch (err) {
    console.log("Request cancelled or timeout");
  }

}



/*
========================================================
7. structuredClone()
========================================================

Nativní deep clone objektů.

Výhoda oproti JSON stringify:
- zachová typy
- funguje s Map, Set, Date, ArrayBuffer
*/


const original = {
  user: { name: "John" },
  created: new Date(),
  tags: new Set(["a","b"])
};

const clone = structuredClone(original);

console.log(original);
console.log(clone);



/*
========================================================
JSON clone problem
========================================================
*/

const badClone = JSON.parse(JSON.stringify(original));

// Date se změní na string
console.log("JSON clone:", badClone);



/*
========================================================
Summary
========================================================

Nejužitečnější moderní JS API:

crypto.randomUUID()
- generování unikátních ID

Iterator helpers
- lazy zpracování dat

Promise.withResolvers()
- async eventy, queue

Promise.try()
- sjednocení sync/async kódu

AbortSignal.timeout()
- timeout async operací

AbortSignal.any()
- kombinace více cancel signálů

structuredClone()
- deep clone objektů

========================================================
*/

On gists

Grid as HTML table

CSS

index.html #

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

	
	<html>
    <body>
        <div class="gridTable">
            <div> <!-- Header -->
                <div>Timeclock.Kiwi</div>
                <div>Payroll</div>
                <div>Checked</div>
            </div>
            
            <div> <!-- Body -->
                <div>
                    <div>Cat</div>
                    <div>In</div>
                    <div>Hat</div>
                </div>
                <div>
                    <div>Cat</div>
                    <div>In</div>
                    <div>Hat</div>
                </div>
                <div>
                    <div>Cat</div>
                    <div>In</div>
                    <div>Hat</div>
                </div>
                <div>
                    <div>Cat</div>
                    <div>In</div>
                    <div>Hat</div>
                </div>
            </div>
        </div>
    </body>
</html>
	
</body>
	
</html>

On gists

cn, cva, clx

React

how.js #

// 1 install
npm install class-variance-authority clsx tailwind-merge

// 2 /lib/utils.ts
/*
clsx handles conditional logic and class composition
tailwind-merge removes conflicting Tailwind classes
*/

import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"

cn("px-2 px-4") // => "px-4"


// 3 variant with cva
import { cva } from "class-variance-authority"
import { cn } from "@/lib/utils"

const buttonVariants = cva(
  "rounded px-4 py-2 font-medium transition",
  {
    variants: {
      variant: {
        primary: "bg-blue-500 text-white",
        secondary: "bg-gray-200 text-black",
      },
      size: {
        sm: "text-sm",
        lg: "text-lg",
      },
    },
    defaultVariants: {
      variant: "primary",
      size: "sm",
    },
  }
)
export function Button({ variant, size, className }) {
  return (
    <button
      className={cn(buttonVariants({ variant, size }), className)}
    />
  )
}

export function cn(...inputs: any[]) {
  return twMerge(clsx(inputs))
}


On gists

Zustand

React

zustand.js #

// 1 install
npm install zustand

// 2 create
// store.js
import { create } from 'zustand';

const useStore = create((set) => ({
  count: 0, // Initial state
  increase: () => set((state) => ({ count: state.count + 1 })),
  decrease: () => set((state) => ({ count: state.count - 1 })),
}));
export default useStore;

// 3 use
// App.js
import React from 'react';
import useStore from './store';

const Counter = () => {
  const { count, increase, decrease } = useStore((state) => ({
    count: state.count,
    increase: state.increase,
    decrease: state.decrease,
  }));
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increase}>Increase</button>
      <button onClick={decrease}>Decrease</button>
    </div>
  );
};
export default Counter;


//4 optional - middleware
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

const useStore = create(
  persist(
    (set) => ({
      count: 0,
      increase: () => set((state) => ({ count: state.count + 1 })),
    }),
    { name: 'counter-storage' } // Key for localStorage
  )
);
export default useStore;

On gists

PHP static kešování / memoizace

PHP

index.php #

<?php

declare(strict_types=1);

/**
 * ============================================================
 * VARIANTA 1
 * Jednoduchá request-level cache pomocí static proměnných
 * ============================================================
 */

function getExpensiveData(): mixed
{
    static $loaded = false;
    static $data;

    if (!$loaded) {
        $data = loadFromDatabase();
        $loaded = true;
    }

    return $data;
}



/**
 * ============================================================
 * VARIANTA 3
 * Univerzální memoize wrapper (funkcionální přístup)
 * ============================================================
 */

function memoize(callable $fn): callable
{
    $loaded = false;
    $cache = null;

    return function () use ($fn, &$loaded, &$cache) {
        if (!$loaded) {
            $cache = $fn();
            $loaded = true;
        }

        return $cache;
    };
}

// Použití:
// $getData = memoize(fn() => loadFromDatabase());
// $result = $getData();



/**
 * ============================================================
 * VARIANTA 4
 * OOP přístup se statickou cache a helper metodou remember()
 * ============================================================
 */

class DataProvider
{
    private static array $cache = [];

    private static function remember(string $key, callable $callback): mixed
    {
        if (!array_key_exists($key, self::$cache)) {
            self::$cache[$key] = $callback();
        }

        return self::$cache[$key];
    }

    public static function getUsers(): array|null
    {
        return self::remember('users', function () {
            return loadUsersFromDatabase();
        });
    }

    public static function getOrders(): array|null
    {
        return self::remember('orders', function () {
            return loadOrdersFromDatabase();
        });
    }
}



/**
 * ============================================================
 * Simulace drahých funkcí (jen pro testování)
 * ============================================================
 */

function loadFromDatabase(): ?array
{
    // simulace expensive operace
    sleep(1);

    return ['example' => 'data'];
}

function loadUsersFromDatabase(): ?array
{
    sleep(1);
    return ['user1', 'user2'];
}

function loadOrdersFromDatabase(): ?array
{
    sleep(1);
    return ['order1', 'order2'];
}

On gists

React TodoList with Redurec

React

App.jsx #

import { createContext, useEffect, useReducer, useState } from "react"
import { NewTodoForm } from "./NewTodoForm"
import "./styles.css"
import { TodoFilterForm } from "./TodoFilterForm"
import { TodoList } from "./TodoList"

const LOCAL_STORAGE_KEY = "TODOS"
const ACTIONS = {
  ADD: "ADD",
  UPDATE: "UPDATE",
  TOGGLE: "TOGGLE",
  DELETE: "DELETE",
}

function reducer(todos, { type, payload }) {
  switch (type) {
    case ACTIONS.ADD:
      return [
        ...todos,
        { name: payload.name, completed: false, id: crypto.randomUUID() },
      ]
    case ACTIONS.TOGGLE:
      return todos.map(todo => {
        if (todo.id === payload.id) {
          return { ...todo, completed: payload.completed }
        }

        return todo
      })
    case ACTIONS.DELETE:
      return todos.filter(todo => todo.id !== payload.id)
    case ACTIONS.UPDATE:
      return todos.map(todo => {
        if (todo.id === payload.id) {
          return { ...todo, name: payload.name }
        }

        return todo
      })
    default:
      throw new Error(`No action found for ${type}.`)
  }
}

export const TodoContext = createContext()

function App() {
  const [filterName, setFilterName] = useState("")
  const [hideCompletedFilter, setHideCompletedFilter] = useState(false)
  const [todos, dispatch] = useReducer(reducer, [], initialValue => {
    const value = localStorage.getItem(LOCAL_STORAGE_KEY)
    if (value == null) return initialValue

    return JSON.parse(value)
  })

  const filteredTodos = todos.filter(todo => {
    if (hideCompletedFilter && todo.completed) return false
    return todo.name.includes(filterName)
  })

  useEffect(() => {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todos))
  }, [todos])

  function addNewTodo(name) {
    dispatch({ type: ACTIONS.ADD, payload: { name } })
  }

  function toggleTodo(todoId, completed) {
    dispatch({ type: ACTIONS.TOGGLE, payload: { id: todoId, completed } })
  }

  function updateTodoName(id, name) {
    dispatch({ type: ACTIONS.UPDATE, payload: { id, name } })
  }

  function deleteTodo(todoId) {
    dispatch({ type: ACTIONS.DELETE, payload: { id: todoId } })
  }

  return (
    <TodoContext.Provider
      value={{
        todos: filteredTodos,
        addNewTodo,
        toggleTodo,
        updateTodoName,
        deleteTodo,
      }}
    >
      <TodoFilterForm
        name={filterName}
        setName={setFilterName}
        hideCompleted={hideCompletedFilter}
        setHideCompleted={setHideCompletedFilter}
      />
      <TodoList />
      <NewTodoForm />
    </TodoContext.Provider>
  )
}

export default App