const detectDeviceType = () =>
  /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
    navigator.userAgent
  )
    ?  Mobile 
    :  Desktop ;
console.log(detectDeviceType());
                                 
                                 
                        /*
https://jsbin.com/razumivece/edit?css,output
https://jsbin.com/qejuforoba/edit?css,output
*/
header {
  position: relative;
  background-color: black;
  height: 400px;
  width: 100%;
  overflow: hidden;
}
 video {
  position: absolute;
  top: 50%;
  left: 50%;
  min-width: 100%;
  min-height: 100%;
  width: auto;
  height: auto;
  z-index: 0;
  transform: translateX(-50%) translateY(-50%);
}
/* or */
video {
	position: absolute;
	height: 100%;
	width: 100%;
	object-fit: cover;
}
                                 
                                 
                        /*
https://vueschool.io/articles/vuejs-tutorials/what-is-a-vue-js-composable/
*/
/*
Clarity of Data/Methods Source
Mixins = Data Source Obscured
Composables = Transparent Source of Data and Functions
*/
//MyComponent.vue
import ProductMixin from './ProductMixin'
import BrandMixin from './BrandMixin'
import UserMixin from './UserMixin'
export default{
    mixins:[ProductMixin, BrandMixin, UserMixin],
    created(){
        // Where in the world did name come from? 
        // Let me look through each of the registered mixins to find out
        // Oh man, it's not in any of them...
        // It must be from a globally registered mixin
        console.log(this.site)
        // Oh, I got lucky here turns out the first mixin I inspected has the name
        console.log(this.name)
    }
}
//MyComponent.vue
import useProduct from './useProduct'
import useBrand from './useBrand'
import useUser from './useUser'
export default{
    setup(){
        const { name } = useProduct()
        return { name }
  }
    created(){
        // Where in the world did name come from? 
        // ah, it's not in setup anywhere... this doesn't exist and is an error
        console.log(this.site)
        // Oh, nice I can see directly in setup this came from useProduct
        console.log(this.name)
    }
}
/*
Naming Collisions
Mixins = Risk of Naming Collisions
Composables = NO risk of naming collisions
*/
//MyComponent.vue
import ProductMixin from './ProductMixin' // name = AirMax
import BrandMixin from './BrandMixin' // name = Nike
import UserMixin from './UserMixin' // name = John Doe
export default{
    mixins:[ProductMixin, BrandMixin, UserMixin],
    created(){  
        // Actually I'm not so lucky,
        // yeah I found the name in ProductMixin
        // but turns out UserMixin had a name too
        console.log(this.name) // John Doe
    }
}
//MyComponent.vue
import useProduct from './useProduct' // name = AirMax
import useBrand from './useBrand' // name = Nike
import useUser from './useUser' // name = John Doe
export default{
    setup(){
        const { name: productName } = useProduct()
        const { name: brandName } = useBrand()
        const { name: userName } = useUser()
        return { productName, brandName, userName }
  }
    created(){
        // Yay! Nothing is lost and I can get the name of each of the things
        // together in my component but when writing the composables
        // I don't have to think at all about what variable names might collide
        // with names in other composables
        console.log(this.productName)
        console.log(this.brandName)
        console.log(this.userName)
    }
}
/*
Mutating Module's Reactive Data from the Component
Mixins = Can NOT Safeguard Own Reactive Data
Composables = Can Safeguard Own Reactive Data
*/
// RequestMixin.js
 export default {
  data(){
        return {
            loading: false,
            payload: null
        }
  },
    methods:{
        async makeRequest(url){
            this.loading = true
            const res = await fetch(url)
            this.payload = await res.json()
            this.loading = false
        }
    }
}
// useRequest.js
import { readonly, ref } from "vue";
export default () => {
    // data
  const loading = ref(false);
  const payload = ref(null);
    // methods
  const makeRequest = async (url) => {
    loading.value = true;
    const res = await fetch(url);
    payload.value = await res.json();
  };
    // exposed
  return {
    payload: readonly(payload), //notice the readonly here
    loading: readonly(loading), // and here
    makeRequest
  };
};
/*
Global State with Composables
*/
//CounterMixins.js
export default{
    data(){
        return { count: 0 }
    },
    methods:{
        increment(){
            this.count ++
        }
    }
}
//useCounter.js
import {ref, readonly} from 'vue'
export default () => {
  const count = ref(0)
    const increment = ()=> count.value++
    return {
        count: readonly(count), 
        increment
    }
}
//useCounter.js
import {ref, readonly} from 'vue'
const count = ref(0)
export default () => {
    const increment = ()=> count.value++
    return {
        count: readonly(count), 
        increment
    }
}
                                 
                                 
                        function counter() {
  let count = 0;
  function increment() {
    return count += 1;
  };
  return increment;
}
const generateId = counter();
generateId(); // 1
generateId(); // 2
generateId(); // 3
// ES 6 ;)
const test = () => {
	let temp = 0;
	 return () => {
		temp++;
		console.log(temp);
	}
}
const invoke = test();
invoke();
invoke();
invoke();
                                 
                                 
                           <script>
        var audios = [];
        audios[0] = new Audio("/sounds/audio_2019-12-20_11-12-44.mp3");    
        audios[1] = new Audio("/sounds/audio_2019-12-20_11-13-32.mp3");    
        audios[2] = new Audio("/sounds/audio_2019-12-20_11-13-43.mp3");    
        audios[3] = new Audio("/sounds/makak-oda.mp3");    
        
        var sound;
        var playAudio = function(index)
        {
            for (i = 0; i < audios.length; i++)
            {
                sound = audios[i];
                sound.pause();
                sound.currentTime = 0;
            }
            audios[index].play();
        };
        
    </script>
                                 
                                 
                        <?php
	public function filterAllowedPayments(&$payments)
	{
		// pokud je v kosiku la degustacion nelze platit kartou
		if ($this->isLDBBInBasket() && isset($payments[2])) {
			// $payments->where('NOT id', 2);
			unset($payments[2]);
		}
		// pokud je v kosiku merche, neumoznime platbu kartou pri prevzeti
		if ($this->isMerchInBasket() && isset($payments[4])) {
			// $payments->where('NOT id', 4);
			unset($payments[4]);
		}
		if (!$this->isLDBBInBasket() && isset($payments[4])) {
			unset($payments[4]);
		}
	}
	public function filterAllowedTransports(&$transports)
	{
		// pokud v kosiku neni merche, nelze vyzvednout v ambi kancelari
		if (!$this->isMerchInBasket() && isset($transports[2047])) {
			// $transports->where('NOT id', 2047);
			unset($transports[2047]);
		}
	}
                                 
                                 
                        <?php
namespace Model;
use Nette;
class VatCzSkResolver
{
	private static $instance;
	public $eshopOrderFormMasoprofit;
	
	public function __construct(EshopOrderFormMasoprofit $eshopOrderFormMasoprofit)
	{
		self::$instance = $this;
		$this->eshopOrderFormMasoprofit = $eshopOrderFormMasoprofit;
	}
	public static function getDphRewrite()
	{
		if (!self::$instance) { // nejsme na frontendu
			return null;
		}
		
		if ($billingAddress = self::$instance->eshopOrderFormMasoprofit->getBillingAddress()) {
			if (isset($billingAddress['country_id']) && $billingAddress['country_id'] == 186) {
				if (isset($billingAddress['ic_vat']) && $billingAddress['ic_vat'] && isset($billingAddress['dic']) && $billingAddress['dic']) {
					return 0;
				}
				return 20;
			}
		}
		return null;
	}
}
                                 
                                 
                        const userCardTemplate = document.querySelector("[data-user-template]")
const userCardContainer = document.querySelector("[data-user-cards-container]")
const searchInput = document.querySelector("[data-search]")
let users = []
searchInput.addEventListener("input", e => {
  const value = e.target.value.toLowerCase()
  users.forEach(user => {
    const isVisible =
      user.name.toLowerCase().includes(value) ||
      user.email.toLowerCase().includes(value)
    user.element.classList.toggle("hide", !isVisible)
  })
})
fetch("https://jsonplaceholder.typicode.com/users")
  .then(res => res.json())
  .then(data => {
    users = data.map(user => {
      const card = userCardTemplate.content.cloneNode(true).children[0]
      const header = card.querySelector("[data-header]")
      const body = card.querySelector("[data-body]")
      header.textContent = user.name
      body.textContent = user.email
      userCardContainer.append(card)
      return { name: user.name, email: user.email, element: card }
    })
  })
                                 
                                 
                        // one way
const $ = document.querySelector.bind(document);
const $$ = document.querySelectorAll.bind(document);
// second way
let $ = (selector) => document.querySelector(selector);
let $$ = (selector) => document.querySelectorAll(selector);
$('div').style.color = 'blue'
$$('div').forEach(div => div.style.background = 'orange')
                                 
                                 
                        <?php
/* https://forum.nette.org/cs/35218-muze-checkboxlist-vracet-associativni-pole-misto-indexoveho#p220072 */
0 => 'po'
1 => 'st'
2 => 'ct'
po => true
ut => false
st => true
ct => true
pa => false
array_walk($arr, fn(&$item, $key, $values) => $item = in_array($key, $values), $values);