Kto jest kim w IMGW-PIB LMM
Przewodnik po stronie
Prognozy wideo
Pogoda kosmiczna
Portal letni
Aerologia (mapy górne)
Prognozy wiązkowe
Prognoza synoptyczna (2 dni)
Prognoza synoptyczna (6 dni)
Pogoda bieżąca
Ultra-Krótkoterminowe
Krótkoterminowe
Średnioterminowe
ECMWF AIFS (10 dni)
ECMWF HRES PL (10 dni)
ECMWF HRES EU (10 dni)
GFS (Opad, 10 dni)
GFS (Temp., 10 dni)
Długoterminowe
ECMWF (5 tyg.)
4 miesięczne
CFS
Specjalne
Zagrożenia pożarowe (2 dni)
Trajektorie
Zanieczyszczenie powietrza (4 dni)
Pogoda na Marsie
Atlas wiatrowy AMEW-PL
Atlas solarny AES-PL
Modelowanie pożarowe
Zjawiska ekstremalne (EFI, SOT)
Zjawiska ekstremalne (Raporty)
Meteogramy ALARO
Serwis OZE
Monitoring warunków opadowych
Konferencja zdrowie
Pogoda dla granic
Pożary i skażenia
Zestawiania danych SYNOP
Pracownia Klimatu
Aktualności
#AkademiaLMM
Informator meteorologiczny LMM
Słownik dla mediów
Vademecum/Produkty
R&D (Badania i rozwój)
Kontakt
Skip to content
Podsumowanie bieżącego miesiąca
Statystyka 30-letnia
Zestawienie miesięczne
<div id="forecast-app" class="forecast-app current-month-app"> <div class="layout-container"> <div class="left-column"> <div class="section"> <h3>Podsumowanie:</h3> <div id="modeButtons" class="buttons mode-buttons"></div> </div> <div class="section"> <h3>Charakterystyka:</h3> <div id="paramButtons" class="buttons params-buttons"></div> </div> <div class="keyboard-info"> <strong>💡 Skróty klawiszowe:</strong><br> 1-2 wybór widoku<br> ↑, ↓ zmiana charakterystyki<br> < > zmiana karty głównej </div> </div> <div class="right-column"> <div class="section images"> <div id="loader" class="loader-container" style="display: none;"> <div class="loader"></div> </div> <div id="images" class="images-grid"></div> <div id="noData" class="date-warning">Brak dostępnej mapy dla wybranego zestawu.</div> </div> </div> </div> </div> <style> .forecast-app { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; } .layout-container { display: flex; flex-wrap: wrap; gap: 10px; } .left-column { flex: 1; min-width: 260px; max-width: 300px; } .right-column { flex: 2; min-width: 400px; } .section { margin-bottom: 12px; background: #f9f9f9; padding: 10px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); } .section h3 { margin-top: 0; margin-bottom: 6px; border-bottom: 1px solid #ddd; padding-bottom: 5px; color: #333; } .buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; } .buttons button { padding: 8px 10px; min-width: 45px; border: 1px solid #666; border-radius: 8px; background: #f5f5f5; cursor: pointer; transition: all 0.2s; font-size: 0.9em; font-weight: 600; } .buttons button:hover { background: #e3f5f3; border-color: rgba(86, 221, 208, 1); } .buttons button.active { background: rgba(86, 221, 208, 1); border-color: rgba(56, 191, 178, 1); color: #fff; } .mode-buttons, .params-buttons { display: grid; grid-template-columns: 1fr; gap: 8px; } .mode-buttons button, .params-buttons button { width: 100%; text-align: center; } .images-grid { display: grid; grid-template-columns: 1fr; gap: 14px; min-height: 420px; } .image-card { margin: 0; border: 1px solid #ddd; border-radius: 8px; padding: 8px; background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); } .image-card img { width: 100%; height: auto; display: block; border-radius: 5px; } .loader-container { display: flex; justify-content: center; align-items: center; flex-direction: column; width: 100%; height: 300px; z-index: 100; position: relative; background-color: rgba(245, 245, 245, 0.7); border-radius: 8px; margin-bottom: 10px; } .loader { border: 12px solid #f3f3f3; border-radius: 50%; border-top: 12px solid rgba(86, 221, 208, 1); width: 90px; height: 90px; animation: spin 0.8s linear infinite; box-shadow: 0 0 20px rgba(86, 221, 208, 0.7); } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .date-warning { display: none; text-align: center; padding: 8px 15px; background: rgba(255, 152, 0, 0.1); border: 1px solid rgba(255, 152, 0, 0.3); border-radius: 6px; font-size: 13px; color: #e65100; margin: 10px 0; font-weight: 500; } .keyboard-info { font-size: 11px; color: #555; margin-top: 20px; padding: 10px; line-height: 1.6; background-color: #f0f8ff; border-left: 3px solid rgba(86, 221, 208, 1); border-radius: 4px; } .keyboard-info strong { color: rgba(86, 221, 208, 1); font-size: 12px; } @media (max-width: 768px) { .layout-container { flex-direction: column; } .left-column, .right-column { max-width: 100%; width: 100%; min-width: 0; } .keyboard-info { display: none; } } </style> <script> const modeConfig = { summary: { id: "summary", label: "Podsumowanie miesiąca", folder: "aktu_mies", parameters: [ { id: "TAVE", label: "Temperatura średnia", file: "TAVE.png" }, { id: "TAVE_ANOM", label: "Anomalia temperatury", file: "TAVE_anom.png" }, { id: "TMAX", label: "Temperatura maksymalna", file: "TMAX.png" }, { id: "TMIN", label: "Temperatura minimalna", file: "TMIN.png" }, { id: "RRR_ACU", label: "Suma opadu", file: "RRR_acu.png" }, { id: "RRR_ANOM", label: "Anomalia opadu", file: "RRR_anom.png" }, { id: "SSS_ACU", label: "Usłonecznienie", file: "SSS_acu.png" }, { id: "SSS_ANOM", label: "Anomalia usłonecznienia", file: "SSS_anom.png" } ] }, daily: { id: "daily", label: "Zestawienie dni", folder: "aktu_mies_kazdy_dzien", parameters: [ { id: "TAVE", label: "Temperatura średnia", file: "TAVE.png" }, { id: "TMAX", label: "Temperatura maksymalna", file: "TMAX.png" }, { id: "TMIN", label: "Temperatura minimalna", file: "TMIN.png" }, { id: "RR", label: "Opad", file: "RR.png" } ] } }; const orderedModes = ["summary", "daily"]; const state = { mode: "summary", param: "TAVE" }; const bridge = window.__switcherBridge; const initialState = bridge ? bridge.getInitialState("current") : null; if (initialState) { if (typeof initialState.mode === "string" && orderedModes.includes(initialState.mode)) { state.mode = initialState.mode; } if (typeof initialState.param === "string") { state.param = initialState.param; } } const modeButtonsEl = document.getElementById("modeButtons"); const paramButtonsEl = document.getElementById("paramButtons"); const imagesEl = document.getElementById("images"); const noDataEl = document.getElementById("noData"); const loaderEl = document.getElementById("loader"); const pageCacheToken = String(Date.now()); const imageAvailabilityCache = new Map(); const imagePreloadPromises = new Map(); let renderToken = 0; function syncUrlState() { if (!bridge) { return; } bridge.updateState("current", { mode: state.mode, param: state.param }); } function getCurrentParameters() { return modeConfig[state.mode].parameters; } function ensureActiveParameter() { const params = getCurrentParameters(); if (!params.some((item) => item.id === state.param)) { state.param = params[0].id; } } function getSelectedParameter() { const params = getCurrentParameters(); return params.find((item) => item.id === state.param) || params[0]; } function setLoading(isLoading) { loaderEl.style.display = isLoading ? "flex" : "none"; } function setActiveModeButton() { modeButtonsEl.querySelectorAll("button").forEach((button) => { button.classList.toggle("active", button.dataset.mode === state.mode); }); } function setActiveParamButton() { paramButtonsEl.querySelectorAll("button").forEach((button) => { button.classList.toggle("active", button.dataset.param === state.param); }); } function buildImagePathFor(modeId, paramFile) { return `/cmm/wp-content/uploads/production/analizy_meteo/${modeConfig[modeId].folder}/${paramFile}?v=${pageCacheToken}`; } function buildImagePath() { const selectedParam = getSelectedParameter(); return buildImagePathFor(state.mode, selectedParam.file); } function preloadImage(src) { if (imageAvailabilityCache.has(src)) { return Promise.resolve(imageAvailabilityCache.get(src)); } if (imagePreloadPromises.has(src)) { return imagePreloadPromises.get(src); } const preloadPromise = new Promise((resolve) => { const img = new Image(); img.onload = () => { imageAvailabilityCache.set(src, true); imagePreloadPromises.delete(src); resolve(true); }; img.onerror = () => { imageAvailabilityCache.set(src, false); imagePreloadPromises.delete(src); resolve(false); }; img.src = src; }); imagePreloadPromises.set(src, preloadPromise); return preloadPromise; } function preloadModeImages(modeId) { const params = modeConfig[modeId].parameters; params.forEach((param) => { const src = buildImagePathFor(modeId, param.file); void preloadImage(src); }); } function checkImageExists(src) { return preloadImage(src); } function renderModeButtons() { modeButtonsEl.innerHTML = ""; orderedModes.forEach((modeId) => { const button = document.createElement("button"); button.type = "button"; button.dataset.mode = modeId; button.textContent = modeConfig[modeId].label; button.addEventListener("click", () => { state.mode = modeId; ensureActiveParameter(); preloadModeImages(state.mode); setActiveModeButton(); renderParamButtons(); renderImage(); }); modeButtonsEl.appendChild(button); }); setActiveModeButton(); } function renderParamButtons() { paramButtonsEl.innerHTML = ""; getCurrentParameters().forEach((param) => { const button = document.createElement("button"); button.type = "button"; button.dataset.param = param.id; button.textContent = param.label; button.addEventListener("click", () => { state.param = param.id; setActiveParamButton(); renderImage(); }); paramButtonsEl.appendChild(button); }); setActiveParamButton(); } function appendImageCard(imagePath) { const figure = document.createElement("figure"); figure.className = "image-card"; const link = document.createElement("a"); link.href = imagePath; link.target = "_blank"; link.rel = "noopener"; const image = document.createElement("img"); image.src = imagePath; image.alt = "Mapa aktualnego miesiąca"; link.appendChild(image); figure.appendChild(link); imagesEl.appendChild(figure); } async function renderImage() { imagesEl.innerHTML = ""; noDataEl.style.display = "none"; setLoading(true); syncUrlState(); const token = ++renderToken; const imagePath = buildImagePath(); const exists = await checkImageExists(imagePath); if (token !== renderToken) { return; } if (exists) { appendImageCard(imagePath); } else { noDataEl.style.display = "block"; } setLoading(false); } function selectModeByIndex(index) { const modeId = orderedModes[index]; if (!modeId) { return; } state.mode = modeId; ensureActiveParameter(); setActiveModeButton(); renderParamButtons(); renderImage(); } function selectNextParam(step) { const params = getCurrentParameters(); const currentIndex = params.findIndex((item) => item.id === state.param); if (currentIndex === -1) { return; } const nextIndex = (currentIndex + step + params.length) % params.length; state.param = params[nextIndex].id; setActiveParamButton(); renderImage(); } function shouldIgnoreKeyboardEvent(event) { const target = event.target; if (!target) { return false; } const tag = target.tagName ? target.tagName.toLowerCase() : ""; return tag === "input" || tag === "textarea" || tag === "select" || target.isContentEditable; } document.addEventListener("keydown", (event) => { if (shouldIgnoreKeyboardEvent(event)) { return; } if (event.key === "1") { event.preventDefault(); selectModeByIndex(0); return; } if (event.key === "2") { event.preventDefault(); selectModeByIndex(1); return; } if (event.key === "ArrowUp") { event.preventDefault(); selectNextParam(-1); return; } if (event.key === "ArrowDown") { event.preventDefault(); selectNextParam(1); } }); renderModeButtons(); ensureActiveParameter(); orderedModes.forEach((modeId) => preloadModeImages(modeId)); renderParamButtons(); renderImage(); console.log("Autor Bartłomiej Sobczyk 2026"); </script>
<div id="forecast-app" class="forecast-app monthly-summary-app"> <div class="layout-container"> <div class="left-column"> <div class="section"> <h3>Rocznik:</h3> <div id="yearButtons" class="buttons year-buttons"></div> </div> <div class="section"> <h3>Miesiąc:</h3> <div class="month-slider-wrap"> <div id="monthValue" class="month-value">Styczeń</div> <input type="range" id="monthSlider" class="horizontal-slider" min="1" max="12" step="1" value="1" aria-label="Wybierz miesiąc"> <div class="month-labels"> <span>01</span><span>02</span><span>03</span><span>04</span><span>05</span><span>06</span> <span>07</span><span>08</span><span>09</span><span>10</span><span>11</span><span>12</span> </div> </div> </div> <div class="section"> <h3>Charakterystyka:</h3> <div class="buttons params-buttons tab" id="paramTabs"> <button class="tablinks" data-param="TEMPSR" id="defaultOpen" onclick="wrf(event, 'TEMPSR')">Temperatura średnia</button> <button class="tablinks" data-param="TEMPMAX" onclick="wrf(event, 'TEMPMAX')">Temperatura maksymalna</button> <button class="tablinks" data-param="TEMPMIN" onclick="wrf(event, 'TEMPMIN')">Temperatura minimalna</button> <button class="tablinks" data-param="OPAD" onclick="wrf(event, 'OPAD')">Opad</button> </div> </div> <div class="keyboard-info"> <strong>💡 Skróty klawiszowe:</strong><br> ↑, ↓ Zmiana rocznika<br> ←, → Zmiana miesiąca<br> 1-4 Wybór charakterystyki<br> A Wszystkie miesiące<br> S Ten sam miesiąc w latach<br> < > zmiana karty głównej </div> </div> <div class="right-column"> <div class="section images"> <div class="image-header"> <h3 id="imageTitle">Temperatura średnia | Styczeń 2026</h3> <div class="header-actions"> <button id="showAllBtn" class="control-btn" type="button">Pokaż wszystkie miesiące w roku</button> <button id="showAllYearsBtn" class="control-btn" type="button">Pokaż ten sam miesiąc w latach</button> </div> </div> <div id="loader" class="loader-container" style="display: none;"> <div class="loader"></div> </div> <div id="images" class="images-grid"></div> <div id="noData" class="date-warning">Brak dostępnych map dla wybranego zestawu.</div> </div> </div> </div> </div> <style> .forecast-app { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; } .layout-container { display: flex; flex-wrap: wrap; gap: 10px; } .left-column { flex: 1; min-width: 230px; max-width: 230px; } .right-column { flex: 2; min-width: 400px; } .section { margin-bottom: 12px; background: #f9f9f9; padding: 10px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); } .section h3 { margin-top: 0; margin-bottom: 6px; border-bottom: 1px solid #ddd; padding-bottom: 5px; color: #333; } .buttons { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 3px; } .buttons button { padding: 6px 10px; min-width: 45px; border: 1px solid #666; border-radius: 6px; background: #f5f5f5; cursor: pointer; transition: all 0.2s; font-size: 0.9em; } .buttons button:hover { background: #e3f5f3; border-color: rgba(86, 221, 208, 1); } .buttons button.active, .tablinks.active { background: rgba(86, 221, 208, 1); border-color: rgba(56, 191, 178, 1); color: #fff; } .year-buttons { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; } .year-buttons button { width: 100%; min-width: 0; font-variant-numeric: tabular-nums; } .params-buttons { display: grid; grid-template-columns: 1fr; gap: 6px; } .params-buttons button { width: 100%; text-align: center; } .month-slider-wrap { margin-top: 4px; } .month-value { font-size: 1.1em; font-weight: bold; color: rgba(86, 221, 208, 1); margin-bottom: 6px; } .horizontal-slider { -webkit-appearance: none; appearance: none; width: 100%; height: 10px; border-radius: 5px; background: #e0e0e0; outline: none; margin: 4px 0 8px; } .horizontal-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 22px; height: 22px; border-radius: 50%; background: rgba(86, 221, 208, 1); cursor: pointer; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); } .horizontal-slider::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; background: rgba(86, 221, 208, 1); cursor: pointer; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); } .month-labels { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 2px; font-size: 10px; color: #777; text-align: center; } .image-header { display: flex; align-items: center; gap: 10px; justify-content: space-between; margin-bottom: 10px; } .image-header h3 { margin: 0; padding: 0; border: none; } .header-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; } .control-btn { background: rgba(86, 221, 208, 0.1); border: 2px solid rgba(86, 221, 208, 1); color: rgba(56, 191, 178, 1); border-radius: 8px; cursor: pointer; transition: all 0.2s; padding: 7px 10px; font-size: 0.85em; font-weight: bold; white-space: nowrap; } .control-btn:hover { background: rgba(86, 221, 208, 0.2); } .control-btn.active { background: rgba(86, 221, 208, 1); color: #fff; } .images-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 14px; min-height: 420px; } .image-card { margin: 0; border: 1px solid #ddd; border-radius: 8px; padding: 8px; background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); } .image-card img { width: 100%; height: auto; display: block; border-radius: 5px; } .loader-container { display: flex; justify-content: center; align-items: center; flex-direction: column; width: 100%; height: 300px; z-index: 100; position: relative; background-color: rgba(245, 245, 245, 0.7); border-radius: 8px; margin-bottom: 10px; } .loader { border: 12px solid #f3f3f3; border-radius: 50%; border-top: 12px solid rgba(86, 221, 208, 1); width: 90px; height: 90px; animation: spin 0.8s linear infinite; box-shadow: 0 0 20px rgba(86, 221, 208, 0.7); } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .date-warning { display: none; text-align: center; padding: 8px 15px; background: rgba(255, 152, 0, 0.1); border: 1px solid rgba(255, 152, 0, 0.3); border-radius: 6px; font-size: 13px; color: #e65100; margin: 10px 0; font-weight: 500; } .keyboard-info { font-size: 11px; color: #555; margin-top: 20px; padding: 10px; line-height: 1.6; background-color: #f0f8ff; border-left: 3px solid rgba(86, 221, 208, 1); border-radius: 4px; } .keyboard-info strong { color: rgba(86, 221, 208, 1); font-size: 12px; } @media (max-width: 768px) { .layout-container { flex-direction: column; } .left-column, .right-column { max-width: 100%; width: 100%; min-width: 0; } .images-grid { grid-template-columns: 1fr; } .image-header { flex-direction: column; align-items: flex-start; } .header-actions { justify-content: flex-start; } } </style> <script> const months = [ { value: 1, label: "Styczeń" }, { value: 2, label: "Luty" }, { value: 3, label: "Marzec" }, { value: 4, label: "Kwiecień" }, { value: 5, label: "Maj" }, { value: 6, label: "Czerwiec" }, { value: 7, label: "Lipiec" }, { value: 8, label: "Sierpień" }, { value: 9, label: "Wrzesień" }, { value: 10, label: "Październik" }, { value: 11, label: "Listopad" }, { value: 12, label: "Grudzień" } ]; const paramsConfig = { TEMPSR: { label: "Temperatura średnia", suffix: "TAVE" }, TEMPMAX: { label: "Temperatura maksymalna", suffix: "TMAX" }, TEMPMIN: { label: "Temperatura minimalna", suffix: "TMIN" }, OPAD: { label: "Opad", suffix: "RR" } }; const firstYear = 2013; const now = new Date(); const currentYear = now.getFullYear(); const currentMonth = now.getMonth() + 1; const defaultMonthDate = new Date(currentYear, currentMonth - 2, 1); const defaultYear = defaultMonthDate.getFullYear(); const defaultMonth = defaultMonthDate.getMonth() + 1; const latestYear = Math.max(firstYear, currentYear); const years = Array.from({ length: latestYear - firstYear + 1 }, (_, i) => latestYear - i); const state = { year: defaultYear, month: defaultMonth, param: "TEMPSR", viewMode: "single" }; const bridge = window.__switcherBridge; const initialState = bridge ? bridge.getInitialState("monthly") : null; if (initialState) { if (Number.isInteger(initialState.year) && years.includes(initialState.year)) { state.year = initialState.year; } if (Number.isInteger(initialState.month) && initialState.month >= 1 && initialState.month <= 12) { state.month = initialState.month; } if (typeof initialState.param === "string" && paramsConfig[initialState.param]) { state.param = initialState.param; } if ( typeof initialState.viewMode === "string" && ["single", "allMonths", "allYears"].includes(initialState.viewMode) ) { state.viewMode = initialState.viewMode; } } const hasPinnedPeriodFromUrl = Boolean(initialState && initialState.periodPinned === true); const yearButtonsEl = document.getElementById("yearButtons"); const monthSliderEl = document.getElementById("monthSlider"); const monthValueEl = document.getElementById("monthValue"); const imageTitleEl = document.getElementById("imageTitle"); const imagesEl = document.getElementById("images"); const noDataEl = document.getElementById("noData"); const showAllBtnEl = document.getElementById("showAllBtn"); const showAllYearsBtnEl = document.getElementById("showAllYearsBtn"); const loaderEl = document.getElementById("loader"); const imageAvailabilityCache = new Map(); const imagePreloadPromises = new Map(); let renderToken = 0; function syncUrlState() { if (!bridge) { return; } bridge.updateState("monthly", { year: state.year, month: state.month, param: state.param, viewMode: state.viewMode }); } function getMonthMeta(monthNumber) { return months.find((m) => m.value === monthNumber) || months[0]; } function createImagePath(year, month, suffix) { return `/cmm/wp-content/uploads/production/analizy_meteo/miesieczne/${year}_${month}_${suffix}.png`; } function checkImageExists(src) { return preloadImage(src); } async function findLatestAvailableYearMonth(paramId) { const suffix = paramsConfig[paramId].suffix; for (const year of years) { const monthsDesc = Array.from({ length: 12 }, (_, i) => 12 - i); const checks = await Promise.all( monthsDesc.map(async (month) => { const path = createImagePath(year, month, suffix); return { month: month, ok: await checkImageExists(path) }; }) ); const found = checks.find((item) => item.ok); if (found) { return { year: year, month: found.month }; } } return null; } function createYearButtons() { yearButtonsEl.innerHTML = ""; years.forEach((year) => { const btn = document.createElement("button"); btn.type = "button"; btn.textContent = year; btn.dataset.year = String(year); if (year === state.year) { btn.classList.add("active"); } btn.addEventListener("click", () => { state.year = year; yearButtonsEl.querySelectorAll("button").forEach((b) => b.classList.remove("active")); btn.classList.add("active"); renderImages(); }); yearButtonsEl.appendChild(btn); }); } function setLoading(isLoading) { loaderEl.style.display = isLoading ? "flex" : "none"; } async function initializeDefaultSelection() { setLoading(true); try { const preferredPeriod = hasPinnedPeriodFromUrl ? { year: state.year, month: state.month } : { year: defaultYear, month: defaultMonth }; state.year = preferredPeriod.year; state.month = preferredPeriod.month; if (!years.includes(state.year)) { state.year = years[0]; } monthSliderEl.value = String(state.month); updateActiveYearButton(); setActiveParamButton(state.param); await renderImages(); } finally { setLoading(false); } } function updateMonthLabel() { const monthMeta = getMonthMeta(state.month); monthValueEl.textContent = monthMeta.label; } function syncViewModeButtons() { const allMonthsActive = state.viewMode === "allMonths"; const allYearsActive = state.viewMode === "allYears"; showAllBtnEl.classList.toggle("active", allMonthsActive); showAllYearsBtnEl.classList.toggle("active", allYearsActive); showAllBtnEl.textContent = allMonthsActive ? "Wróć do jednego miesiąca" : "Pokaż wszystkie miesiące"; showAllYearsBtnEl.textContent = allYearsActive ? "Wróć do jednego roku" : "Pokaż ten sam miesiąc w latach"; } function updateTitle() { const monthMeta = getMonthMeta(state.month); const paramLabel = paramsConfig[state.param].label; const period = state.viewMode === "allMonths" ? `${state.year} (wszystkie miesiące)` : state.viewMode === "allYears" ? `${monthMeta.label} (różne lata)` : `${monthMeta.label} ${state.year}`; imageTitleEl.textContent = `${paramLabel} | ${period}`; } function setActiveParamButton(activeParam) { document.querySelectorAll(".tablinks").forEach((button) => { button.classList.toggle("active", button.dataset.param === activeParam); }); } function preloadImage(src) { if (imageAvailabilityCache.has(src)) { return Promise.resolve(imageAvailabilityCache.get(src)); } if (imagePreloadPromises.has(src)) { return imagePreloadPromises.get(src); } const preloadPromise = new Promise((resolve) => { const img = new Image(); img.onload = () => { imageAvailabilityCache.set(src, true); imagePreloadPromises.delete(src); resolve(true); }; img.onerror = () => { imageAvailabilityCache.set(src, false); imagePreloadPromises.delete(src); resolve(false); }; img.src = src; }); imagePreloadPromises.set(src, preloadPromise); return preloadPromise; } function appendImageCard(src) { const figure = document.createElement("figure"); figure.className = "image-card"; const link = document.createElement("a"); link.href = src; link.target = "_blank"; link.rel = "noopener"; const img = document.createElement("img"); img.src = src; img.alt = "Mapa"; link.appendChild(img); figure.appendChild(link); imagesEl.appendChild(figure); } function updateActiveYearButton() { yearButtonsEl.querySelectorAll("button").forEach((button) => { button.classList.toggle("active", Number(button.dataset.year) === state.year); }); } function toggleShowAll() { state.viewMode = state.viewMode === "allMonths" ? "single" : "allMonths"; syncViewModeButtons(); renderImages(); } function toggleShowAllYears() { state.viewMode = state.viewMode === "allYears" ? "single" : "allYears"; syncViewModeButtons(); renderImages(); } function changeYearByOffset(offset) { const currentIndex = years.indexOf(state.year); if (currentIndex === -1) { return; } const nextIndex = Math.max(0, Math.min(years.length - 1, currentIndex + offset)); if (nextIndex === currentIndex) { return; } state.year = years[nextIndex]; updateActiveYearButton(); renderImages(); } function changeMonthByOffset(offset) { const nextMonth = Math.max(1, Math.min(12, state.month + offset)); if (nextMonth === state.month) { return; } state.month = nextMonth; monthSliderEl.value = String(nextMonth); renderImages(); } function selectParamByIndex(index) { const orderedParams = ["TEMPSR", "TEMPMAX", "TEMPMIN", "OPAD"]; const paramId = orderedParams[index]; if (!paramId) { return; } state.param = paramId; setActiveParamButton(paramId); renderImages(); } function shouldIgnoreKeyboardEvent(event) { const target = event.target; if (!target) { return false; } const tag = target.tagName ? target.tagName.toLowerCase() : ""; return tag === "input" || tag === "textarea" || tag === "select" || target.isContentEditable; } async function renderImages() { imagesEl.innerHTML = ""; noDataEl.style.display = "none"; const token = ++renderToken; setLoading(true); syncUrlState(); updateMonthLabel(); updateTitle(); const renderTargets = state.viewMode === "allMonths" ? months.map((monthMeta) => ({ year: state.year, month: monthMeta.value })) : state.viewMode === "allYears" ? years.map((year) => ({ year: year, month: state.month })) : [{ year: state.year, month: state.month }]; const suffix = paramsConfig[state.param].suffix; try { const checks = await Promise.all( renderTargets.map(async (target) => { const filePath = createImagePath(target.year, target.month, suffix); const ok = await preloadImage(filePath); return { ok: ok, filePath: filePath }; }) ); if (token !== renderToken) { return; } checks.forEach((item) => { if (item.ok) { appendImageCard(item.filePath); } }); if (!checks.some((item) => item.ok)) { noDataEl.style.display = "block"; } } finally { if (token === renderToken) { setLoading(false); } } } function wrf(evt, paramId) { state.param = paramId; setActiveParamButton(paramId); renderImages(); if (evt && evt.currentTarget) { evt.preventDefault(); } } monthSliderEl.addEventListener("input", (event) => { state.month = Number(event.target.value); renderImages(); }); showAllBtnEl.addEventListener("click", toggleShowAll); showAllYearsBtnEl.addEventListener("click", toggleShowAllYears); document.addEventListener("keydown", (event) => { if (shouldIgnoreKeyboardEvent(event)) { return; } if (event.key === "ArrowLeft") { event.preventDefault(); changeMonthByOffset(-1); return; } if (event.key === "ArrowRight") { event.preventDefault(); changeMonthByOffset(1); return; } if (event.key === "ArrowUp") { event.preventDefault(); changeYearByOffset(-1); return; } if (event.key === "ArrowDown") { event.preventDefault(); changeYearByOffset(1); return; } if (event.key === "1") { selectParamByIndex(0); return; } if (event.key === "2") { selectParamByIndex(1); return; } if (event.key === "3") { selectParamByIndex(2); return; } if (event.key === "4") { selectParamByIndex(3); return; } if (event.key === "a" || event.key === "A") { event.preventDefault(); toggleShowAll(); return; } if (event.key === "s" || event.key === "S") { event.preventDefault(); toggleShowAllYears(); } }); createYearButtons(); syncViewModeButtons(); initializeDefaultSelection(); console.log("Autor Bartłomiej Sobczyk 2026"); </script>
<div id="forecast-app" class="forecast-app climate-stats-app"> <div class="layout-container"> <div class="left-column"> <div class="section"> <h3>Zakres statystyki:</h3> <div id="modeButtons" class="buttons mode-buttons"></div> </div> <div class="section"> <h3 id="paramTitle">Charakterystyka:</h3> <div id="paramButtons" class="buttons params-buttons"></div> </div> <div class="keyboard-info"> <strong>💡 Skróty klawiszowe:</strong><br> 1-3 zmiana zakresu statystyki <br>↑, ↓ zmiana charakterystyki <br>< > zmiana karty głównej </div> </div> <div class="right-column"> <div class="section images"> <div id="loader" class="loader-container" style="display: none;"> <div class="loader"></div> </div> <div id="images" class="images-grid"></div> <div id="noData" class="date-warning">Brak dostępnej mapy dla wybranego zestawu.</div> </div> </div> </div> </div> <style> .forecast-app { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; } .layout-container { display: flex; flex-wrap: wrap; gap: 10px; } .left-column { flex: 1; min-width: 280px; max-width: 320px; } .right-column { flex: 2; min-width: 400px; } .section { margin-bottom: 12px; background: #f9f9f9; padding: 10px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); } .section h3 { margin-top: 0; margin-bottom: 6px; border-bottom: 1px solid #ddd; padding-bottom: 5px; color: #333; } .buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; } .buttons button { padding: 8px 10px; min-width: 45px; border: 1px solid #666; border-radius: 8px; background: #f5f5f5; cursor: pointer; transition: all 0.2s; font-size: 0.9em; font-weight: 600; } .buttons button:hover { background: #e3f5f3; border-color: rgba(86, 221, 208, 1); } .buttons button.active { background: rgba(86, 221, 208, 1); border-color: rgba(56, 191, 178, 1); color: #fff; } .mode-buttons { display: grid; grid-template-columns: 1fr; gap: 8px; } .mode-buttons button { width: 100%; text-align: center; } .params-buttons { display: grid; grid-template-columns: 1fr; gap: 8px; } .params-buttons button { width: 100%; text-align: center; } .param-select-wrap { position: relative; width: 100%; min-height: 44px; } .param-select { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; } .param-select-display { min-height: 44px; padding: 10px 40px 10px 12px; border: 1px solid #666; border-radius: 8px; background: #fff; font-size: 16px; line-height: 1.35; font-weight: 500; white-space: normal; word-break: break-word; position: relative; pointer-events: none; } .param-select-display::after { content: ""; position: absolute; right: 14px; top: 50%; margin-top: -3px; width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 7px solid #666; } .param-select-wrap:focus-within .param-select-display { outline: 2px solid rgba(86, 221, 208, 0.35); border-color: rgba(86, 221, 208, 1); } .images-grid { display: grid; grid-template-columns: 1fr; gap: 14px; min-height: 420px; } .image-card { margin: 0; border: 1px solid #ddd; border-radius: 8px; padding: 8px; background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); } .image-card img { width: 100%; height: auto; display: block; border-radius: 5px; } .loader-container { display: flex; justify-content: center; align-items: center; flex-direction: column; width: 100%; height: 300px; z-index: 100; position: relative; background-color: rgba(245, 245, 245, 0.7); border-radius: 8px; margin-bottom: 10px; } .loader { border: 12px solid #f3f3f3; border-radius: 50%; border-top: 12px solid rgba(86, 221, 208, 1); width: 90px; height: 90px; animation: spin 0.8s linear infinite; box-shadow: 0 0 20px rgba(86, 221, 208, 0.7); } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .date-warning { display: none; text-align: center; padding: 8px 15px; background: rgba(255, 152, 0, 0.1); border: 1px solid rgba(255, 152, 0, 0.3); border-radius: 6px; font-size: 13px; color: #e65100; margin: 10px 0; font-weight: 500; } .keyboard-info { font-size: 11px; color: #555; margin-top: 20px; padding: 10px; line-height: 1.6; background-color: #f0f8ff; border-left: 3px solid rgba(86, 221, 208, 1); border-radius: 4px; } .keyboard-info strong { color: rgba(86, 221, 208, 1); font-size: 12px; } @media (max-width: 768px) { .layout-container { flex-direction: column; } .left-column, .right-column { max-width: 100%; width: 100%; min-width: 0; } .params-buttons { grid-template-columns: 1fr; } .keyboard-info { display: none; } } </style> <script> const monthNamesUpperGen = [ "stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca", "lipca", "sierpnia", "września", "października", "listopada", "grudnia" ]; const monthNamesUpperNom = [ "styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień" ]; const modeConfig = { day: { id: "day", titlePrefix: "Zestawienie na dzień", sectionTitle: "Charakterystyka:", folders: ["dobowe_30lat"] }, period: { id: "period", titlePrefix: "Zestawienie", sectionTitle: "Charakterystyka:", folders: ["15dni_30lat"] }, month: { id: "month", titlePrefix: "Zestawienie za", sectionTitle: "Charakterystyka:", folders: ["miesieczne_30lat"] } }; const orderedModes = ["day", "period", "month"]; const dayParameters = [ { id: "TEMPSR", label: "Temperatura średnia", code: "TAVE" }, { id: "TEMPMAX", label: "Temperatura maksymalna", code: "TMAX" }, { id: "TEMPMIN", label: "Temperatura minimalna", code: "TMIN" }, { id: "OPAD", label: "Opad", code: "RR" }, { id: "WIATR", label: "Wiatr", code: "WIATR" }, { id: "PKSN", label: "Pokrywa śnieżna", code: "PKSN" } ]; const periodMonthParameters = [ { id: "LD_OPAD_01", label: "Liczba dni z opadem >= 0.1mm", code: "LD_OPAD_01" }, { id: "LD_PKSN", label: "Liczba dni z pokrywą śnieżną >= 1cm", code: "LD_PKSN" }, { id: "LD_PORYWY_55", label: "Liczba dni z porywem wiatru >= 55km/h", code: "LD_PORYWY_55" }, { id: "LD_TMAX_25", label: "Liczba dni z temperaturą >= 25°C", code: "LD_TMAX_25" }, { id: "LD_TMAX_30", label: "Liczba dni z temperaturą >= 30°C", code: "LD_TMAX_30" }, { id: "LD_TMIN_PON_0", label: "Liczba dni z temperaturą < 0°C", code: "LD_TMIN_PON_0" }, { id: "LD_TMIN_PON_10", label: "Liczba dni z temperaturą <= -10°C", code: "LD_TMIN_PON_10" }, { id: "LD_TMIN_PON_15", label: "Liczba dni z temperaturą <= -15°C", code: "LD_TMIN_PON_15" }, { id: "LD_TMIN_PON_20", label: "Liczba dni z temperaturą <= -20°C", code: "LD_TMIN_PON_20" }, { id: "LD_TMIN_PON_25", label: "Liczba dni z temperaturą <= -25°C", code: "LD_TMIN_PON_25" }, { id: "PKSN", label: "Maksymalna grubość pokrywy śnieżnej (cm)", code: "PKSN" }, { id: "PKSN_AVE", label: "Średnia grubość pokrywy śnieżnej (cm)", code: "PKSN_AVE" }, { id: "RR_ANOM", label: "Anomalia sumy opadu (%) względem lat 1991-2020", code: "RR_anom" }, { id: "RR", label: "Suma opadu (mm)", code: "RR" }, { id: "SMBD", label: "Maksymalny dobowy opad (mm)", code: "SMBD" }, { id: "TAVE_ANOM", label: "Anomalia średniej temperatury (°C) względem lat 1991-2020", code: "TAVE_anom" }, { id: "TAVE", label: "Średnia temperatura (°C)", code: "TAVE" }, { id: "TMAX_AVE", label: "Średnia maksymalna temperatura (°C)", code: "TMAX_AVE" }, { id: "TMAX", label: "Maksymalna temperatura (°C)", code: "TMAX" }, { id: "TMIN_AVE", label: "Średnia minimalna temperatura (°C)", code: "TMIN_AVE" }, { id: "TMIN", label: "Minimalna temperatura (°C)", code: "TMIN" }, { id: "WIATR_AVG", label: "Średnia prędkość wiatru (km/h)", code: "Wiatr" } ]; const modeButtonsEl = document.getElementById("modeButtons"); const paramButtonsEl = document.getElementById("paramButtons"); const paramTitleEl = document.getElementById("paramTitle"); const imagesEl = document.getElementById("images"); const noDataEl = document.getElementById("noData"); const loaderEl = document.getElementById("loader"); const now = new Date(); const dayDate = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const periodStartDate = new Date(now.getFullYear(), now.getMonth(), now.getDate()); periodStartDate.setDate(periodStartDate.getDate() - 7); const periodEndDate = new Date(now.getFullYear(), now.getMonth(), now.getDate()); periodEndDate.setDate(periodEndDate.getDate() + 7); const monthDate = new Date(now.getFullYear(), now.getMonth(), 1); const state = { mode: "day", param: "TEMPSR" }; const bridge = window.__switcherBridge; const initialState = bridge ? bridge.getInitialState("climate") : null; if (initialState) { if (typeof initialState.mode === "string" && orderedModes.includes(initialState.mode)) { state.mode = initialState.mode; } if (typeof initialState.param === "string") { state.param = initialState.param; } } let renderToken = 0; const imageAvailabilityCache = new Map(); const imagePreloadPromises = new Map(); function syncUrlState() { if (!bridge) { return; } bridge.updateState("climate", { mode: state.mode, param: state.param }); } function isDropdownMode(modeId) { return modeId === "period" || modeId === "month"; } function getParametersForMode(modeId) { if (modeId === "day") { return dayParameters; } return periodMonthParameters; } function ensureActiveParameterForMode() { const modeParams = getParametersForMode(state.mode); if (!modeParams.some((item) => item.id === state.param)) { state.param = modeParams[0].id; } } function formatDayLabel(date) { return `${date.getDate()} ${monthNamesUpperGen[date.getMonth()]}`; } function formatMonthLabel(date) { return monthNamesUpperNom[date.getMonth()]; } function formatPeriodLabel(startDate, endDate) { const startPart = `${startDate.getDate()} ${monthNamesUpperGen[startDate.getMonth()]}`; const endPart = `${endDate.getDate()} ${monthNamesUpperGen[endDate.getMonth()]}`; return `${startPart} - ${endPart}`; } function getModeButtonText(modeId) { if (modeId === "day") { return `${modeConfig.day.titlePrefix} ${formatDayLabel(dayDate)}`; } if (modeId === "period") { return `${modeConfig.period.titlePrefix} ${formatPeriodLabel(periodStartDate, periodEndDate)}`; } return `${modeConfig.month.titlePrefix} ${formatMonthLabel(monthDate)}`; } function getModeDisplayPeriod(modeId) { if (modeId === "day") { return formatDayLabel(dayDate); } if (modeId === "period") { return formatPeriodLabel(periodStartDate, periodEndDate); } return formatMonthLabel(monthDate); } function setLoading(isLoading) { loaderEl.style.display = isLoading ? "flex" : "none"; } function setActiveModeButton() { modeButtonsEl.querySelectorAll("button").forEach((button) => { button.classList.toggle("active", button.dataset.mode === state.mode); }); } function setActiveParamButton() { const select = paramButtonsEl.querySelector("select"); if (select) { const modeParams = getParametersForMode(state.mode); const selected = modeParams.find((item) => item.id === state.param) || modeParams[0]; select.value = selected.id; select.title = selected.label; const display = paramButtonsEl.querySelector(".param-select-display"); if (display) { display.textContent = selected.label; } } paramButtonsEl.querySelectorAll("button").forEach((button) => { button.classList.toggle("active", button.dataset.param === state.param); }); } function getFileCandidates(paramCode, modeId) { if (modeId === "day" && paramCode === "WIATR") { return ["WIATR.png", "Wiatr.png"]; } return [`${paramCode}.png`]; } function buildImageCandidates(paramCode, modeId) { const folders = modeConfig[modeId].folders; const fileCandidates = getFileCandidates(paramCode, modeId); const urls = []; folders.forEach((folder) => { fileCandidates.forEach((fileName) => { urls.push(`/cmm/wp-content/uploads/production/analizy_meteo/${folder}/${fileName}`); }); }); return urls; } function preloadImage(src) { if (imageAvailabilityCache.has(src)) { return Promise.resolve(imageAvailabilityCache.get(src)); } if (imagePreloadPromises.has(src)) { return imagePreloadPromises.get(src); } const preloadPromise = new Promise((resolve) => { const img = new Image(); img.onload = () => { imageAvailabilityCache.set(src, true); imagePreloadPromises.delete(src); resolve(true); }; img.onerror = () => { imageAvailabilityCache.set(src, false); imagePreloadPromises.delete(src); resolve(false); }; img.src = src; }); imagePreloadPromises.set(src, preloadPromise); return preloadPromise; } function preloadModeImages(modeId) { const modeParams = getParametersForMode(modeId); modeParams.forEach((param) => { const candidates = buildImageCandidates(param.code, modeId); candidates.forEach((src) => { void preloadImage(src); }); }); } function checkImageExists(src) { return preloadImage(src); } async function findFirstAvailableImagePath(paramCode, modeId) { const candidates = buildImageCandidates(paramCode, modeId); for (const candidate of candidates) { const exists = await checkImageExists(candidate); if (exists) { return candidate; } } return null; } function renderModeButtons() { modeButtonsEl.innerHTML = ""; orderedModes.forEach((modeId) => { const button = document.createElement("button"); button.type = "button"; button.dataset.mode = modeId; button.textContent = getModeButtonText(modeId); button.addEventListener("click", () => { state.mode = modeId; ensureActiveParameterForMode(); preloadModeImages(state.mode); paramTitleEl.textContent = modeConfig[modeId].sectionTitle; setActiveModeButton(); renderParamButtons(); renderImage(); }); modeButtonsEl.appendChild(button); }); setActiveModeButton(); } function selectNextMode(step) { const currentIndex = orderedModes.indexOf(state.mode); if (currentIndex === -1) { return; } const nextIndex = (currentIndex + step + orderedModes.length) % orderedModes.length; state.mode = orderedModes[nextIndex]; ensureActiveParameterForMode(); paramTitleEl.textContent = modeConfig[state.mode].sectionTitle; setActiveModeButton(); renderParamButtons(); renderImage(); } function selectModeByIndex(index) { const modeId = orderedModes[index]; if (!modeId) { return; } state.mode = modeId; ensureActiveParameterForMode(); paramTitleEl.textContent = modeConfig[state.mode].sectionTitle; setActiveModeButton(); renderParamButtons(); renderImage(); } function renderParamButtons() { paramButtonsEl.innerHTML = ""; const modeParams = getParametersForMode(state.mode); if (isDropdownMode(state.mode)) { const wrap = document.createElement("div"); wrap.className = "param-select-wrap"; const select = document.createElement("select"); select.className = "param-select"; select.setAttribute("aria-label", "Wybierz charakterystykę"); modeParams.forEach((param) => { const option = document.createElement("option"); option.value = param.id; option.textContent = param.label; select.appendChild(option); }); select.addEventListener("change", (event) => { state.param = event.target.value; setActiveParamButton(); renderImage(); }); const display = document.createElement("div"); display.className = "param-select-display"; wrap.appendChild(select); wrap.appendChild(display); paramButtonsEl.appendChild(wrap); setActiveParamButton(); return; } modeParams.forEach((param) => { const button = document.createElement("button"); button.type = "button"; button.dataset.param = param.id; button.textContent = param.label; button.addEventListener("click", () => { state.param = param.id; setActiveParamButton(); renderImage(); }); paramButtonsEl.appendChild(button); }); setActiveParamButton(); } function appendImageCard(imagePath) { const figure = document.createElement("figure"); figure.className = "image-card"; const link = document.createElement("a"); link.href = imagePath; link.target = "_blank"; link.rel = "noopener"; const image = document.createElement("img"); image.src = imagePath; image.alt = "Mapa statystyki 30-letniej"; link.appendChild(image); figure.appendChild(link); imagesEl.appendChild(figure); } async function renderImage() { imagesEl.innerHTML = ""; noDataEl.style.display = "none"; setLoading(true); syncUrlState(); const token = ++renderToken; const modeParams = getParametersForMode(state.mode); const selectedParam = modeParams.find((item) => item.id === state.param) || modeParams[0]; const imagePath = await findFirstAvailableImagePath(selectedParam.code, state.mode); if (token !== renderToken) { return; } if (imagePath) { appendImageCard(imagePath); } else { noDataEl.style.display = "block"; } setLoading(false); } function selectNextParam(step) { const modeParams = getParametersForMode(state.mode); const currentIndex = modeParams.findIndex((item) => item.id === state.param); if (currentIndex === -1) { return; } const nextIndex = (currentIndex + step + modeParams.length) % modeParams.length; state.param = modeParams[nextIndex].id; setActiveParamButton(); renderImage(); } function shouldIgnoreKeyboardEvent(event) { const target = event.target; if (!target) { return false; } const tag = target.tagName ? target.tagName.toLowerCase() : ""; return tag === "input" || tag === "textarea" || tag === "select" || target.isContentEditable; } document.addEventListener("keydown", (event) => { if (shouldIgnoreKeyboardEvent(event)) { return; } if (event.key === "1") { event.preventDefault(); selectModeByIndex(0); return; } if (event.key === "2") { event.preventDefault(); selectModeByIndex(1); return; } if (event.key === "3") { event.preventDefault(); selectModeByIndex(2); return; } if (event.key === "ArrowUp") { event.preventDefault(); selectNextParam(-1); return; } if (event.key === "ArrowDown") { event.preventDefault(); selectNextParam(1); } }); renderModeButtons(); ensureActiveParameterForMode(); orderedModes.forEach((modeId) => preloadModeImages(modeId)); renderParamButtons(); paramTitleEl.textContent = modeConfig[state.mode].sectionTitle; renderImage(); console.log("Autor Bartłomiej Sobczyk 2026"); </script>
UDOSTĘPNIJ STRONĘ
Scroll Up
account
android
arrow-alt-circle-down
arrow-alt-circle-left
arrow-alt-circle-right
arrow-alt-circle-up
arrow-down
arrow-left
arrow-right
arrow-up
author
bars
behance
blogger
buffer
caret-down
caret-left
caret-right
caret-square-down
caret-square-left
caret-square-right
caret-square-up
caret-up
cart-menu-1
cart-menu-2
cart-menu-3
cart-menu-4
categories
chevron-down
chevron-left
chevron-right
chevron-up
clock
close
comments
cookies
copyright
coupon-discount
date-modified
date-published
discord
double-arrows-down
double-arrows-left
double-arrows-right
double-arrows-up
dribbble
envelope-open
envelope
eye
facebook
fax
flickr
foursquare
github
gmail
google-drive
grid-view
hashtag
hollow-ring
homepage
instagram
ios
level-down-alt
level-up-alt
line
link
linkedin
list-view
login
logout
long-arrow-alt-down
long-arrow-alt-left
long-arrow-alt-right
long-arrow-alt-up
medium
messenger
mobile-menu
mobile
phone
pinterest
place
qq
quote-left
quote-right
quotes
reading-time-hourglass
reading-time-stopwatch
reddit
rss
scroll-to-top
search
shazam
shopping-bag
shopping-cart
side-panel-opening-2-left
side-panel-opening-2-right
side-panel-opening-left
side-panel-opening-right
skype
slack
small-arrow-down
small-arrow-left
small-arrow-right
small-arrow-up
sms
snapchat
soundcloud
spinner
spotify
stackoverflow
sync
telegram
tiktok
times-circle
tinder
trello
tripadvisor
tumblr
twitch
twitter
viber
vimeo
vine
vkontakte
website
wechat
whatsapp
windows
wishlist
xing
yelp
youtube
zoom