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;
});