/ Gists

Gists

On gists

example.js

example.js #

_

On gists

Promise / Promise.withResolvers

JavaScript

example.js #

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

setTimeout(() => resolve('Done!'), 1000);
promise.then(console.log); // 'Done!'



function foo()
{
  const {promise, resolve, reject} = Promise.withResolvers()

  setTimeout(() => {
    resolve('DONE')
  }, 2000)
  
  
  return promise
}


function foo2()
{
  const {promise, resolve, reject} = withResolvers()

  setTimeout(() => {
    resolve('DONE 2')
  }, 2500)
  
  
  return promise
}

// polyfill
function withResolvers() {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  return { promise, resolve, reject };
}

// Použití:
const { promise: aliasOnlyForTesting, resolve } = withResolvers();



(async() => {
  const data = await foo()
  console.log(data)
  
  const data2 = await foo2()
  console.log(data2)
})()

On gists

Awaited computed from composable - special pattern by me

Vue.js

useAnyComposable.js #

// 1 - composable
import { ref, computed, watchEffect } from 'vue';
import useSomeOtherComposable from './useSomeOtherComposable';

export default function useMyComposable() {
  const { asyncValue1, asyncValue2 } = useSomeOtherComposable();

  const resolved = ref(false);

  // Hodnoty, které vrátíme, až budou splněny podmínky
  const computedValue1 = ref(null);
  const computedValue2 = ref(null);

  // Proměnná promise, která se splní, když budou data připravena
  const dataReady = new Promise((resolve) => {
    watchEffect(() => {
      if (asyncValue1.value === 'desiredValue1' && asyncValue2.value === 'desiredValue2') {
        computedValue1.value = asyncValue1.value;
        computedValue2.value = asyncValue2.value;
        resolved.value = true;
        resolve();
      }
    });
  });


 /*
  // i watchEffect lze zastavit
  
      const dataReady = new Promise((resolve) => {
      const stopEffect = watchEffect(() => {
        if (asyncValue1.value === 'desiredValue1' && asyncValue2.value === 'desiredValue2') {
          computedValue1.value = asyncValue1.value;
          computedValue2.value = asyncValue2.value;
          resolve(); // Vyřeší Promise, když jsou hodnoty požadované
          stopEffect(); // Zastaví watchEffect, protože už není potřeba
        }
      });
    });
 
 */



  // Vrátíme computed hodnoty i promise
  return {
    computedValue1,
    computedValue2,
    dataReady,
    resolved
  };
}

// usage - component
import { defineComponent, onMounted } from 'vue';
import useMyComposable from './useMyComposable'; // another composable which returns computed

export default defineComponent({
  setup() {
    const { computedValue1, computedValue2, dataReady } = useMyComposable();

    onMounted(async () => {
      await dataReady; // Počkáme, až budou hodnoty připravené
      console.log('Values are ready:', computedValue1.value, computedValue2.value);
    });

    return {
      computedValue1,
      computedValue2
    };
  }
});


// 2 - watch insteadof watchEffect
import { ref, watch } from 'vue';
import useSomeOtherComposable from './useSomeOtherComposable';

export default function useMyComposable() {
  const { asyncValue1, asyncValue2 } = useSomeOtherComposable();

  const computedValue1 = ref(null);
  const computedValue2 = ref(null);

  const dataReady = new Promise((resolve) => {
    const stopWatching = watch(
      [asyncValue1, asyncValue2],
      ([newVal1, newVal2]) => {
        if (newVal1 === 'desiredValue1' && newVal2 === 'desiredValue2') {
          computedValue1.value = newVal1;
          computedValue2.value = newVal2;
          resolve(); // Vyřeší Promise, jakmile hodnoty odpovídají požadavkům
          stopWatching(); // Zastaví sledování, protože už není potřeba
        }
      },
      { immediate: true } // Sleduj hned od začátku
    );
  });

  return {
    computedValue1,
    computedValue2,
    dataReady
  };
}


// component usage
import { defineComponent, onMounted } from 'vue';
import useMyComposable from './useMyComposable';

export default defineComponent({
  setup() {
    const { computedValue1, computedValue2, dataReady } = useMyComposable();

    onMounted(async () => {
      await dataReady; // Počkáme, až budou hodnoty připravené
      console.log('Values are ready:', computedValue1.value, computedValue2.value);
    });

    return {
      computedValue1,
      computedValue2
    };
  }
});


// ---------------------------------------------------
// geolocation checker aka MSP 
// ---------------------------------------------------
import { ref, computed } from 'vue';
import { useMyComposable } from './path/to/composable';

export default {
  setup() {
    // Definuj proměnné na úrovni komponenty
    const computedValue1 = ref(null);
    const computedValue2 = ref(null);
    const dataReady = ref(false);

    const check = () => {
      const { computedValue1: cv1, computedValue2: cv2, dataReady: dr } = useMyComposable();
      
      // Přiřaď hodnoty z composable do definovaných proměnných
      computedValue1.value = cv1.value;
      computedValue2.value = cv2.value;
      dataReady.value = dr.value;
    };

    // Spusť funkci nebo ji použij, když potřebuješ načíst data
    check();

    // Můžeš nyní přistupovat k computedValue1 a computedValue2 přímo mimo `check`
    console.log(computedValue1.value, computedValue2.value);

    return {
      computedValue1,
      computedValue2,
      dataReady,
      check,
    };
  },
};

On gists

Multiple params in fn - Solution

PHP DOC PHP Patterns

index.php #

<?php

// 1 config object
class FooConfig {
    public int $param1 = 0;
    public int $param2 = 0;
    public string $param3 = '';
    public string $param4 = '';
    public bool $param5 = false;
    public ?int $param6 = null;
    public int $param7 = 0;
    public string $param8 = '';
}

function Foo(FooConfig $config): void {
    // Použití: $config->param1, $config->param2, atd.
}

// Použití
$config = new FooConfig();
$config->param1 = 1;
$config->param2 = 5;
$config->param3 = "aaa";
$config->param4 = "bbb";
$config->param5 = false;
$config->param6 = null;
$config->param7 = 22;
$config->param8 = "ok";



// 2 array
/**
 * @param array{
 *   param1: int,
 *   param2: int,
 *   param3: string,
 *   param4: string,
 *   param5: bool,
 *   param6: mixed,
 *   param7: int,
 *   param8: string
 * } $params
 */
function Foo(array $params): void {
    // Použití: $params['param1'], $params['param2'], atd.
}

// Použití
Foo([
    'param1' => 1,
    'param2' => 5,
    'param3' => "aaa",
    'param4' => "bbb",
    'param5' => false,
    'param6' => null,
    'param7' => 22,
    'param8' => "ok"
]);



// 3 builder
class FooBuilder {
    private array $params = [];

    public function setParam1(int $value): self {
        $this->params['param1'] = $value;
        return $this;
    }

    public function setParam2(int $value): self {
        $this->params['param2'] = $value;
        return $this;
    }

    // Další metody pro nastavení parametrů...

    public function build(): Foo {
        return new Foo($this->params);
    }
}

class Foo {
    public function __construct(array $params) {
        // Inicializace s parametry
    }
}

// Použití
$foo = (new FooBuilder())
    ->setParam1(1)
    ->setParam2(5)
    ->setParam3("aaa")
    ->setParam4("bbb")
    ->setParam5(false)
    ->setParam6(null)
    ->setParam7(22)
    ->setParam8("ok")
    ->build();
    
    
    
  // 4 named   PHP 8+
  function Foo(
    int $param1 = 0,
    int $param2 = 0,
    string $param3 = '',
    string $param4 = '',
    bool $param5 = false,
    $param6 = null,
    int $param7 = 0,
    string $param8 = ''
) {
    // Funkční logika
}

// Použití
Foo(
    param1: 1,
    param2: 5,
    param3: "aaa",
    param4: "bbb",
    param5: false,
    param6: null,
    param7: 22,
    param8: "ok"
);



// Fluent
class FooParams {
    private int $param1 = 0;
    private int $param2 = 0;
    private string $param3 = '';
    private string $param4 = '';
    private bool $param5 = false;
    private $param6 = null;
    private int $param7 = 0;
    private string $param8 = '';

    public function param1(int $value): self {
        $this->param1 = $value;
        return $this;
    }

    public function param2(int $value): self {
        $this->param2 = $value;
        return $this;
    }

    // Další metody pro ostatní parametry...

    public function getParams(): array {
        return [
            'param1' => $this->param1,
            'param2' => $this->param2,
            // ...
        ];
    }
}

function Foo(array $params) {
    // Funkční logika
}

// Použití
$params = (new FooParams())
    ->param1(1)
    ->param2(5)
    ->param3("aaa")
    ->param4("bbb")
    ->param5(false)
    ->param6(null)
    ->param7(22)
    ->param8("ok");

Foo($params->getParams());

On gists

Fake slider :) (rather for mobile )

CSS

index.html #

<style>
grid {
  border: 2px solid maroon;
  width: 100%;
  display: flex;
  overflow: auto visible;
  scrollbar-width: none;
  
}

grid-item {
  
  width: min(80vw, 500px);
  flex: 0 0 auto;
  outline: 1px solid lime;
  padding-block: 2rem;
}
</style>


<grid>
    <grid-item>1</grid-item>
    <grid-item>2</grid-item>
    <grid-item>3</grid-item>
    <grid-item>4</grid-item>
    <grid-item>5</grid-item>
    <grid-item>6</grid-item>
    <grid-item>7</grid-item>
    <grid-item>8</grid-item>
    <grid-item>9</grid-item>
    <grid-item>10</grid-item>
</grid>
    
    


On gists

Lazy loading with IntersectionObserver

JavaScript

image-lazy-loading.js #

document.addEventListener('DOMContentLoaded', () => {
    let lazyImages = document.querySelectorAll('.lazyload');
    let observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                let img = entry.target;
                img.src = img.dataset.src;
                observer.unobserve(img);
            }
        });
    });
    lazyImages.forEach(img => {
        observer.observe(img);
    });
});

On gists

All datatypes in JS for testing

JavaScript

datatypes.js #

// Copied from https://javascript.plainenglish.io/structuredclone-the-easiest-way-to-deep-clone-objects-in-javascript-c503b536266b

const testData = {
  number: 123,
  string: "test",
  undefined: undefined,
  null: null,
  boolean: true,
  object: { a: 1, b: { c: 2 } },
  array: [1, 2, { d: 3 }],
  function: function() { return "hello"; },
  map: new Map([["key1", "value1"], ["key2", "value2"]]),
  set: new Set([1, 2, 3]),
  date: new Date(),
  error: new Error("An error occurred"),
  regex: /test/i,
  domNode: document.createElement("div")
}

On gists

AW: Vue in Latte

AW

file.latte #

<aw-alert v-for="flash in {$control->getVueDataVar('flashes')}" :type="flash.type">{_}Je to správně? Zkuste číslo opsat ještě jednou.{/_}</aw-alert>

<template v-for="image in $presenter.voucher.photos" :key="image.id">
  <aw-img src="/assets/temp/enjoyment-1.jpg" class="rounded-ambi" :image="image" size="1230x870x8" />
</template>


<div class="Filters justify-center">
	<ambi-filter-tag 
		v-for="(filter, index) in $controls['filterTagsList'].filters"
		:key="index"
		:filter="filter"
		filter-url
		class="FilterTag -Xs mb-2 lg:mb-4 mr-2 lg:mr-4"
	/>
</div>

On gists

Google Chrome DevTools

Devtools

inspect-xpath.js #

function inspectXPath(xpath) {
    const element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    if (element) {
        inspect(element);
    } else {
        console.log("Element not found");
    }
}

inspectXPath('/html/body/div[2]/div[4]/div[1]/div/div[2]/div/div/div[1]/article[3]/div[1]')