/ Gists

Gists

On gists

Compute & transform logic outside of UI component

Popular ⭐ Vue.js

index.md #

Vue.js Media Transformer - Všechny varianty implementace

1. Composable (Vue 3 Composition API)

// composables/useMediaObjects.js
export function useMediaObjects() {
  const transformMediaObjects = (productGallery, productVideos) => {
    const finalObjects = []

    // Photos
    if (productGallery) {
      finalObjects.push(
        ...productGallery.map((photo, index) => ({
          ...photo,
          type: 'photo',
          rank: index + 1
        }))
      )
    }

    // Videos
    if (productVideos) {
      finalObjects.push(
        ...productVideos.map((videoUrl, index) => {
          const youtubeId = extractYouTubeId(videoUrl)
          return {
            url: videoUrl,
            type: 'video',
            rank: finalObjects.length + index + 1,
            previewThumb: youtubeId 
              ? `https://img.youtube.com/vi/${youtubeId}/sddefault.jpg` 
              : null
          }
        })
      )
    }

    return finalObjects
  }

  const extractYouTubeId = (url) => {
    return url.match(
      /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
    )?.[1]
  }

  return {
    transformMediaObjects,
    extractYouTubeId
  }
}

Použití v komponentě:

// Product.vue
<script setup>
import { computed } from 'vue'
import { useMediaObjects } from '@/composables/useMediaObjects'

const props = defineProps(['productGallery', 'product'])

const { transformMediaObjects } = useMediaObjects()

const mediaObjects = computed(() => {
  return transformMediaObjects(props.productGallery, props.product?.product_video)
})
</script>

2. JS Třída - Statické metody

// services/MediaTransformer.js
export class MediaTransformer {
  static transform(productGallery, productVideos) {
    const finalObjects = []

    if (productGallery) {
      finalObjects.push(
        ...productGallery.map((photo, index) => ({
          ...photo,
          type: 'photo',
          rank: index + 1
        }))
      )
    }

    if (productVideos) {
      finalObjects.push(
        ...productVideos.map((videoUrl, index) => {
          const youtubeId = this.extractYouTubeId(videoUrl)
          return {
            url: videoUrl,
            type: 'video',
            rank: finalObjects.length + index + 1,
            previewThumb: youtubeId 
              ? `https://img.youtube.com/vi/${youtubeId}/sddefault.jpg` 
              : null
          }
        })
      )
    }

    return finalObjects
  }

  static extractYouTubeId(url) {
    return url.match(
      /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
    )?.[1]
  }

  static generateThumbnail(youtubeId, quality = 'sddefault') {
    return `https://img.youtube.com/vi/${youtubeId}/${quality}.jpg`
  }
}

Použití:

// Product.vue
<script setup>
import { computed } from 'vue'
import { MediaTransformer } from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  return MediaTransformer.transform(props.productGallery, props.product?.product_video)
})
</script>

3. JS Třída - Export třídy (instance v komponentě)

// services/MediaTransformer.js
export class MediaTransformer {
  constructor(config = {}) {
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
    this.defaultVideoType = config.defaultVideoType || 'video'
  }

  transform(productGallery, productVideos) {
    const finalObjects = []

    if (productGallery) {
      finalObjects.push(
        ...productGallery.map((photo, index) => ({
          ...photo,
          type: 'photo',
          rank: index + 1
        }))
      )
    }

    if (productVideos) {
      finalObjects.push(
        ...productVideos.map((videoUrl, index) => {
          const youtubeId = this.extractYouTubeId(videoUrl)
          return {
            url: videoUrl,
            type: this.defaultVideoType,
            rank: finalObjects.length + index + 1,
            previewThumb: youtubeId 
              ? `https://img.youtube.com/vi/${youtubeId}/${this.thumbnailQuality}.jpg` 
              : null
          }
        })
      )
    }

    return finalObjects
  }

  extractYouTubeId(url) {
    return url.match(
      /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
    )?.[1]
  }

  setConfig(newConfig) {
    Object.assign(this, newConfig)
    return this
  }
}

Použití:

// Product.vue
<script setup>
import { computed, ref } from 'vue'
import { MediaTransformer } from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaTransformer = ref(new MediaTransformer({ thumbnailQuality: 'hqdefault' }))

const mediaObjects = computed(() => {
  return mediaTransformer.value.transform(props.productGallery, props.product?.product_video)
})
</script>

4. JS Třída - Export instance (singleton)

// services/MediaTransformer.js
class MediaTransformer {
  constructor(config = {}) {
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
  }

  transform(productGallery, productVideos) {
    // stejná implementace jako výše...
  }

  extractYouTubeId(url) {
    // stejná implementace...
  }

  setConfig(newConfig) {
    Object.assign(this, newConfig)
    return this
  }
}

// Export instance
export const mediaTransformer = new MediaTransformer()

// Případně export obou
export { MediaTransformer }

Použití:

// Product.vue
<script setup>
import { computed } from 'vue'
import { mediaTransformer } from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  return mediaTransformer.transform(props.productGallery, props.product?.product_video)
})

// Změna konfigurace kdykoliv:
// mediaTransformer.setConfig({ thumbnailQuality: 'maxresdefault' })
</script>

5. Singleton Pattern

// services/MediaTransformer.js
class MediaTransformer {
  static _instance = null

  constructor(config = {}) {
    if (MediaTransformer._instance) {
      return MediaTransformer._instance
    }

    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
    MediaTransformer._instance = this
  }

  static getInstance(config = {}) {
    if (!this._instance) {
      this._instance = new MediaTransformer(config)
    }
    return this._instance
  }

  transform(productGallery, productVideos) {
    // implementace...
  }

  extractYouTubeId(url) {
    // implementace...
  }
}

export default MediaTransformer

Použití:

// Product.vue
<script setup>
import { computed } from 'vue'
import MediaTransformer from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  const transformer = MediaTransformer.getInstance({ thumbnailQuality: 'hqdefault' })
  return transformer.transform(props.productGallery, props.product?.product_video)
})
</script>

5.1 Singleton with Registry

class MediaTransformer {
  static _instances = new Map()

  constructor(config = {}) {
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
    this.config = config
  }

  static getInstance(config = {}) {
    // Vytvoř unikátní klíč z configu
    const key = JSON.stringify(config)

    if (!this._instances.has(key)) {
      this._instances.set(key, new MediaTransformer(config))
    }

    return this._instances.get(key)
  }

  transform(productGallery, productVideos) {
    // implementace...
  }
}

const hq = MediaTransformer.getInstance({ thumbnailQuality: 'hqdefault' })
const max = MediaTransformer.getInstance({ thumbnailQuality: 'maxresdefault' })
// Různé instance ✅

5.2 New class with static fn

class MediaTransformer {
  constructor(config = {}) {
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
  }

  transform(productGallery, productVideos) {
    // implementace...
  }

  static transform(productGallery, productVideos, config = {}) {
    const instance = new MediaTransformer(config)
    return instance.transform(productGallery, productVideos)
  }
}

export default MediaTransformer

// Varianta 1: Instance
const transformer = new MediaTransformer({ thumbnailQuality: 'hqdefault' })
const media = transformer.transform(gallery, videos)

// Varianta 2: Statická metoda
const media = MediaTransformer.transform(gallery, videos, { thumbnailQuality: 'hqdefault' })

6. Factory Function

// services/MediaTransformer.js
class MediaTransformer {
  constructor(config = {}) {
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
  }

  transform(productGallery, productVideos) {
    // implementace...
  }

  extractYouTubeId(url) {
    // implementace...
  }
}

export const createMediaTransformer = (config = {}) => {
  return new MediaTransformer(config)
}

// Export i třídy pro pokročilé použití
export { MediaTransformer }

Použití:

// Product.vue
<script setup>
import { computed, ref } from 'vue'
import { createMediaTransformer } from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaTransformer = ref(createMediaTransformer({ thumbnailQuality: 'maxresdefault' }))

const mediaObjects = computed(() => {
  return mediaTransformer.value.transform(props.productGallery, props.product?.product_video)
})
</script>

7. Plain Object/Service

// services/mediaService.js
export const mediaService = {
  defaultConfig: {
    thumbnailQuality: 'sddefault'
  },

  transform(productGallery, productVideos, config = {}) {
    const finalConfig = { ...this.defaultConfig, ...config }
    const finalObjects = []

    if (productGallery) {
      finalObjects.push(
        ...productGallery.map((photo, index) => ({
          ...photo,
          type: 'photo',
          rank: index + 1
        }))
      )
    }

    if (productVideos) {
      finalObjects.push(
        ...productVideos.map((videoUrl, index) => {
          const youtubeId = this.extractYouTubeId(videoUrl)
          return {
            url: videoUrl,
            type: 'video',
            rank: finalObjects.length + index + 1,
            previewThumb: youtubeId 
              ? `https://img.youtube.com/vi/${youtubeId}/${finalConfig.thumbnailQuality}.jpg` 
              : null
          }
        })
      )
    }

    return finalObjects
  },

  extractYouTubeId(url) {
    return url.match(
      /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
    )?.[1]
  }
}

Použití:

// Product.vue
<script setup>
import { computed } from 'vue'
import { mediaService } from '@/services/mediaService'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  return mediaService.transform(
    props.productGallery, 
    props.product?.product_video,
    { thumbnailQuality: 'hqdefault' }
  )
})
</script>

8. Pure Functions (Helper)

// utils/mediaTransform.js
export const transformMediaObjects = (productGallery, productVideos, config = {}) => {
  const { thumbnailQuality = 'sddefault' } = config
  const finalObjects = []

  if (productGallery) {
    finalObjects.push(
      ...productGallery.map((photo, index) => ({
        ...photo,
        type: 'photo',
        rank: index + 1
      }))
    )
  }

  if (productVideos) {
    finalObjects.push(
      ...productVideos.map((videoUrl, index) => {
        const youtubeId = extractYouTubeId(videoUrl)
        return {
          url: videoUrl,
          type: 'video',
          rank: finalObjects.length + index + 1,
          previewThumb: youtubeId 
            ? `https://img.youtube.com/vi/${youtubeId}/${thumbnailQuality}.jpg` 
            : null
        }
      })
    )
  }

  return finalObjects
}

export const extractYouTubeId = (url) => {
  return url.match(
    /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
  )?.[1]
}

Použití:

// Product.vue
<script setup>
import { computed } from 'vue'
import { transformMediaObjects } from '@/utils/mediaTransform'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  return transformMediaObjects(
    props.productGallery, 
    props.product?.product_video,
    { thumbnailQuality: 'hqdefault' }
  )
})
</script>

Srovnání variant

Varianta Výhody Nevýhody Použití
Composable Vue 3 native, reaktivita, auto-import Vue specific Vue 3 projekty
Statické metody Jednoduché, žádná konfigurace Není flexibilní Jednoduché transformace
Export třídy Flexibilní konfigurace Musíš vytvářet instance Různé konfigurace
Export instance Žádné new, sdílený stav Pevná konfigurace Jednotná konfigurace
Singleton Jedna instance, lazy loading Složitější pattern Globální konfigurace
Factory Flexibilní vytváření Extra abstrakce Komplexní objekty
Plain Object Jednoduché, framework agnostic Není OOP Malé utility
Pure Functions Nejjednodušší, testovatelné Žádná organizace Funkcionální přístup

Doporučení

  • Pro jednoduché transformace: Pure Functions nebo Statické metody
  • Pro flexibilní konfiguraci: Export třídy nebo Factory
  • Pro Vue 3 projekty: Composable
  • Pro globální použití: Export instance s setConfig

On gists

Vue parent - child

Popular ⭐ Vue.js

vue1.js #

// https://play.vuejs.org/#eNqdVE2P2jAQ/SsjXwCJBlXtic2itohDK7W72u7Rl5BMwItjW7bDUiH+e8d2krJbRNXlgOyZN1/Pb3Jkn43J9i2yOctdaYXx4NC3ZsGVaIy2Ho5gsZ5C6/ARGyMLjw9YwwlqqxsYUehogH7XVSE7RzaLt5CbAKVWzkMTLCH69lW68Si6RpMbrvJZ6oM6oIvvQHS7LywqD/nawoyut3//Bl++br3XCj6VUpS7W876ypk2qMYTzhZ3dEgN57OEvhpXSu0wBi7D6UJkqNz9b7suEh9EX5+Js+SYDWOxKfOO2KnFJntyWtE7HLkC4KzUjRES7Z3xgtjjbA7RE3yFlPr5W7R52+K0t5dbLHcX7E/uEGyc3Vt0aPfI2eDzhd2gT+7Vzx94oPPgpK5bSegrzgd0WrahxwT70qqK2j7DxW6/RokItXl0q4NH5fqhQqMBeYp4zkgwyyuj/2n3Q/YxxnF1IhYHtQUln6kGYLkVsoJxBEzeJp//VM0/xVKJPezfua1+JrRwIStJo5SFc2SI8KVWxBINukgq6u75jGJfSijuyZXdfbWr/TKmsrSKBBnXhXQ44apuVRk4hzRxoj0hs30hWyR8eDAg0s/Q3cAX4TF1wnNVYS0Urg4m4I+xyjRFw4nKv9x953/J9ITZOSW9FkxRVaSnOby32NzAuih3G6tJfXMwsm3oUxJQDelFqA7U6YXKxNTs9BvEAbCg

// Parent
<script setup>
import { ref, useTemplateRef } from 'vue'
import Modal from './Modal.vue'
const modalRef = useTemplateRef('modal');
</script>

<template>
Parent <br />
=================== <br />
<button @click="modalRef.open()">Open Modal</button>
<button @click="modalRef.close()">Close Modal</button>
<br /><br /><hr />
<Modal ref="modal" />
</template>

// Child - Modal
<template>
  Child (Modal) <br />
=================== <br />
<button @click="open()">Open Modal</button>
<button @click="close()">Close Modal</button>
<div v-show="isOpen" class="ModalContent">Modal Content</div>
</template>

<script setup>
import { ref } from 'vue'

const isOpen = ref(false)
function open() {
  isOpen.value = true 
}
function close() {
  isOpen.value = false 
}

defineExpose({ open, close })
</script>

<style>
  .ModalContent {
    padding: 1rem; background: plum;
    margin: 1rem;
  }
</style>

On gists

Css Toggle (if-else)

CSS CSS trick

demo.css #

/*
https://css-tricks.com/the-css-custom-property-toggle-trick/
*/


html {
  --mq-sm: initial;
}

@media (max-width: 600px) {
  html {
    --mq-sm: ;
  }
}

.card {
  --bg1: var(--mq-sm) green; /* first can be invalid ;) */
  --bg2: red;

  background: var(--bg1, var(--bg2));
}

On gists

Vue computed with private variable via IIFE

Popular ⭐ JS Patterns Vue.js

any-component.js #

const showThumbs = (() => {
  // really private ;-)
  const state = ref(props.enableThumbs)

  return computed({
    get: () => state.value,
    set: value => {
      state.value = value
    }
  })
  
})()

/*

-----------------------------------
Nejčastější použití je právě pro:
  - Vytvoření privátního scope
  - Enkapsulaci dat a logiky
  - Vyhnutí se globálnímu scope
  - Zachování stavu přes closure
 -----------------------------------
 * 1. Vytvoření privátního scope
 * - proměnné uvnitř neuniknou ven
 * - čisté API pro vnější svět
 */
const counter = (() => {
  let count = 0  // privátní proměnná
  return {
    increment() { count++ },
    getCount() { return count }
  }
})()

/**
 * 2. Vyhnutí se globálnímu scope
 * - dočasné proměnné zůstanou lokální
 * - neznečišťuje globální namespace
 */
(() => {
  const temp = 'nějaká dočasná proměnná'
  // temp existuje jen uvnitř, neznečišťuje globální scope
})()

/**
 * 3. Modulární pattern
 * - privátní metody a proměnné
 * - veřejné API
 */
const module = (() => {
  const privateVar = 'private'
  const privateMethod = () => { 
    console.log(privateVar) 
  }
  
  return {
    publicMethod() {
      privateMethod()  // má přístup k privátním věcem
    }
  }
})()

/**
 * 4. Closure pro zachování stavu
 * - privátní stav
 * - reaktivní hodnota
 */
const showThumbs = (() => {
  const state = ref(props.enableThumbs)  // privátní stav
  return computed({
    get: () => state.value,
    set: (value) => {
      state.value = value
    }
  })
})()

/**
 * 5. Vyhnutí se konfliktům
 * - lokální aliasy
 * - izolace kódu
 */
(() => {
  const $ = jQuery  // lokální alias pro jQuery
  // používání $ uvnitř neovlivní jiné knihovny používající $
})()

/**
 * 6. Inicializace
 * - nastavení při načtení
 * - konfigurace
 * - event listenery
 */
(() => {
  // nějaká inicializace
  const config = { 
    apiKey: 'xxx',
    endpoint: 'https://api.example.com'
  }
  
  // nastavení event listenerů
  document.addEventListener('DOMContentLoaded', () => {
    // inicializace UI
  })
  
  // další setup
  const init = () => {
    // ...
  }
  
  init()
})()

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

object.js

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

Advanced tailwind tricks by shadcn

Tailwind CSS Vue.js

examples.js #

// https://www.reddit.com/r/tailwindcss/comments/1icfwbo/here_are_10_tailwind_tricks_shared_by_shadcn_they/
// https://x.com/shadcn/status/1842329158879420864


// 1. Dynamic CSS Variables in Tailwind
<div style={{ "--width": isCollapsed ? "8rem" : "14rem" }} className="w-[--width] transition-all" />

// 2. Data Attribute State Management
<div 
  data-state={isOpen ? "open" : "closed"}
  className="data-[state=open]:bg-blue-500"
/>


// 3. Nested SVG Controll
<div 
  data-collapsed={isCollapsed}
  className="[&[data-collapsed=true]_svg]:rotate-180"
>
  <svg>...</svg>
</div>


// 4. Parent-Child Style Inheritance
<section :data-collapsed="isCollapsed"
  <div className="[[data-collapsed=true]_&]:rotate-180">
    {/* Child inherits rotation when parent has data-collapsed=true */}
  </div>
</section>


// 5. Group Data States
<div className="group" data-collapsed={isCollapsed}>
  <div className="group-data-[collapsed=true]:rotate-180"/>
</div>


// 6. Data Slots
<div className="data-[slot=action]:*:hover:mr-0">
  <div data-slot="action" class="-mr-10">...</div>
</div>


// 7. Peer Element Control
<button className="peer" :data-active="isActive">Menu</button>
<div className="peer-data-[active=true]:bg-blue-500"/>


// 8. Named Group Focus
<div className="group/menu">
  <button className="group-focus-within/menu:bg-blue-500"/>
</div>


// 9. Group Has Selectors
<div className="group/menu">
  <div className="group-has-[[data-active=true]]/menu:bg-blue-500"/>
</div>


// 10. Variant Props
<button 
  data-variant={variant}
  className="data-[variant=ghost]:border-blue-500"
/>

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

Reactive like unwrap on first level

Vue.js

explanation.js #

// 1 Když neobalíš objekt do reactive():

const filtersStorage = {
  priceValue: computed({
    get: () => selectedFilters.value.priceValue,
    set: v => selectedFilters.value.priceValue = +v
  })
}

// Pak filtersStorage.priceValue je přímo ComputedRef objekt. A ComputedRef se chová jako ref - musíš použít .value pro přístup k hodnotě:

// Bez reactive() wrapper
filtersStorage.priceValue.value // ✅ musíš použít .value


// 2
// Když obalíš objekt do reactive():
const filtersStorage = reactive({
  priceValue: computed(...)
})

// S reactive() wrapper
filtersStorage.priceValue // ✅ .value se přidá automaticky


/*
Proč se to děje?

reactive() má speciální chování - automaticky unwrapuje refs na prvním levelu objektu
Tohle je záměrné chování pro lepší DX (developer experience)
Bez reactive() wrapper pracuješ přímo s ComputedRef objektem

*/