Object.keys(window).forEach(key => {
if (/^on/.test(key)) {
window.addEventListener(key.slice(2), event => {
console.log(event);
});
}
});
Vývoj software je často o hledání správné rovnováhy mezi:
čistotou kódu vs. praktičností
přehledností vs. flexibilitou
striktními pravidly vs. pragmatickým přístupem
A jak jste správně poznamenal - je to neustálý proces učení a přizpůsobování. Co fungovalo včera, nemusí být nejlepší řešení zítra. A to je v pořádku!
Důležité je:
Dělat informovaná rozhodnutí
Nebát se změny, když je potřeba
Učit se z předchozích zkušeností
Zachovat si zdravý rozum a neupnout se na jeden přístup
Proto je tak důležité mít v týmu otevřenou diskusi o těchto věcech - přesně jako teď! 👍
<!--
https://codepen.io/kevinpowell/pen/OJaBNQE
-->
<div class="grid">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item offset"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>
<style>
.grid {
margin: 2rem auto;
max-width: 900px;
display: grid;
gap: 1rem;
grid-template-columns: repeat(8, 1fr);
}
.grid-item {
padding: 2rem;
background: lightblue;
border: 4px solid royalblue;
grid-column: span 2;
}
.offset {
grid-column: 2 / span 2;
}
</style>
/*
https://javascript.plainenglish.io/3-powerful-ways-to-share-data-across-browser-tabs-in-javascript-a6a98dffa1a3
*/
// 1. local storage
// Sender
localStorage.setItem('sharedData', JSON.stringify({
message: 'Hello from Tab1!',
timestamp: Date.now()
}));
// Receiver
window.addEventListener('storage', (e) => {
if(e.key === 'sharedData') {
const data = JSON.parse(e.newValue);
console.log('Received data:', data);
}
});
// 2. BroadcastChannel API
// Create a channel (use the same channel name across all tabs)
const channel = new BroadcastChannel('app-channel');
// Send a message
channel.postMessage({
type: 'USER_UPDATE',
payload: { name: 'John' }
});
// Receive messages
channel.onmessage = (e) => {
console.log('Received broadcast:', e.data);
};
// Close the connection
window.onunload = () => channel.close();
// 3.SharedWorker Shared Thread
// shared-worker.js
let ports = [];
onconnect = (e) => {
const port = e.ports[0];
ports.push(port);
port.onmessage = (e) => {
// Broadcast to all connected pages
ports.forEach(p => {
if(p !== port) p.postMessage(e.data);
});
};
};
// Page code
const worker = new SharedWorker('shared-worker.js');
worker.port.start();
// Send a message
worker.port.postMessage('Message from Tab A');
// Receive messages
worker.port.onmessage = (e) => {
console.log('Shared thread message:', e.data);
};
// https://devsmitra.medium.com/javascript-error-handling-just-got-a-whole-lot-easier-meet-the-safe-assignment-operator-c372d892d4ed
// without
async function getData() {
try {
const response = await fetch("https://api.example.com/data");
const json = await response.json();
return validationSchema.parse(json);
} catch (error) {
handleError(error);
}
}
// with
async function getData() {
const [fetchError, response]?= await fetch("https://api.example.com/data");
if (fetchError) return handleFetchError(fetchError);
const [jsonError, json]?= await response.json();
if (jsonError) return handleJsonError(jsonError);
const [validationError, data]?= validationSchema.parse(json);
if (validationError) return handleValidationError(validationError);
return data;
}
// my version - inspired by https://michaelnthiessen.com/stealing-prop-types/
// iconDefault.js
export const iconDefaults = {
size: 'medium',
shape: 'circle',
icon: 'default',
animation: 'none'
};
<!-- Icon.vue -->
<script setup>
import { iconDefaults } from './iconDefaults.js';
const props = defineProps({
size: { type: String, default: iconDefaults.size },
shape: { type: String, default: iconDefaults.shape },
icon: { type: String, default: iconDefaults.icon },
animation: { type: String, default: iconDefaults.animation }
});
</script>
<!-- Panel.vue -->
<script setup>
import Icon from './Icon.vue';
import { iconDefaults } from './iconDefaults.js';
import { computed } from 'vue';
const props = defineProps({
heading: String,
withIcons: Boolean,
iconConfig: {
type: Object,
default: () => ({ ...iconDefaults })
}
});
const finalIconConfig = computed(() => {
return { ...iconDefaults, ...props.iconConfig };
});
</script>
/* https://codepen.io/555/pen/pdwvBP */
/*
https://s3-us-west-2.amazonaws.com/s.cdpn.io/8399/grunge.png
*/
stamp {
transform: rotate(12deg);
color: #555;
font-size: 3rem;
font-weight: 700;
border: 0.25rem solid #555;
display: inline-block;
padding: 0.25rem 1rem;
text-transform: uppercase;
border-radius: 1rem;
font-family: 'Courier';
-webkit-mask-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/8399/grunge.png');
-webkit-mask-size: 944px 604px;
mix-blend-mode: multiply;
}
.is-nope {
color: #D23;
border: 0.5rem double #D23;
transform: rotate(3deg);
-webkit-mask-position: 2rem 3rem;
font-size: 2rem;
}
.is-approved {
color: #0A9928;
border: 0.5rem solid #0A9928;
-webkit-mask-position: 13rem 6rem;
transform: rotate(-14deg);
border-radius: 0;
}
.is-draft {
color: #C4C4C4;
border: 1rem double #C4C4C4;
transform: rotate(-5deg);
font-size: 6rem;
font-family: "Open sans", Helvetica, Arial, sans-serif;
border-radius: 0;
padding: 0.5rem;
}
// https://medium.com/@arnoldgunter/how-relative-colors-in-css-just-solved-one-of-the-hardest-styling-problems-24b9f5ad7b8emys
:root {
--btn-blue: hsl(220, 100%, 50%);
--btn-green: hsl(140, 70%, 45%);
--btn-red: hsl(0, 80%, 55%);
--btn-yellow: hsl(45, 100%, 50%);
}
/* Base styles for all buttons */
.button {
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
}
/* Individual button base colors */
.button.blue { --button-color: var(--btn-blue); }
.button.green { --button-color: var(--btn-green); }
.button.red { --button-color: var(--btn-red); }
.button.yellow { --button-color: var(--btn-yellow); }
.button.blue,
.button.green,
.button.red,
.button.yellow {
background-color: var(--button-color);
}
/* Single hover rule using relative color */
.button:hover {
background-color: hsl(from var(--button-color) h s calc(l + 10%));
}