let button = document.querySelector('button')
let span = document.querySelector('span')
 
let proxy = Alpine.reactive({ color: ‘blue’ })
 
Alpine.effect(() => {
    span.textContent = proxy.color
})
 
button.addEventListener('click', () => {
    proxy.color = (proxy.color == ‘blue’) ? ‘green’ : ‘blue’
}) 
                                 
                                 
                        async function getItems() {
    let response = await fetch('/api/items/all')
    let json = await response.json()
    return json
}
<div x-text="JSON.stringify(getItems())"></div>
// or alternatively:
<div
    x-data="{
        items: {},
        async getItems() {
            this.items = await (await fetch('/api/items/all')).json();
        }
    }"
    x-init="getItems">
</div>
                                 
                                 
                        // https://github.com/markmead/alpinejs-overlap/blob/main/src/index.js
export default function (Alpine) {
  Alpine.magic('overlap', (el, {}) => (targetId) => {
    const targetEl = document.querySelector(targetId)
    return checkOverlap(
      targetEl.getBoundingClientRect(),
      el.getBoundingClientRect()
    )
  })
  function checkOverlap(targetBounding, elBounding) {
    return !(
      targetBounding.top > elBounding.bottom ||
      targetBounding.right < elBounding.left ||
      targetBounding.bottom < elBounding.top ||
      targetBounding.left > elBounding.right
    )
  }
}
                                 
                                 
                        // https://github.com/markmead/alpinejs-slug
import slugify from 'slugify'
export default function (Alpine) {
  Alpine.directive('slug', (el, { expression }, { evaluateLater, effect }) => {
    let setInputValue = evaluateLater(expression)
    effect(() => {
      setInputValue((string) => {
        el.value = slugify(string, {
          lower: true,
        })
      })
    })
  })
}
                                 
                                 
                        <!-- https://codepen.io/ryangjchandler/pen/qBOEgjg -->
<div x-data="toDoList()" class="max-w-2xl mx-auto px-12 py-8 rounded-lg shadow-lg bg-gray-200">
    <div class="flex flex-col items-center justify-center mb-8">
        <h1 class="text-3xl font-bold mb-8">
            To Do List
        </h1>
        <input type="text" x-model="newTodo" placeholder="I need to..." class="mx-auto px-4 py-2 rounded shadow text-lg min-w-full" @keydown.enter="addToDo">
    </div>
    <div class="bg-white w-full rounded shadow mb-8">
        <template x-for="(todo, index) in todos" :key="index">
            <div class="flex items-center py-4" :class="{ 'border-b border-gray-400': ! isLastToDo(index) }">
                <div class="w-1/12 text-center">
                    <input type="checkbox" @change="toggleToDoCompleted(index)" :checked="todo.completed">
                </div>
                <div class="w-10/12">
                    <p x-text="todo.todo" :class="{ 'line-through': todo.completed }"></p>
                </div>
                <div class="w-1/12 text-center">
                    <button class="bg-red-600 text-white px-2 py-1 rounded hover:bg-red-700" @click="deleteToDo(index)">
                        ✗
                    </button>
                </div>
            </div>
        </template>
    </div>
    <div>
        <span x-text="numberOfToDosCompleted()"></span> / <span x-text="toDoCount()"></span> to dos completed
    </div>
</div>
<script>
  function toDoList() {
    return {
        newTodo: "",
        todos: [],
        addToDo() {
            this.todos.push({
                todo: this.newTodo,
                completed: false
            });
            this.newTodo = "";
        },
        toggleToDoCompleted(index) {
            this.todos[index].completed = !this.todos[index].completed;
        },
        deleteToDo(index) {
            this.todos = this.todos.filter((todo, todoIndex) => {
                return index !== todoIndex
            })
        },
        numberOfToDosCompleted() {
            return this.todos.filter(todo => todo.completed).length;
        },
        toDoCount() {
            return this.todos.length
        },
        isLastToDo(index) {
            return this.todos.length - 1 === index
        }
    };
}
  
</script>
                                 
                                 
                        // https://javascript.plainenglish.io/you-dont-need-removeeventlistener-to-remove-dom-event-listeners-12db93cd8bf6
// 1. once
document.querySelector('#btn').addEventListener('click', () => {
  console.log('clicked');
}, {once: true});
// 2. AbortController
const controller = new AbortController();
document.querySelector('#btn').addEventListener('click', () => {
  console.log('clicked');
}, { signal: controller.signal });
// abort the listener!
controller.abort();
// or
const controller = new AbortController();
const { signal } = controller;
document.querySelector('#btn').addEventListener('click', () => {
  console.log('clicked');
}, { signal });
document.querySelector('#btn').addEventListener('mouseenter', () => {
  console.log('mouseenter');
}, { signal })
window.addEventListener('scroll', () => {
  console.log('scroll');
}, { signal })
// Remove all listeners at once:
controller.abort();
// 3. clone element
const button = document.querySelector('#btn');
button.replaceWith(button.cloneNode(true));
                                 
                                 
                        <!--
@sources
https://play.tailwindcss.com/om6YbfPx0J
https://www.setrimsmalinou.cz/
-->
<!-- FROM LEFT TO RIGHT -->
<div class="relative h-[500px] border-2 border-black">
  <!-- image -->
  <div class="absolute inset-y-0 w-1/2 bg-red-300">
    <img src="https://picsum.photos/id/237/1500/1500" class="h-full w-full object-cover object-center" alt="" />
  </div>
  <!-- container -->
  <div class="mx-auto flex h-full max-w-6xl justify-end border-2 border-green-500">
    <div class="w-1/2">Content ...</div>
  </div>
</div>
<!-- FROM RIGHT TO LEFT -->
<div class="relative h-[500px] border-2 border-black">
  <!-- image -->
  <div class="absolute inset-y-0 right-0 w-1/2 bg-red-300">
    <img src="https://picsum.photos/id/237/1500/1500" class="h-full w-full object-cover object-center" alt="" />
  </div>
  <!-- container -->
  <div class="mx-auto flex h-full max-w-6xl justify-start border-2 border-green-500">
    <div class="w-1/2">Content ...</div>
  </div>
</div>
                                 
                                 
                          <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li id="selected">6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
  </ul>
                                 
                                 
                        <?php
// https://blog.martinhujer.cz/clever-way-to-sort-php-arrays-by-multiple-values/
// https://stackoverflow.com/questions/2699086/how-to-sort-a-multi-dimensional-array-by-value
// COMPLEX: https://stackoverflow.com/questions/17364127/how-can-i-sort-arrays-and-data-in-php
// https://stackoverflow.com/questions/44309585/properly-sorting-multidimensional-array-using-usort-and-spaceship-operator/44309755#44309755
// 1)
// order products by: price ASC, inStock DESC, isRecommended DESC, name ASC
usort($products, function (Product $a, Product $b): int {
    return
        ($a->getPrice() <=> $b->getPrice()) * 1000 + // price ASC
        ($b->isInStock() <=> $a->isInStock()) * 100 + // inStock DESC
        ($b->isRecommended() <=> $a->isRecommended()) * 10 + // isRecommended DESC
        ($a->getName() <=> $b->getName()); // name ASC
});
// 2) 
// order products by: price ASC, inStock DESC, isRecommended DESC, name ASC
usort($products, fn (Product $a, Product $b): int =>
    ($a->getPrice() <=> $b->getPrice()) * 1000 + // price ASC
    ($b->isInStock() <=> $a->isInStock()) * 100 + // inStock DESC
    ($b->isRecommended() <=> $a->isRecommended()) * 10 + // isRecommended DESC
    ($a->getName() <=> $b->getName()) // name ASC
);
// 3)
usort($products, fn (Product $a, Product $b): int =>
    [$a->getPrice(), $b->isInStock(), $b->isRecommended(), $a->getName()]
    <=>
    [$b->getPrice(), $a->isInStock(), $a->isRecommended(), $b->getName()]
);
usort($myArray, function($a, $b) {
    $retval = $a['order'] <=> $b['order'];
    if ($retval == 0) {
        $retval = $a['suborder'] <=> $b['suborder'];
        if ($retval == 0) {
            $retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
        }
    }
    return $retval;
});