/ Gists

Gists

On gists

Inefficient DOM Manipulations

JavaScript

demo.js #

/*
Why It’s a Problem:
Direct DOM manipulation triggers reflows and repaints, slowing down rendering.
Inserting elements one by one instead of batching updates increases the number of re-renders.
Modifying styles directly forces layout recalculations.
*/

// BAD: Multiple reflows
for (let i = 0; i < 1000; i++) {
    const div = document.createElement('div');
    div.textContent = `Item ${i}`;
    document.body.appendChild(div);
}

// GOOD: Batch updates using DocumentFragment
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
    const div = document.createElement('div');
    div.textContent = `Item ${i}`;
    fragment.appendChild(div);
}
document.body.appendChild(fragment);

On gists

CSS Colors: color opacity (tailwind)

Tailwind CSS CSS CSS trick

index.html #

<!--
https://ishadeed.com/article/css-relative-colors/#adjust-the-opacity-with-color-mix
-->

<!-- works only for color from config not defined like css variables -->

<!--v2 -->
<div class="ring-msp-red-default/30"></div>

<!--v3 -->
<div class="ring-msp-red-default ring-opacity-30"></div>

<!-- Hack if color is defined like css variable in config -->
'my-red': 'var(--primary-color)', // '#ba0c2f',

<!--v2 hack -->
does not exist

<!--v3 hack -->
ring-[color-mix(in_srgb,theme(colors.my-red)_50%,transparent)]

<!--v4 -->
no hack needed, v4 is functional (read doc)

On gists

Dynamic imports

JavaScript ES 6

examples.md #

Výhody dynamických importů v JavaScriptu

Výhody dynamických importů

  1. Code splitting (rozdělení kódu)

Místo načtení celé aplikace najednou můžeš načítat moduly až když jsou potřeba:

// Běžný statický import
import { heavyFunction } from './heavyModule.js';

// Dynamický import - načte se jen když je potřeba
button.addEventListener('click', async () => {
  const { heavyFunction } = await import('./heavyModule.js');
  heavyFunction();
});
  1. Podmíněné načítání

Můžeš načítat moduly jen za určitých podmínek:

async function loadFeature(featureName) {
  if (featureName === 'chart') {
    const { createChart } = await import('./chartModule.js');
    createChart();
  } else if (featureName === 'table') {
    const { createTable } = await import('./tableModule.js');
    createTable();
  }
}
  1. Lazy loading (líné načítání) komponent v Nuxt/Vue
// Místo tohoto statického importu
import HeavyComponent from '@/components/HeavyComponent.vue';

// Můžeš použít dynamický import
const HeavyComponent = defineAsyncComponent(() => 
  import('@/components/HeavyComponent.vue')
);
  1. Lepší výkon první načtení stránky

Zmenšíš hlavní bundle a zrychlíš tak první vykreslení:

// V Nuxt 3 můžeš dynamicky importovat i stránky
const routes = [
  {
    path: '/',
    component: () => import('./Home.vue')
  },
  {
    path: '/dashboard',
    component: () => import('./Dashboard.vue') // Načte se až při navigaci
  }
]
  1. Práce s různými formáty souborů
async function loadConfigBasedOnEnvironment() {
  if (process.env.NODE_ENV === 'development') {
    return import('./config.dev.json');
  } else {
    return import('./config.prod.json');
  }
}
  1. Lepší cachování v prohlížeči

Když změníš jeden modul, prohlížeč může znovu stáhnout jen tento modul, ne celý bundle.

  1. Vyhnutí se problémům s cyklickými závislostmi

Dynamické importy mohou někdy pomoct vyřešit cyklické závislosti:

// moduleA.js
export function funcA() {
  console.log('Function A');
}

export async function funcThatUsesB() {
  const moduleB = await import('./moduleB.js');
  moduleB.funcB();
}

// moduleB.js
import { funcA } from './moduleA.js';

export function funcB() {
  console.log('Function B calls:');
  funcA();
}

On gists

Fetch

Nuxt

server-api-product.js #

export default defineEventHandler(async (event) => {
  // Získání dat z externího API pomocí $fetch
  const products = await $fetch('https://externi-api.com/products', {
    headers: {
      'Authorization': `Bearer ${process.env.API_KEY}`
    }
  })
  
  // Transformace dat na serveru
  return products.map(product => ({
    id: product.product_id,
    title: product.product_name,
    price: `${product.price} ${product.currency}`,
    inStock: product.stock_quantity > 0
  }))
})

On gists

Delay in JS

JavaScript

sleep.js #

// 1
await new Promise(resolve => setTimeout(resolve, 1000)); // wait for 1 sec


// 2
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
   
   
   

On gists

Parser - PsiDetektiv

PHP-PHPDOM

parser.php #

<?php

libxml_use_internal_errors(true);
 
$data = file_get_contents('https://www.psidetektiv.cz/ztracena-zvirata/');

// Load HTML into DOMDocument
$dom = new DOMDocument();
$dom->loadHTML($data, LIBXML_NOERROR | LIBXML_NOWARNING);
$finder = new DomXPath($dom);

$wrapper = $finder->query("//div[@id='category-list']"); 

if ($wrapper->length > 0) {
    $catalogItems = $finder->query(".//div[contains(@class, 'catalog-item')]", $wrapper->item(0));
    

    $savedItems = [];
    foreach ($catalogItems as $index => $item) {
        // Safely get link
        $linkElement = $finder->query(".//a[contains(@href, '/zvire/')]", $item)->item(0);
        $link = $linkElement ? $linkElement->getAttribute('href') : '';
        
        // Safely get background image
        $bgImageElement = $finder->query(".//span[@class='bg-image']", $item)->item(0);
        $bgImageStyle = $bgImageElement ? $bgImageElement->getAttribute('style') : '';
        
        // Extract image URL from style
        preg_match('/background-image:url\((.*?)\)/', $bgImageStyle, $matches);
        $imageUrl = isset($matches[1]) ? $matches[1] : '';
        
        $name = trim($finder->query(".//div[contains(@class, 'name')]/span[contains(@class, 'label') and contains(text(), 'Jméno:')]/following::text()[1]", $item)->item(0)->nodeValue);
        $breed = trim($finder->query(".//div[contains(@class, 'line')]/span[contains(@class, 'label') and contains(text(), 'Plemeno:')]/following::text()[1]", $item)->item(0)->nodeValue);
        $lostLocation = trim($finder->query(".//div[contains(@class, 'line')]/span[contains(@class, 'label') and contains(text(), 'Místo ztráty:')]/following::text()[1]", $item)->item(0)->nodeValue);
        $region = trim($finder->query(".//div[contains(@class, 'line')]/span[contains(@class, 'label') and contains(text(), 'Kraj:')]/following::text()[1]", $item)->item(0)->nodeValue);
        $gender = trim($finder->query(".//div[contains(@class, 'line')]/span[contains(@class, 'label') and contains(text(), 'Pohlaví:')]/following::text()[1]", $item)->item(0)->nodeValue);
        $color = trim($finder->query(".//div[contains(@class, 'line')]/span[contains(@class, 'label') and contains(text(), 'Barva:')]/following::text()[1]", $item)->item(0)->nodeValue);
        $size = trim($finder->query(".//div[contains(@class, 'line')]/span[contains(@class, 'label') and contains(text(), 'Velikost:')]/following::text()[1]", $item)->item(0)->nodeValue);
        
        $animalData = [
            'odkaz' => $link,
            'jmeno' => $name,
            'plemeno' => $breed,
            'misto_ztraty' => $lostLocation,
            'kraj' => $region,
            'pohlavi' => $gender,
            'barva' => $color,
            'velikost' => $size,
            'obrazek' => $imageUrl
        ];
    
        $savedItems[] = $animalData;
    }
} else {
    echo "No elements found\n";
    foreach (libxml_get_errors() as $error) {
        echo "Line {$error->line}: {$error->message}\n";
    }
}


echo "<pre>";
print_r($savedItems);
echo "</pre>";




On gists

Dropdown without JS

Tailwind CSS CSS HTML

code.html #

<!-- https://codepen.io/xqbuilds/pen/LYwvOer  -->

<head>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-black text-white flex items-center justify-center min-h-screen space-x-6">
    <!-- Hover Dropdown -->
    <div class="relative group">
        <button class="bg-amber-900 hover:bg-amber-800 px-6 py-3 rounded-lg transition">
            Hover Dropdown
        </button>
        <div class="absolute left-0 hidden w-40 bg-gray-800 rounded-lg group-hover:block">
            <a href="#" class="block px-4 py-2 hover:bg-gray-700">Option 1</a>
            <a href="#" class="block px-4 py-2 hover:bg-gray-700">Option 2</a>
            <a href="#" class="block px-4 py-2 hover:bg-gray-700">Option 3</a>
            <a href="#" class="block px-4 py-2 hover:bg-gray-700">Option 4</a>
        </div>
    </div>
    <!-- Click Dropdown -->
    <div class="relative">
        <details>
            <summary class="bg-teal-800 hover:bg-teal-700 px-6 py-3 rounded-lg cursor-pointer transition">
                Click to Open
            </summary>
            <div class="absolute left-0 w-40 bg-gray-800 rounded-lg">
                <a href="#" class="block px-4 py-2 hover:bg-gray-700">Option A</a>
                <a href="#" class="block px-4 py-2 hover:bg-gray-700">Option B</a>
                <a href="#" class="block px-4 py-2 hover:bg-gray-700">Option C</a>
                <a href="#" class="block px-4 py-2 hover:bg-gray-700">Option D</a>
            </div>
        </details>
    </div>
</body>
</html>

On gists

Better Vue components with TS

JavaScript Typescript Vue.js

better-vue-with-components.vue #

<!-- 1. PROPS  -->

<!-- JS -->
<script setup>
import { defineProps } from 'vue';

const props = defineProps({
  foo: { type: String, required: true },
  bar: Number,
});

// props.foo is a string
// props.bar is a number or undefined
</script>


<!-- TS -->
<script setup lang="ts">
const props = defineProps<{
  foo: string;
  bar?: number;
}>()
</script>


<script setup lang="ts">
interface Props {
  foo: string;
  bar?: number;
}

const props = defineProps<Props>()
</script>



<!-- 2. EMITS  -->
<!-- JS -->
<script setup>
const emit = defineEmits(['change', 'update'])
</script>

 <!-- TS -->
 <script setup lang="ts">
const emit = defineEmits<{
  change: [id: number]
  update: [value: string]
}>()
</script>



<!-- 3. Typing Ref and Reactive Data => Inference -->
<script setup>
import { ref } from 'vue';

const count = ref(0); 
count.value = 'string';  // error, inference, we expect number
</script>


<!-- 4. Typing Server Responses -->
<script setup lang="ts">
import { ref, onMounted } from 'vue';

interface User {
  id: number;
  name: string;
  email: string;
}

const userData = ref<User | null>(null);

onMounted(async () => {
  const response = await fetch('https://api.example.com/user');
  const data: User = await response.json();
  userData.value = data; // TypeScript ensures data usages match the User interface
});
</script>


<!-- 5. Typing Computed Data -->
import { ref, computed } from 'vue'

const count = ref(0)
// inferred type: ComputedRef<number>
const double = computed(() => count.value * 2)
// => TS Error: Property 'split' does not exist on type 'number'
const result = double.value.split('')

// or explicitely define return type
const double = computed<number>(() => {
  // type error if this doesn't return a number
})



<!-- 6. Typing Scoped Slots-->
<template>
  <slot :msg="message"></slot>
</template>

<script setup lang="ts">
const message = 'Hello, Vue!';

const slots = defineSlots<{
  default: (props: { msg: string }) => any;
}>()
</script>


<!-- 7. Typing Template Refs -->
<script setup lang="ts">
import { useTemplateRef, onMounted } from 'vue';

const myInput = useTemplateRef('my-input');

onMounted(() => {
  myInput.value?.focus(); 
});
</script>

<template>
  <input ref="my-input" />
</template>



<!-- 8. Typing Provide/Inject -->
<!-- ParentComponent.vue -->
<script setup lang="ts">
import { provide } from 'vue';

const theme = 'dark';
provide('theme', theme);
</script>

<!-- ChildComponent.vue -->
<script setup lang="ts">
import { inject } from 'vue';

const theme = inject<string>('theme'); // Inject with expected type
// TypeScript ensures that 'theme' is of type string
</script>


<!-- 9. Generics -->
<script setup lang="ts" generic="T">
defineProps<{
  items: T[];      // Array of items of type T
  selected: T;     // Single selected item of type T
}>()
</script>


<!-- 10. Typed Composables -->
// useUser.ts
import { ref } from 'vue';

interface User {
  id: number;
  name: string;
  age: number;
}

export function useUser() {
  const user = ref<User | null>(null);

  function fetchUser(id: number) {
    // Fetching user logic
    user.value = { id, name: 'John Doe', age: 30 };
  }

  return { user, fetchUser };
}

On gists

Ben Hong - One object to rule them all

Popular ⭐ Vue.js

obj.vue #

<!-- https://www.vuemastery.com/courses/component-design-patterns/one-object-to-rule-them-all -->

<!-- To heavy , to complicated, all props we dont need ...-->
<template>
  <main>
    <Component 
      v-for="content in apiResponse"
      :key="content.id"
      :is="content.type"
      :article-title="content.title"
      :article-content="content.body"
      :ad-image="content.image"
      :ad-heading="content.heading"
      @click="content.type === 'NewsArticle' ? openArticle : openAd"
      @mouseover="content.type === 'NewsArticle' ? showPreview : trackAdEvent"
    />
  </main>
</template>


<!--Much better -->
<template>
  <main>
    <Component 
      v-for="content in apiResponse"
      :key="content.id"
      :is="content.type"
      v-bind="feedItem(content).attrs"
      v-on="feedItem(content).events"
    />
  </main>
</template>

<script>
export default {
  methods: {
    feedItem(item) {
      if (item.type === 'NewsArticle') {
        return {
          attrs: {
            'article-title': item.title,
            'article-content': item.content
          },
          events: {
            click: this.openArticle,
            mouseover: this.showPreview
          }
        }
      } else if (item.type === 'NewsAd') {
        return {
          attrs: {
            'ad-image': item.image,
            'ad-heading': item.heading
          },
          events: {
            click: this.openAd,
            mouseover: this.trackAdEvent
          }
        }
      }
    }
  }
}
</script>



<!-- The best! -->
<script>
export default {
  computed: {
    feedItems() {
      return this.apiResponse.map(item => {
        if (item.type === 'NewsArticle') {
          return {
            id: item.id,
            type: item.type,
            attrs: {
              'article-title': item.title,
              'article-content': item.content,
              class: 'feed-item feed-item--article'
            },
            events: {
              click: this.openArticle,
              mouseover: this.showPreview
            }
          }
        } else if (item.type === 'NewsAd') {
          return {
            id: item.id,
            type: item.type,
            attrs: {
              'ad-image': item.image,
              'ad-heading': item.heading,
              class: 'feed-item feed-item--ad'
            },
            events: {
              click: this.openAd,
              mouseover: this.trackAdEvent
            }
          }
        }
      })
    }
  }
}

// OR
computed: {
  feedItems() {
    return this.apiResponse.map(item => ({
      ...this.getFeedItemConfig(item),
      id: item.id
    }))
  }
},
methods: {
  getFeedItemConfig(item) {
    // Tohle se volá jen v computed, ne při každém renderu
    if (item.type === 'NewsArticle') { /* ... */ }
  }
}


</script

On gists

Css transition (with / height) 2025

CSS CSS trick

transition-native.css #

/* 
https://developer.chrome.com/docs/css-ui/animate-to-height-auto

// 1 moznost, zapnout globalne
:root {
  interpolate-size: allow-keywords;
} */

.x {
	width: 50px;
	overflow: hidden;
	background: red;
	white-space: nowrap;
	transition: 300ms;
}


/*2 nebo pres calc-size */
.x:hover {
	 width: calc-size(max-content, size);
}