// Weather region rendering for live playback. var weatherRegistry = window.pulsePlayerRegionTypes; var weatherPlaceholderUtils = window.placeholderUtils || {}; function weatherIconForCode(code) { var value = Number(code); if (value === 0) return 'bi-sun'; if (value <= 3) return 'bi-cloud-sun'; if (value <= 48) return 'bi-cloud-fog'; if (value <= 67 || value > 77 && value <= 82) return 'bi-cloud-rain'; if (value <= 77) return 'bi-cloud-snow'; return 'bi-cloud-lightning-rain'; } function getWeatherLocation(locationId) { var locations = Array.isArray(initialData && initialData.weatherLocations) ? initialData.weatherLocations : []; return locations.find(function (location) { return Number(location.id) === Number(locationId); }) || null; } function normalizeWeatherExpression(expression) { var value = String(expression || '').trim(); var currentAliases = { temp: 'current.temperature_2m', temp_unit: 'current.temperature_unit', feels_like: 'current.apparent_temperature', humidity: 'current.relative_humidity_2m', code: 'current.weather_code', wind: 'current.wind_speed_10m', wind_unit: 'current.wind_speed_unit', precip: 'current.precipitation', precip_unit: 'current.precipitation_unit', uv_index: 'current.uv_index', cloud_cover: 'current.cloud_cover', icon: 'current.weather_code.icon' }; var globalAliases = { temp_unit: 'current.temperature_unit', wind_unit: 'current.wind_speed_unit', precip_unit: 'current.precipitation_unit' }; if (globalAliases[value]) return globalAliases[value]; var currentField = value.replace(/^current\./, ''); var currentMatch = currentField.match(/^([^.()]+)((?:\(.*\))|(?:\..*))?$/); if (currentMatch && currentAliases[currentMatch[1]]) return currentAliases[currentMatch[1]] + (currentMatch[2] || ''); var indexed = value.match(/^(daily|hourly)\.(\d+)\.(.+)$/); if (!indexed) return value; var fieldMatch = indexed[3].match(/^([^.()]+)((?:\(.*\))|(?:\..*))?$/); var field = fieldMatch ? fieldMatch[1] : indexed[3]; var aliases = indexed[1] === 'daily' ? { time: 'time', code: 'weather_code', temp_max: 'temperature_2m_max', temp_min: 'temperature_2m_min', precip: 'precipitation_sum', wind: 'wind_speed_10m_max', uv_index: 'uv_index_max', cloud_cover: 'cloud_cover_mean', sunrise: 'sunrise', sunset: 'sunset', icon: 'weather_code' } : { time: 'time', code: 'weather_code', temp: 'temperature_2m', precip: 'precipitation', wind: 'wind_speed_10m', uv_index: 'uv_index', cloud_cover: 'cloud_cover', icon: 'weather_code' }; if (!Object.prototype.hasOwnProperty.call(aliases, field)) return value; return field === 'icon' ? indexed[1] + '.' + aliases[field] + '.' + indexed[2] + '.icon' + (fieldMatch[2] || '') : indexed[1] + '.' + aliases[field] + '.' + indexed[2] + (fieldMatch[2] || ''); } function withWeatherUnits(snapshot, location) { var data = Object.assign({}, snapshot, { location_label: location.location_label || '', name: location.name || '', timezone: location.timezone || '', temp_unit: location.temperature_unit === 'fahrenheit' ? '°F' : '°C', wind_unit: location.wind_unit === 'mph' ? 'mph' : location.wind_unit === 'ms' ? 'm/s' : 'km/h', precip_unit: location.precipitation_unit === 'inch' ? 'in' : 'mm' }); var temperatureUnit = location.temperature_unit === 'fahrenheit' ? '°F' : '°C'; var windUnit = location.wind_unit === 'mph' ? 'mph' : location.wind_unit === 'ms' ? 'm/s' : 'km/h'; var precipitationUnit = location.precipitation_unit === 'inch' ? 'in' : 'mm'; data.current = Object.assign({}, snapshot.current || {}, { temperature_unit: temperatureUnit, wind_speed_unit: windUnit, precipitation_unit: precipitationUnit }); data.daily = Object.assign({}, snapshot.daily || {}, { temperature_unit: temperatureUnit }); data.hourly = Object.assign({}, snapshot.hourly || {}, { temperature_unit: temperatureUnit }); return data; } function substituteWeatherVariables(html, value, iconSetId) { return String(html || '').replace(/\{\{\s*([^{}]+?)\s*\}\}/g, function (_match, expression) { if (!value || typeof value !== 'object' || typeof weatherPlaceholderUtils.resolvePlaceholderExpression !== 'function' || typeof weatherPlaceholderUtils.formatPlaceholderValue !== 'function') return ''; var rawExpression = String(expression).trim(); var normalizedExpression = normalizeWeatherExpression(rawExpression); if (typeof weatherPlaceholderUtils.isProgressPlaceholderExpression === 'function' && weatherPlaceholderUtils.isProgressPlaceholderExpression(rawExpression)) { return weatherPlaceholderUtils.renderProgressPlaceholder(value, rawExpression); } var iconMatch = normalizedExpression.match(/^(?:current\.weather_code|daily\.weather_code\.\d+|hourly\.weather_code\.\d+)\.icon(?:\((\d+)(?:\s*,\s*(\d+))?(?:\s*,\s*(top|middle|bottom))?\))?$/); if (iconMatch) { var codeExpression = normalizedExpression.replace(/\.icon(?:\(.*\))?$/, ''); var width = iconMatch[1] ? Math.max(1, Math.min(1000, Number(iconMatch[1]))) : 0; var height = iconMatch[2] ? Math.max(1, Math.min(1000, Number(iconMatch[2]))) : width; var alignment = iconMatch[3] || 'middle'; var style = width ? ' style="display:block;font-size:' + width + 'px;line-height:1;width:' + width + 'px;height:' + height + 'px;"' : ''; var weatherCode = weatherPlaceholderUtils.resolvePlaceholderExpression(value, codeExpression, { timeZone: value.timezone }); var source = window.pulseWeatherIcons && window.pulseWeatherIcons.imageForCode(initialData && initialData.weatherIconSets, iconSetId, weatherCode, window.pulseWeatherIcons.isNightForWeather(value)); if (source) return window.pulseWeatherIcons.renderImage(source, width, height, alignment); var icon = ''; var verticalAlign = alignment === 'top' || alignment === 'bottom' ? alignment : 'middle'; return width ? '' + icon + '' : icon; } return escapeHtml(weatherPlaceholderUtils.formatPlaceholderValue(weatherPlaceholderUtils.resolvePlaceholderExpression(value, normalizeWeatherExpression(expression), { timeZone: value.timezone }))); }); } function renderWeatherRegion(region, regionContent) { var value = String(regionContent && regionContent.value || ''); if (!value.trim()) return ''; var location = getWeatherLocation(regionContent && regionContent.weather_location_id); var snapshot = location && location.responseJson && typeof location.responseJson === 'object' ? location.responseJson : null; var width = Math.max(1, Math.round(Number(region && region.pixelWidth) || 1)); var height = Math.max(1, Math.round(Number(region && region.pixelHeight) || 1)); var scale = Number(region && region.canvasScale) || 1; var style = 'width:' + width + 'px;height:' + height + 'px;transform:scale(' + scale + ');transform-origin:top left;overflow:hidden;'; if (!location || !snapshot) return '
'; var current = snapshot.current || {}; if (value) { var weatherData = withWeatherUnits(snapshot, location); var fontSize = Math.max(8, Number(regionContent && regionContent.font_size || region && (region.font_size || region.fontSize) || 32) || 32); return '
' + renderEditorJsContent(substituteWeatherVariables(value, weatherData, regionContent.weather_icon_set_id)) + '
'; } var daily = snapshot.daily || {}; var days = (daily.time || []).slice(0, 7).map(function (day, index) { return '
' + escapeHtml(index === 0 ? 'Today' : String(day).slice(5)) + '' + escapeHtml(daily.temperature_2m_max && daily.temperature_2m_max[index] !== undefined ? daily.temperature_2m_max[index] + '°' : '-') + '
'; }).join(''); return '
' + escapeHtml(location.location_label || location.name) + '
' + escapeHtml(current.temperature_2m === undefined ? '-' : current.temperature_2m) + '°
' + days + '
'; } weatherRegistry.register('weather', { renderRegion: renderWeatherRegion });