PageSourceSearch

https://calendariociclismo.app/js/components/race-card.js?v=5a5fd8c0e4d4

js calendariociclismo.app collected 2026-10-01 14:05:47 UTC 3,547 bytes, 72 lines download raw bytes

1// ─────────────────────────────────────────────────────────────────
2//  Tarjeta de carrera — Hoy, Competición y Ciclocross
3// ─────────────────────────────────────────────────────────────────
4// Una sola estructura: logo | .race-card__main (nombre, subtítulo, badges) |
5// .race-card__meta, con el miniperfil en .race-card__profile como banda
6// inferior. Cada página decide el contenido de cada zona; las piezas de
7// jornada de carretera (cifras, horario, perfil, resultados, activación)
8// están en stage-card.js.
9
10function hexLuminance(hex) {
11  if (!hex || !/^#[0-9a-fA-F]{3,6}$/.test(hex)) return null;
12  const h = hex.replace('#', '');
13  const full = h.length === 3 ? h.split('').map(c => c + c).join('') : h;
14  const [r, g, b] = [0, 2, 4].map(i => parseInt(full.slice(i, i + 2), 16));
15  return { r, g, b, lum: 0.299 * r + 0.587 * g + 0.114 * b };
16}
17
18// Color visible como raya/borde en ambos temas: los muy claros se oscurecen.
19function safeCardColor(hex) {
20  const c = hexLuminance(hex);
21  if (!c) return '#888';
22  if (c.lum <= 210) return hex;
23  const darken = v => Math.round(v * 0.6).toString(16).padStart(2, '0');
24  return '#' + darken(c.r) + darken(c.g) + darken(c.b);
25}
26
27// Contenedor de la tarjeta con el color de la carrera y el borde mínimo de
28// los colores claros o inválidos.
29export function createRaceCard(colorHex, extraClass = '', tag = 'div') {
30  const card = document.createElement(tag);
31  const c = hexLuminance(colorHex);
32  card.className = ['race-card', extraClass, !c || c.lum > 210 ? 'race-card--light-color' : ''].filter(Boolean).join(' ');
33  card.style.setProperty('--card-color', safeCardColor(colorHex));
34  return card;
35}
36
37export function cardLogoHtml(logoUrl, flag, hideFlag) {
38  if (logoUrl) {
39    return `<div class="race-card__logo">
40         <img class="race-logo-img" src="${logoUrl}" alt="" loading="lazy" onerror="this.style.display='none'">
41         ${hideFlag ? '' : `<span>${flag}</span>`}
42       </div>`;
43  }
44  return hideFlag ? '' : `<div class="race-card__flag">${flag}</div>`;
45}
46
47// Acceso a la competición o al torneo junto al nombre.
48export function overviewButtonHtml(href, label) {
49  return `<a class="race-card__overview-btn" href="${href}" aria-label="${label}" onclick="event.stopPropagation()"><span aria-hidden="true">☰</span></a>`;
50}
51
52// Zonas de la tarjeta. Todo es HTML: el llamador escapa lo que proceda.
53// `meta` va en .race-card__meta-top; `metaBlock` sustituye la columna entera
54// (categorías de ciclocross).
55export function raceCardHtml({ logo = '', name, sub = '', badges = '', meta = '', metaBlock = null }) {
56  return `${logo}<div class="race-card__main">`
57    + `<div class="race-card__name">${name}</div>`
58    + (sub ? `<div class="race-card__sub">${sub}</div>` : '')
59    + `<div class="race-card__badges">${badges}</div>`
60    + `</div>${metaBlock ?? `<div class="race-card__meta"><div class="race-card__meta-top">${meta}</div></div>`}`;
61}
62
63// Tarjeta sin página ni modal: tooltip al pasar el ratón y aviso al pulsar en
64// móvil (initPhTooltip de shared.js).
65export function setInfoTooltip(card, { message, name, flag, sub }) {
66  card.style.cursor = 'default';
67  card.dataset.phTooltip = message;
68  card.dataset.phName = name;
69  card.dataset.phFlag = flag;
70  if (sub) card.dataset.phSub = sub;
71}
72

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.