Potrzebowałem kalendarz który pozwoli badzo szybko przewijać miesiące bez podgrzewania procesora. Przetestowałem popularne biblioteki Moment oraz Luxon, efekty były słabe, więc napisałem wszystko sam w języku TypeScript.
Zmiana kolorów poprzez zmienne CSS sterowane przez JS.
function setTheme(t: colorDef): void {
Object.keys(t).map(key => document.documentElement.style.setProperty(key, t[key]))
}
@mixin backgroundColor($color-name) {
background-color: map-get($colors, $color-name);
background-color: var(map-get($csscolors, $color-name));
}
Szybka reakcja na telefonie, bo efekt po zdarzeniu 'touchstart', a nie po 'click'
gist.github.com/jbarnat/debounce.ts
Możliwość wyboru dni poprzez zaznaczenie obszaru myszką.
Drobna optymalizacja: w pierwszym kroku wybieram miesiące które przecinają się z zaznaczonym obszarem, następnie sprawdzam wszystkie dni z wybranych miesięcy.
const m: HTMLElement[][] = Array.from(document.querySelectorAll('.monthSmall'))
.filter(el => intersect(el.getBoundingClientRect(), markRect))
.map(el => Array.from(el.querySelectorAll('.day')))
const days: HTMLElement[] = R.flatten(m).filter(el => overlap(markRect, el.getBoundingClientRect()))
barnat.net/portfolio/filter/admin.html
Baza zawiera 20 tysięcy publikacji charakteryzowanych przez rok wydania, język, kraj, konferencję, wydawcę itp.
Niebieskie liczby widoczne przy każdej kategorii oznaczają liczbę publikacji które należą do danej kategorii.
Kliknięcie w kategorię powoduje nałożenie filtra na zbiór publikacji; następnie wyświetlenie pasujacych publikacji oraz aktualizację liczebności wszystkich kategorii.
Zastosowanie podobne do tabeli przestawnych w arkuszach kalkulacyjnych.
Przeliczanie odbywa się po stronie przeglądarki, zajmuje około 50ms, a cała strona zajmuje jedynie 3.8 MB pamięci RAM (Google Chrome)
// przygotowanie danych
const response = await fetch(dataUrl)
const buffer = await response.arrayBuffer()
Object.defineProperty(list[x], 'data', {
value: new DataView(buffer, x * bytesPerVar, bytesPerVar)
})
// aktualizacja filtra
for (let offset = 0; offset < bytesPerVar; offset++) {
let bitmask = list
.filter(f => f.on)
.map(f => f.data.getUint8(offset))
.reduce((sum, c) => sum & c, -1)
if (bitmask > 0) {
for (let x = 7; x > -1; x--) {
if (bitmask >> x & 1) {
currentDocuments.add((offset * 8) + (7 - x))
}
}
list.forEach(f => {
let data = f.data.getUint8(offset)
let share = data & bitmask
if (share != 0) {
for (let y = 7; y > -1; y--) {
if (share >> y & 1) {
f.currentPower++
}
}
}
})
}
}
js, babylon.js