Skip to content

Instantly share code, notes, and snippets.

View mmocny's full-sized avatar

Michal Mocny mmocny

View GitHub Profile
@mmocny
mmocny / SaveEventTargets.js
Created August 30, 2023 16:27
Save Event Targets
const interestingEventTypes = [ 'pointerdown', 'pointerup', 'click', 'keydown', 'keypress', 'keyup'];
const mapOfTargets = Object.fromEntries(interestingEventTypes.map(type => [type, {}]));
interestingEventTypes.forEach(type =>
document.addEventListener(type, (event) => {
// TODO: Improve this
const nodeType = event.target.nodeName.toLowerCase();
const nodeId = event.target.id;
const nodeClasses = event.target.className.replace(/\s/g, '.');
@mmocny
mmocny / processArrayOfWork.js
Last active July 28, 2023 12:08
processArrayOfWork with PostTask
function processArrayOfWork(arr) {
const item = arr.shift();
console.log(`Processing array item: ${item}`);
if (arr.length > 0) {
// Recursive call.
processArrayOfWork(arr);
} else {
console.log('End processing array of data.');
}
@mmocny
mmocny / whyNP.js
Last active August 16, 2023 14:43
(() => {
// processLoAFEntry.js
function floorObject(o) {
return Object.fromEntries(
Array.from(Object.entries(o)).map(([key, value]) => [
key,
typeof value === "number" ? Math.floor(value) : value
])
);
}
@mmocny
mmocny / logInteractions.js
Created June 16, 2023 20:28
Log all Interaction in pretty style
const RATING_COLORS = {
good: "#0CCE6A",
"needs-improvement": "#FFA400",
poor: "#FF4E42"
};
function onInteraction(callback) {
const valueToRating = (score) =>
score <= 200 ? "good" : score <= 500 ? "needs-improvement" : "poor";
@mmocny
mmocny / inp-devtools-watch.js
Created April 14, 2023 14:12
Add these snippets to DevTools (console) Watch expressions
// max-INP:
(()=>{let o=globalThis;return void 0===o.winp&&(o.winp=0,new PerformanceObserver(n=>{for(let e of n.getEntries()){if(!e.interactionId)continue;o.winp=Math.max(e.duration,o.winp);let r=o=>o<=200?"color: green":o<=500?"color: yellow":"color: red";console.log(`%c[Interaction: ${e.name.padEnd(12)}] %cDuration: %c${e.duration}`,"color: grey; font-family: Consolas,monospace","",r(e.duration))}}).observe({type:"event",durationThreshold:0,buffered:!0})),o.winp})();
// interactionCount
performance.interactionCount;
@mmocny
mmocny / soft-navs.js
Last active January 9, 2024 15:42
Measure FCP/LCP + Soft Navs
const RATING_COLORS = {
"good": "#0CCE6A",
"needs-improvement": "#FFA400",
"poor": "#FF4E42",
"invalid": "#FFC0CB",
"default": "inherit", // Will default to this, anyway
};
function log(metric) {
const prettyScore = metric.value.toLocaleString(undefined, { maximumFractionDigits: 0 });
@mmocny
mmocny / shadowQuerySelectorAll.js
Created October 6, 2022 16:43
shadowQuerySelectorAll. Like querySelectorAll, but which works across shadowRoots
// Inspiration: https://www.abeautifulsite.net/posts/querying-through-shadow-roots/
/*
* Acts like querySelectorAll, except you can pass a list of selectors...
* Each selector is evaluated within the shadowRoot of the previous NodeList
*/
function* shadowQuerySelectorsAll(selectors, rootNode = document, depth = 0) {
const nodes = rootNode?.querySelectorAll(selectors[depth]);
if (depth >= selectors.length - 1) {
yield* nodes;
import firstOnly from './Promise.firstOnly.polyfill.js';
// Always unblocks next-render... but can leave main thread idle time while waiting for next frame.
function doubleRaf(cb) {
requestAnimationFrame(() => {
requestAnimationFrame(cb);
});
}
// Always unblocks next-render... but gets scheduled at the back of the main thread task queue
/* Usage:
await Promise.firstOnly([
(signal) => {
return new Promise((resolve, reject) => {
// ...do work and resolve();
signal.addEventListener("abort", () => {
// ...cancel and reject();
});
});
},
@mmocny
mmocny / po2it.md
Last active February 4, 2021 16:10
Performance Observer to Async Iterator

Performance Observer to Async Iterator

Background: Iterators, Performance Observer, and Async Iterators

function* range() {
   yield 1;
   yield 2;
   yield 3;
}