(Install package: wiki-nation-panel-hover-fly-focus-textonly-20260705 / js/NationsPanel.js) |
(Install package: wiki-nation-panel-focus-inertia-button-sfx-20260705 / js/NationsPanel.js) |
||
| 817번째 줄: | 817번째 줄: | ||
function renderNationEmpty() { | function renderNationEmpty() { | ||
return '<span class="clbi-nations-era-wip-message"><span class="clbi-nations-era-wip-message-ko">작업 중...</span><span class="clbi-nations-era-wip-message-en">Working in Progress...</span></span>'; | return '<span class="clbi-nations-era-wip-message"><span class="clbi-nations-era-wip-message-ko">작업 중...</span><span class="clbi-nations-era-wip-message-en">Working in Progress...</span></span>'; | ||
} | |||
function playNationsPanelClickSound() { | |||
try { | |||
if (window && typeof window.playStaticSound === 'function') { | |||
window.playStaticSound(); | |||
} else if (typeof playStaticSound === 'function') { | |||
playStaticSound(); | |||
} | |||
} catch (err) {} | |||
} | } | ||
| 1,128번째 줄: | 1,138번째 줄: | ||
tab.addEventListener('click', function () { | tab.addEventListener('click', function () { | ||
playNationsPanelClickSound(); | |||
activate(tab.getAttribute('data-continent')); | activate(tab.getAttribute('data-continent')); | ||
}); | }); | ||
| 1,134번째 줄: | 1,145번째 줄: | ||
if (event.key === 'Enter' || event.key === ' ') { | if (event.key === 'Enter' || event.key === ' ') { | ||
event.preventDefault(); | event.preventDefault(); | ||
playNationsPanelClickSound(); | |||
activate(tab.getAttribute('data-continent')); | activate(tab.getAttribute('data-continent')); | ||
} | } | ||
| 1,173번째 줄: | 1,185번째 줄: | ||
tab.addEventListener('click', function () { | tab.addEventListener('click', function () { | ||
playNationsPanelClickSound(); | |||
activate(tab.getAttribute('data-year')); | activate(tab.getAttribute('data-year')); | ||
}); | }); | ||
| 1,179번째 줄: | 1,192번째 줄: | ||
if (event.key === 'Enter' || event.key === ' ') { | if (event.key === 'Enter' || event.key === ' ') { | ||
event.preventDefault(); | event.preventDefault(); | ||
playNationsPanelClickSound(); | |||
activate(tab.getAttribute('data-year')); | activate(tab.getAttribute('data-year')); | ||
} | } | ||
2026년 7월 6일 (월) 07:06 판
/* =========================================
COASTLINE: BLACK ICE - Nations Panel
국가 및 조합: 시대 전환 / 역사 연도 / 대륙 탭 제어
========================================= */
(function () {
'use strict';
var NATIONS_PANEL_BUILD = '20260705-mediawiki-file-thumb-render';
var DEFAULT_ERAS = [
'1950', '1960', '1970', '1980', '1990', '2000', '2010', '2020',
'2030', '2040', '2050', '2060', '2070', '2080', '2090', '2100'
];
function toArray(list) {
return Array.prototype.slice.call(list || []);
}
function unique(values) {
var seen = {};
var out = [];
values.forEach(function (value) {
value = String(value || '').trim();
if (!value || seen[value]) return;
seen[value] = true;
out.push(value);
});
return out;
}
function parseEraList(stack) {
var raw = stack ? stack.getAttribute('data-nations-era-years') : '';
var values = raw ? raw.split(/[\s,|]+/) : [];
values = unique(values.filter(function (value) {
return /^\d{4}$/.test(value);
}));
return values.length ? values : DEFAULT_ERAS.slice();
}
function getEraIndex(eras, era) {
var index = eras.indexOf(String(era || ''));
return index >= 0 ? index : 0;
}
function getWrappedEra(eras, index) {
if (!eras.length) return '';
index = ((index % eras.length) + eras.length) % eras.length;
return eras[index];
}
function setHidden(element, hidden) {
if (!element) return;
if (hidden) {
element.setAttribute('hidden', 'hidden');
element.setAttribute('aria-hidden', 'true');
element.classList.remove('is-active');
} else {
element.removeAttribute('hidden');
element.setAttribute('aria-hidden', 'false');
element.classList.add('is-active');
}
}
function setActiveButton(buttons, activeButton) {
buttons.forEach(function (button) {
var active = button === activeButton;
button.classList.toggle('is-active', active);
button.setAttribute('aria-selected', active ? 'true' : 'false');
button.setAttribute('tabindex', active ? '0' : '-1');
});
}
function activatePanelsByAttribute(panels, attrName, value) {
panels.forEach(function (panel) {
setHidden(panel, panel.getAttribute(attrName) !== value);
});
}
function replaceYearTemplate(template, era) {
return String(template || '').replace(/\{year\}/g, String(era || ''));
}
function readTemplate(root, attrName, fallback) {
if (!root) return fallback;
return root.getAttribute(attrName) || fallback;
}
function setAttributeFromTemplate(root, attrName, templateName, fallback, era) {
var template = readTemplate(root, templateName, fallback);
if (!template) {
root.removeAttribute(attrName);
return;
}
root.setAttribute(attrName, replaceYearTemplate(template, era));
}
function resetGlobeDom(globe) {
var instance;
if (!globe) return;
instance = globe.CLBI_NationsGlobeInstance || null;
if (instance && typeof instance.dispose === 'function') {
try { instance.dispose(); } catch (err) {}
}
globe.CLBI_NationsGlobeInstance = null;
globe.removeAttribute('data-nations-globe-ready');
globe.classList.remove('is-ready', 'has-error', 'is-dragging');
globe.innerHTML = '';
}
function reloadGlobe(globe) {
if (!globe) return;
if (window.CLBI_NationsGlobe && typeof window.CLBI_NationsGlobe.reload === 'function') {
window.CLBI_NationsGlobe.reload(globe);
return;
}
resetGlobeDom(globe);
if (window.CLBI_NationsGlobe && typeof window.CLBI_NationsGlobe.init === 'function') {
window.CLBI_NationsGlobe.init(globe.parentNode || document);
return;
}
window.setTimeout(function () {
if (window.CLBI_NationsGlobe && typeof window.CLBI_NationsGlobe.init === 'function') {
window.CLBI_NationsGlobe.init(globe.parentNode || document);
}
}, 0);
}
function applyGlobeEra(globe, era, reload) {
if (!globe || !era) return;
globe.setAttribute('data-era-active', era);
globe.setAttribute('data-era', replaceYearTemplate(
readTemplate(globe, 'data-era-readout-template', '{year} · CLBI BORDER LAYER'),
era
));
setAttributeFromTemplate(
globe,
'data-geojson-url',
'data-era-border-url-template',
'/index.php/Special:Redirect/file/{year}_Border_Lines.geojson',
era
);
setAttributeFromTemplate(
globe,
'data-polygon-overlay-url',
'data-era-polygon-overlay-url-template',
'/index.php/Special:Redirect/file/{year}_Polygon_Overlay.webp',
era
);
setAttributeFromTemplate(
globe,
'data-polygon-hit-url',
'data-era-polygon-hit-url-template',
'/index.php/Special:Redirect/file/{year}_Polygon_Hit.geojson',
era
);
setAttributeFromTemplate(
globe,
'data-nation-link-map-url',
'data-era-nation-link-map-url-template',
'/index.php?title=MediaWiki:{year}_Nation_Link_Map.json&action=raw&ctype=application/json',
era
);
setAttributeFromTemplate(
globe,
'data-lakes-overlay-url',
'data-era-lakes-overlay-url-template',
'/index.php/Special:Redirect/file/{year}_Lakes_Overlay.webp',
era
);
if (reload) {
reloadGlobe(globe);
}
}
var NATION_CONTINENT_FALLBACK = [
{ key: 'america', label: '아메리카', regions: ['북아메리카', '남아메리카'] },
{ key: 'europe', label: '유럽', regions: ['북유럽', '서유럽', '중앙유럽', '동유럽', '동남유럽', '남유럽', '남서유럽'] },
{ key: 'africa', label: '아프리카', regions: ['북아프리카', '서아프리카', '중앙아프리카', '동아프리카', '남아프리카'] },
{ key: 'asia', label: '아시아', regions: ['서아시아', '중앙아시아', '북아시아', '남아시아', '동아시아', '동남아시아'] },
{ key: 'oceania', label: '오세아니아', regions: ['오세아니아'] },
{ key: 'antarctica', label: '남극', regions: ['남극'] }
];
var nationListCache = {};
var nationLinkMapCache = {};
var nationRuntimeCacheBust = String(Date.now());
var nationResolvedFileUrlCache = {};
function addNationCacheBust(url) {
url = String(url || '').trim();
if (!url) return '';
if (/[?&]_clbiBust=/.test(url)) return url;
return url + (url.indexOf('?') >= 0 ? '&' : '?') + '_clbiBust=' + encodeURIComponent(nationRuntimeCacheBust);
}
function escapeHtml(value) {
return String(value == null ? '' : value)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
function encodeWikiTitle(title) {
return String(title || '')
.trim()
.replace(/ /g, '_')
.split('/')
.map(function (part) { return encodeURIComponent(part); })
.join('/');
}
function normalizeNationFile(value) {
var text = String(value || '').trim();
var titleMatch;
var redirectMatch;
var previous;
var i;
var j;
if (!text) return '';
text = text
.replace(/^\[\[:?\s*/i, '')
.replace(/\]\]$/i, '')
.trim();
for (i = 0; i < 8; i += 1) {
previous = text;
for (j = 0; j < 3; j += 1) {
try {
if (/%[0-9a-f]{2}/i.test(text)) {
text = decodeURIComponent(text);
}
} catch (err) {
break;
}
}
text = text.replace(/\\/g, '/').trim();
titleMatch = text.match(/[?&]title=([^&#]+)/i);
if (titleMatch) {
text = titleMatch[1];
continue;
}
text = text
.replace(/[?#].*$/g, '')
.replace(/^https?:\/\/[^/]+/i, '')
.replace(/^\/+/, '')
.replace(/^index\.php\/?/i, '')
.replace(/^wiki\/?/i, '')
.trim();
for (j = 0; j < 6; j += 1) {
var stripped = text
.replace(/^\s*파일\s*:/i, '')
.replace(/^\s*File\s*:/i, '')
.replace(/^\s*이미지\s*:/i, '')
.replace(/^\s*Image\s*:/i, '')
.replace(/^:+/, '')
.trim();
if (stripped === text) break;
text = stripped;
}
redirectMatch = text.match(/^(?:(?:Special|특수)\s*[:/]\s*)+(?:Redirect|넘겨주기)\s*\/\s*file\s*\/(.+)$/i) ||
text.match(/^(?:Redirect|넘겨주기)\s*\/\s*file\s*\/(.+)$/i) ||
text.match(/(?:^|\/)(?:(?:Special|특수)\s*[:/]\s*)+(?:Redirect|넘겨주기)\s*\/\s*file\s*\/(.+)$/i);
if (redirectMatch) {
text = redirectMatch[1].trim();
continue;
}
if (text === previous) break;
}
text = text.replace(/^\/+/, '').trim();
return text;
}
function normalizeNationFileKey(file) {
return normalizeNationFile(file).replace(/_/g, ' ').trim().toLowerCase();
}
function getWikiApiUrl(params) {
var query = [];
Object.keys(params || {}).forEach(function (key) {
if (params[key] == null) return;
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(String(params[key])));
});
return (window.mw && mw.util && mw.util.wikiScript ? mw.util.wikiScript('api') : '/api.php') + '?' + query.join('&');
}
function getWikiApiEndpoint() {
return (window.mw && mw.util && mw.util.wikiScript ? mw.util.wikiScript('api') : '/api.php');
}
function fetchWikiApi(params) {
var body;
try {
body = new URLSearchParams();
Object.keys(params || {}).forEach(function (key) {
if (params[key] == null) return;
body.append(key, String(params[key]));
});
return fetch(getWikiApiEndpoint(), {
method: 'POST',
credentials: 'same-origin',
cache: 'no-store',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
body: body.toString()
}).then(function (res) {
if (!res.ok) throw new Error('wiki api failed: ' + res.status);
return res.json();
});
} catch (err) {
return fetch(getWikiApiUrl(params), { credentials: 'same-origin', cache: 'no-store' }).then(function (res) {
if (!res.ok) throw new Error('wiki api failed: ' + res.status);
return res.json();
});
}
}
function buildNationFileUrl(file) {
var clean = normalizeNationFile(file);
var key = normalizeNationFileKey(clean);
var resolved;
if (!clean || !key) return '';
/*
Render nation-list flags through MediaWiki's own file thumbnail pipeline.
This mirrors [[파일:Name.svg|16px]] far more closely than using the raw
SVG URL or Special:Redirect/file path directly. If MediaWiki cannot
resolve the file title, return an empty URL and hide the flag slot.
*/
resolved = nationResolvedFileUrlCache[key];
return resolved ? addNationCacheBust(resolved) : '';
}
function collectNationFlagFileNames(data) {
var files = [];
function addFlag(flag) {
var file = normalizeNationFile(flag && (flag.file || flag.flag_file || flag.flag || flag.flag_title || flag));
if (file) files.push(file);
}
function scanItems(items) {
(items || []).forEach(function (item) {
if (!item || typeof item !== 'object') return;
if (Array.isArray(item.flags)) item.flags.forEach(addFlag);
addFlag(item.flag_file || item.flag || item.flag_title || '');
});
}
(data && data.continents || []).forEach(function (continent) {
(continent.regions || []).forEach(function (region) {
scanItems(region.items || []);
});
});
return unique(files);
}
function resolveNationFlagFileUrls(files) {
var cleanFiles = unique((files || []).map(normalizeNationFile).filter(Boolean));
var pending = cleanFiles.filter(function (file) {
var key = normalizeNationFileKey(file);
return key && nationResolvedFileUrlCache[key] === undefined;
});
var chunks = [];
while (pending.length) chunks.push(pending.splice(0, 20));
if (!chunks.length) return Promise.resolve(nationResolvedFileUrlCache);
return Promise.all(chunks.map(function (chunk) {
var titleToKey = {};
var titles = [];
chunk.forEach(function (file) {
var key = normalizeNationFileKey(file);
var canonical = 'File:' + file;
var local = '파일:' + file;
if (!key) return;
titleToKey[normalizeNationFileKey(canonical)] = key;
titleToKey[normalizeNationFileKey(local)] = key;
titles.push(canonical);
titles.push(local);
});
return fetchWikiApi({
action: 'query',
format: 'json',
formatversion: '2',
redirects: '1',
prop: 'imageinfo',
iiprop: 'url',
iiurlwidth: '16',
titles: titles.join('|')
}).then(function (json) {
var pages = (json && json.query && json.query.pages) || [];
var seen = {};
pages.forEach(function (page) {
var file = normalizeNationFile(page && page.title);
var pageKey = normalizeNationFileKey(file);
var originalKey = titleToKey[pageKey] || pageKey;
var imageinfo = page && page.imageinfo && page.imageinfo[0];
if (!originalKey) return;
seen[originalKey] = true;
if (imageinfo && (imageinfo.thumburl || imageinfo.url)) {
nationResolvedFileUrlCache[originalKey] = imageinfo.thumburl || imageinfo.url;
if (pageKey) nationResolvedFileUrlCache[pageKey] = imageinfo.thumburl || imageinfo.url;
} else if (nationResolvedFileUrlCache[originalKey] === undefined) {
nationResolvedFileUrlCache[originalKey] = '';
}
});
chunk.forEach(function (file) {
var key = normalizeNationFileKey(file);
if (key && !seen[key] && nationResolvedFileUrlCache[key] === undefined) {
nationResolvedFileUrlCache[key] = '';
}
});
}).catch(function () {
chunk.forEach(function (file) {
var key = normalizeNationFileKey(file);
if (key && nationResolvedFileUrlCache[key] === undefined) nationResolvedFileUrlCache[key] = '';
});
});
})).then(function () {
return nationResolvedFileUrlCache;
});
}
function isLegacyNationIndexFileUrl(src) {
src = String(src || '');
if (!src) return false;
if (!/\.svg(?:[?#]|$)/i.test(src)) return false;
if (/\/images\//i.test(src)) return false;
return /(?:Special|%ED%8A%B9%EC%88%98|특수).*?(?:Redirect|%EB%84%98%EA%B2%A8%EC%A3%BC%EA%B8%B0|넘겨주기).*?file/i.test(src) || /\/index\.php\//i.test(src);
}
function purgeLegacyNationIndexFileImages(scope) {
var root = scope || document;
toArray(root.querySelectorAll ? root.querySelectorAll('.clbi-nations-tabpanel-body img, .clbi-nations-tabpanel img') : []).forEach(function (img) {
var src = img.currentSrc || img.getAttribute('src') || '';
if (!isLegacyNationIndexFileUrl(src)) return;
img.removeAttribute('src');
img.setAttribute('data-clbi-legacy-src-removed', src);
});
}
function getNationFlagOffsetY(flag) {
var value;
if (!flag || typeof flag !== 'object') return 0;
value = flag.offsetY;
if (value == null) value = flag.offset_y;
if (value == null) value = flag.flagOffsetY;
if (value == null && flag.decorator === 'top') value = -1;
value = parseFloat(value);
if (!isFinite(value)) value = 0;
return Math.max(-3, Math.min(3, Math.round(value)));
}
function buildNationPageUrl(page) {
page = String(page || '').trim();
return page ? '/index.php/' + encodeWikiTitle(page) : '';
}
function getPanelEra(panel) {
var eraPanel = panel && panel.closest ? panel.closest('.clbi-nations-era-content[data-era-content]') : null;
var stack = panel && panel.closest ? panel.closest('.clbi-nations-panel-stack') : null;
return (eraPanel && eraPanel.getAttribute('data-era-content')) ||
(panel && panel.getAttribute('data-era')) ||
(stack && (stack.getAttribute('data-nations-current-era') || stack.getAttribute('data-era'))) ||
'1950';
}
function getNationListUrl(panel, era) {
var stack = panel && panel.closest ? panel.closest('.clbi-nations-panel-stack') : null;
var template = (panel && panel.getAttribute('data-nation-list-url-template')) ||
(stack && stack.getAttribute('data-nation-list-url-template')) ||
'/index.php?title=MediaWiki:{year}_Nation_List.json&action=raw&ctype=application/json';
return (panel && panel.getAttribute('data-nation-list-url')) || replaceYearTemplate(template, era);
}
function getNationLinkMapUrl(panel, era) {
var stack = panel && panel.closest ? panel.closest('.clbi-nations-panel-stack') : null;
var template = (panel && panel.getAttribute('data-nation-link-map-url-template')) ||
(stack && stack.getAttribute('data-nation-link-map-url-template')) ||
'/index.php?title=MediaWiki:{year}_Nation_Link_Map.json&action=raw&ctype=application/json';
return (panel && panel.getAttribute('data-nation-link-map-url')) || replaceYearTemplate(template, era);
}
function normalizeNationTag(value) {
value = String(value == null ? '' : value).trim().toUpperCase();
return /^[A-Z0-9]{3}$/.test(value) ? value : '';
}
function normalizeLookupKey(value) {
return String(value == null ? '' : value)
.trim()
.replace(/_/g, ' ')
.replace(/\s+/g, ' ')
.toLowerCase();
}
function getNationItemTag(item) {
if (!item || typeof item !== 'object') return '';
return normalizeNationTag(item.tag || item.code || item.map_tag || item.mapTag || '');
}
function collectNationItemFlags(item) {
var flags = [];
if (!item || typeof item !== 'object') return flags;
if (Array.isArray(item.flags)) {
item.flags.forEach(function (flag) {
if (!flag) return;
if (typeof flag === 'string') {
flag = { file: flag };
}
if (typeof flag !== 'object') return;
if (normalizeNationFile(flag.file || flag.flag_file || flag.flag || '')) {
flags.push(flag);
}
});
}
if (!flags.length && (item.flag_file || item.flag || item.flag_title)) {
flags.push({
file: item.flag_file || item.flag || item.flag_title,
width: item.flag_width || '16px',
border: item.border !== false,
offsetMode: item.offsetMode || item.offset_mode || 'auto',
offsetY: item.offsetY || item.offset_y || 0
});
}
return flags;
}
function normalizeNationLinkMap(payload) {
var source = payload && payload.items ? payload.items : {};
var index = { byTag: {}, byPage: {}, byLabel: {} };
Object.keys(source || {}).forEach(function (key) {
var entry = source[key];
var tag;
var pageKey;
var labelKey;
if (!entry || typeof entry !== 'object') return;
tag = normalizeNationTag(entry.tag || key || entry.page || '');
pageKey = normalizeLookupKey(entry.wiki_title || entry.page_title || entry.title || '');
labelKey = normalizeLookupKey(entry.name_ko || entry.label || entry.page_name || '');
if (tag && !index.byTag[tag]) index.byTag[tag] = entry;
if (pageKey && !index.byPage[pageKey]) index.byPage[pageKey] = entry;
if (labelKey && !index.byLabel[labelKey]) index.byLabel[labelKey] = entry;
});
return index;
}
function fetchNationLinkMap(panel, era) {
var url = getNationLinkMapUrl(panel, era);
var cacheKey = era + '|' + url;
if (nationLinkMapCache[cacheKey]) return nationLinkMapCache[cacheKey];
nationLinkMapCache[cacheKey] = fetch(addNationCacheBust(url), { credentials: 'same-origin', cache: 'no-store' })
.then(function (res) {
if (!res.ok) throw new Error('HTTP ' + res.status);
return res.text();
})
.then(function (text) {
var trimmed = String(text || '').trim();
if (!trimmed) throw new Error('empty nation link map');
return normalizeNationLinkMap(JSON.parse(trimmed));
})
.catch(function () {
return normalizeNationLinkMap(null);
});
return nationLinkMapCache[cacheKey];
}
function findNationLinkEntryForItem(item, index) {
var tag;
var pageKey;
var labelKey;
if (!item || !index) return null;
tag = getNationItemTag(item);
if (tag && index.byTag && index.byTag[tag]) return index.byTag[tag];
pageKey = normalizeLookupKey(item.page || item.wiki_title || '');
if (pageKey && index.byPage && index.byPage[pageKey]) return index.byPage[pageKey];
labelKey = normalizeLookupKey(item.label || item.name || item.name_ko || '');
if (labelKey && index.byLabel && index.byLabel[labelKey]) return index.byLabel[labelKey];
return null;
}
function applyNationLinkMapFlagFallback(data, linkMapIndex) {
if (!data || !Array.isArray(data.continents)) return data;
data.continents.forEach(function (continent) {
(continent.regions || []).forEach(function (region) {
(region.items || []).forEach(function (item) {
var entry;
var file;
if (!item || collectNationItemFlags(item).length) return;
entry = findNationLinkEntryForItem(item, linkMapIndex);
file = entry ? normalizeNationFile(entry.flag_file || entry.flag || entry.flag_title || '') : '';
if (!file) return;
item.flags = [{
file: file,
width: '16px',
border: true,
offsetMode: 'auto',
offsetY: 0,
source: 'Nation_Link_Map'
}];
});
});
});
return data;
}
function getNationListFallback() {
return {
version: 1,
year: 1950,
continents: NATION_CONTINENT_FALLBACK.map(function (continent) {
return {
key: continent.key,
label: continent.label,
regions: continent.regions.map(function (region) {
return { key: region, label: region, items: [] };
})
};
})
};
}
function normalizeNationList(payload, era) {
var fallback = getNationListFallback();
var sourceContinents = payload && Array.isArray(payload.continents) ? payload.continents : [];
var sourceByKey = {};
sourceContinents.forEach(function (continent) {
if (continent && continent.key) sourceByKey[continent.key] = continent;
});
return {
version: payload && payload.version ? payload.version : 1,
year: payload && payload.year ? payload.year : parseInt(era || '1950', 10),
description: payload && payload.description ? payload.description : '',
continents: fallback.continents.map(function (base) {
var source = sourceByKey[base.key] || {};
var regionsByLabel = {};
if (Array.isArray(source.regions)) {
source.regions.forEach(function (region) {
if (!region) return;
if (region.key) regionsByLabel[region.key] = region;
if (region.label) regionsByLabel[region.label] = region;
});
}
return {
key: base.key,
label: source.label || base.label,
regions: base.regions.map(function (baseRegion) {
var region = regionsByLabel[baseRegion.key] || regionsByLabel[baseRegion.label] || baseRegion;
return {
key: region.key || baseRegion.key,
label: region.label || baseRegion.label,
items: Array.isArray(region.items) ? region.items.filter(function (item) {
return item && item.enabled !== false;
}) : []
};
})
};
})
};
}
function fetchNationList(panel, era) {
var url = getNationListUrl(panel, era);
var cacheKey = era + '|' + url;
if (nationListCache[cacheKey]) return nationListCache[cacheKey];
nationListCache[cacheKey] = fetch(addNationCacheBust(url), { credentials: 'same-origin', cache: 'no-store' })
.then(function (res) {
if (!res.ok) throw new Error('HTTP ' + res.status);
return res.text();
})
.then(function (text) {
var trimmed = String(text || '').trim();
if (!trimmed) throw new Error('empty nation list');
return normalizeNationList(JSON.parse(trimmed), era);
});
return nationListCache[cacheKey];
}
function normalizeNationFlagMaxWidth(value) {
var raw = String(value || '').trim();
var match = raw.match(/^(\d+(?:\.\d+)?)\s*(px)?$/i);
var n = match ? parseFloat(match[1]) : 16;
if (!isFinite(n)) n = 16;
if (n < 8) n = 8;
if (n > 32) n = 32;
return Math.round(n * 100) / 100 + 'px';
}
function renderNationFlag(flag) {
var file;
var url;
var width;
var classes;
var offsetY;
if (!flag) return '';
file = normalizeNationFile(flag.file || flag.flag_file || flag.flag || '');
if (!file) return '';
url = buildNationFileUrl(file);
width = normalizeNationFlagMaxWidth(flag.width || flag.flag_width || '24px');
offsetY = getNationFlagOffsetY(flag);
classes = 'clbi-nations-list-flag' + (flag.border !== false ? ' has-border' : '');
if (!url) {
return '<span class="clbi-nations-list-flag-slot is-missing" style="--flag-max-w:' + escapeHtml(width) + ';--flag-y:' + offsetY + 'px;" data-flag-file="' + escapeHtml(file) + '" title="국기 파일 URL 미확인: ' + escapeHtml(file) + '"></span>';
}
return '<span class="clbi-nations-list-flag-slot" style="--flag-max-w:' + escapeHtml(width) + ';--flag-y:' + offsetY + 'px;" data-flag-file="' + escapeHtml(file) + '">' +
'<img class="' + classes + '" src="' + escapeHtml(url) + '" alt="" decoding="async">' +
'</span>';
}
function bindNationFlagFallbacks(scope) {
var root = scope || document;
toArray(root.querySelectorAll('.clbi-nations-list-flag-slot .clbi-nations-list-flag')).forEach(function (img) {
if (img.getAttribute('data-flag-missing-handler') === '1') return;
img.setAttribute('data-flag-missing-handler', '1');
img.addEventListener('error', function () {
var slot = img.closest ? img.closest('.clbi-nations-list-flag-slot') : null;
if (slot) {
slot.classList.add('is-missing');
slot.setAttribute('title', '국기 파일 로드 실패: ' + (slot.getAttribute('data-flag-file') || ''));
}
img.removeAttribute('src');
});
});
}
function renderNationItem(item, index, items) {
var flags = collectNationItemFlags(item);
var flagHtml = flags.map(renderNationFlag).join('');
var label = item.label || item.name || item.name_ko || item.page || item.external_url || '미지정';
var href = item.external_url || buildNationPageUrl(item.page || item.wiki_title || '');
var tag = String(item.tag || item.code || item.page_tag || '').trim();
var page = String(item.page || item.wiki_title || '').trim();
var linkHtml = href ? '<a class="clbi-nations-list-link" href="' + escapeHtml(href) + '">' + escapeHtml(label) + '</a>' : '<span class="clbi-nations-list-label">' + escapeHtml(label) + '</span>';
var divider = index < items.length - 1 ? '<span class="clbi-nations-list-divider">·</span>' : '';
return '<span class="clbi-nations-list-item" data-nation-tag="' + escapeHtml(tag) + '" data-nation-page="' + escapeHtml(page) + '" data-nation-label="' + escapeHtml(label) + '">' + flagHtml + linkHtml + '</span>' + divider;
}
function renderNationEmpty() {
return '<span class="clbi-nations-era-wip-message"><span class="clbi-nations-era-wip-message-ko">작업 중...</span><span class="clbi-nations-era-wip-message-en">Working in Progress...</span></span>';
}
function playNationsPanelClickSound() {
try {
if (window && typeof window.playStaticSound === 'function') {
window.playStaticSound();
} else if (typeof playStaticSound === 'function') {
playStaticSound();
}
} catch (err) {}
}
function getNationItemFromEventTarget(target, panel) {
var item = target && target.closest ? target.closest('.clbi-nations-list-item[data-nation-tag]') : null;
if (!item || !panel || !panel.contains(item)) return null;
return item;
}
function getGlobeInstanceForNationItem(item) {
var stack = item && item.closest ? item.closest('.clbi-nations-panel-stack') : null;
var globe = stack && stack.querySelector ? stack.querySelector('.clbi-nations-globe-window[data-nations-globe], .clbi-nations-globe-window') : null;
var instance = globe && globe.CLBI_NationsGlobeInstance ? globe.CLBI_NationsGlobeInstance : null;
if (instance && typeof instance.focusNationByPage === 'function') return instance;
if (window.CLBI_NationsGlobe && typeof window.CLBI_NationsGlobe.init === 'function' && stack) {
window.CLBI_NationsGlobe.init(stack);
instance = globe && globe.CLBI_NationsGlobeInstance ? globe.CLBI_NationsGlobeInstance : null;
}
return instance && typeof instance.focusNationByPage === 'function' ? instance : null;
}
function clearNationPanelHoverState(panel, except) {
if (!panel || !panel.querySelectorAll) return;
toArray(panel.querySelectorAll('.clbi-nations-list-item.is-panel-hovered')).forEach(function (item) {
if (item !== except) item.classList.remove('is-panel-hovered');
});
}
function requestNationItemGlobeFocus(panel, item, immediate) {
var tag;
var instance;
var timer;
if (!panel || !item) return;
tag = String(item.getAttribute('data-nation-tag') || '').trim();
if (!tag) return;
clearNationPanelHoverState(panel, item);
item.classList.add('is-panel-hovered');
timer = panel.CLBI_NationHoverFocusTimer || null;
if (timer) window.clearTimeout(timer);
panel.CLBI_NationHoverFocusTimer = window.setTimeout(function () {
panel.CLBI_NationHoverFocusTimer = null;
if (!document.body.contains(item) || !item.classList.contains('is-panel-hovered')) return;
instance = getGlobeInstanceForNationItem(item);
if (instance && typeof instance.focusNationByPage === 'function') {
instance.focusNationByPage(tag, {
source: 'nation-panel',
label: item.getAttribute('data-nation-label') || '',
duration: immediate ? 360 : null
});
}
}, immediate ? 0 : 75);
}
function clearNationItemGlobeFocus(panel, item) {
var tag;
var instance;
var timer;
if (!panel || !item) return;
tag = String(item.getAttribute('data-nation-tag') || '').trim();
item.classList.remove('is-panel-hovered');
timer = panel.CLBI_NationHoverFocusTimer || null;
if (timer) {
window.clearTimeout(timer);
panel.CLBI_NationHoverFocusTimer = null;
}
if (!tag) return;
instance = getGlobeInstanceForNationItem(item);
if (instance && typeof instance.clearPanelNationFocus === 'function') {
instance.clearPanelNationFocus(tag);
}
}
function bindNationListHoverFocus(panel) {
if (!panel || panel.getAttribute('data-nation-panel-hover-focus-ready') === '1') return;
panel.setAttribute('data-nation-panel-hover-focus-ready', '1');
panel.addEventListener('mouseover', function (event) {
var item = getNationItemFromEventTarget(event.target, panel);
if (!item) return;
if (event.relatedTarget && item.contains(event.relatedTarget)) return;
requestNationItemGlobeFocus(panel, item, false);
});
panel.addEventListener('mouseout', function (event) {
var item = getNationItemFromEventTarget(event.target, panel);
if (!item) return;
if (event.relatedTarget && item.contains(event.relatedTarget)) return;
clearNationItemGlobeFocus(panel, item);
});
panel.addEventListener('focusin', function (event) {
var item = getNationItemFromEventTarget(event.target, panel);
if (item) requestNationItemGlobeFocus(panel, item, true);
});
panel.addEventListener('focusout', function (event) {
var item = getNationItemFromEventTarget(event.target, panel);
if (item) clearNationItemGlobeFocus(panel, item);
});
}
function buildNationTabSkeletonHtml(extraClass) {
var tabs = NATION_CONTINENT_FALLBACK.map(function (continent, index) {
var active = index === 0;
return '<span class="clbi-nations-tabpanel-tab' + (active ? ' is-active' : '') + '" role="tab" tabindex="' + (active ? '0' : '-1') + '" aria-selected="' + (active ? 'true' : 'false') + '" data-continent="' + escapeHtml(continent.key) + '">' + escapeHtml(continent.label) + '</span>';
}).join('');
var bodies = NATION_CONTINENT_FALLBACK.map(function (continent, index) {
var rows = continent.regions.map(function (region) {
return '<div class="clbi-nations-tabpanel-row">' +
'<div class="clbi-nations-tabpanel-region">' + escapeHtml(region) + '</div>' +
'<div class="clbi-nations-tabpanel-well">' + renderNationEmpty() + '</div>' +
'</div>';
}).join('');
return '<div class="clbi-nations-tabpanel-continent' + (index === 0 ? ' is-active' : '') + '" data-continent-panel="' + escapeHtml(continent.key) + '"' + (index === 0 ? '' : ' hidden="hidden"') + '>' + rows + '</div>';
}).join('');
return '<div class="clbi-nations-tabpanel' + (extraClass ? ' ' + extraClass : '') + '" data-clbi-nations-simple data-nation-list-source="1">' +
'<div class="clbi-nations-tabpanel-tabs" role="tablist" aria-label="대륙 선택">' +
tabs +
'<span class="clbi-nations-tabpanel-title" aria-hidden="true">당대 존재 국가</span>' +
'</div>' +
'<div class="clbi-nations-tabpanel-body">' + bodies + '</div>' +
'</div>';
}
function buildHistoryPanelSkeletonHtml(era) {
var start = parseInt(era || '1950', 10);
var years = [];
if (!isFinite(start)) start = 1950;
for (var year = start; year < start + 10; year += 1) {
years.push(String(year));
}
var pages = years.map(function (year, index) {
return '<div class="clbi-nations-history-list clbi-nations-history-page' + (index === 0 ? ' is-active' : '') + '" data-year-panel="' + escapeHtml(year) + '"' + (index === 0 ? '' : ' hidden="hidden"') + '>' +
'<div class="clbi-nations-history-empty"><span class="clbi-nations-history-empty-ko">작업 중...</span><span class="clbi-nations-history-empty-en">Working in Progress...</span></div>' +
'</div>';
}).join('');
var tabs = years.map(function (year, index) {
return '<span class="clbi-nations-history-year-button' + (index === 0 ? ' is-active' : '') + '" role="tab" tabindex="' + (index === 0 ? '0' : '-1') + '" aria-selected="' + (index === 0 ? 'true' : 'false') + '" data-year="' + escapeHtml(year) + '">' + escapeHtml(year) + '</span>';
}).join('');
return '<div class="clbi-nations-forces-panel clbi-nations-module-panel clbi-nations-history-panel">' +
'<div class="clbi-nations-module-title">역사적 사건</div>' +
'<div class="clbi-nations-module-body clbi-nations-history-body">' +
'<div class="clbi-nations-history-pages">' + pages + '</div>' +
'<div class="clbi-nations-history-year-well"><div class="clbi-nations-history-year-list" data-decade-only="1" role="tablist" aria-label="역사적 사건 연도 선택">' + tabs + '</div></div>' +
'</div>' +
'</div>';
}
function buildEraContentSkeletonHtml(era) {
return '<div class="clbi-nations-era-content clbi-nations-era-wip" data-era-content="' + escapeHtml(era) + '" hidden="hidden">' +
buildHistoryPanelSkeletonHtml(era) +
buildNationTabSkeletonHtml('clbi-nations-era-wip-tabpanel') +
'</div>';
}
function ensureEraContentPanels(stack, eras) {
var insertAfter;
if (!stack || !eras || !eras.length) return;
insertAfter = toArray(stack.querySelectorAll('.clbi-nations-era-content[data-era-content]')).pop() || stack.querySelector('.clbi-nations-map-row');
eras.forEach(function (era) {
var selector = '.clbi-nations-era-content[data-era-content="' + String(era).replace(/"/g, '\\"') + '"]';
var wrapper;
var panel;
if (stack.querySelector(selector)) return;
wrapper = document.createElement('div');
wrapper.innerHTML = buildEraContentSkeletonHtml(era);
panel = wrapper.firstElementChild;
if (!panel) return;
if (insertAfter && insertAfter.parentNode) {
insertAfter.parentNode.insertBefore(panel, insertAfter.nextSibling);
} else {
stack.appendChild(panel);
}
insertAfter = panel;
});
}
function renderNationContinent(continent, activeKey) {
var rows = (continent.regions || []).map(function (region) {
var items = Array.isArray(region.items) ? region.items : [];
var content = items.length ? items.map(function (item, index) {
return renderNationItem(item, index, items);
}).join(' ') : renderNationEmpty();
return '' +
'<div class="clbi-nations-tabpanel-row">' +
'<div class="clbi-nations-tabpanel-region">' + escapeHtml(region.label || region.key || '') + '</div>' +
'<div class="clbi-nations-tabpanel-well">' + content + '</div>' +
'</div>';
}).join('');
return '<div class="clbi-nations-tabpanel-continent' + (continent.key === activeKey ? ' is-active' : '') + '" data-continent-panel="' + escapeHtml(continent.key) + '"' + (continent.key === activeKey ? '' : ' hidden="hidden"') + '>' + rows + '</div>';
}
function renderNationListPanel(panel, data) {
var body = panel.querySelector('.clbi-nations-tabpanel-body');
var activeTab = panel.querySelector('.clbi-nations-tabpanel-tab.is-active[data-continent], .clbi-nations-tabpanel-tab[aria-selected="true"][data-continent]');
var activeKey = activeTab ? activeTab.getAttribute('data-continent') : '';
var continents = data && Array.isArray(data.continents) ? data.continents : [];
if (!body || !continents.length) return;
if (!activeKey) activeKey = continents[0].key;
body.innerHTML = continents.map(function (continent) {
return renderNationContinent(continent, activeKey);
}).join('');
bindNationFlagFallbacks(body);
bindNationListHoverFocus(panel);
panel.classList.add('clbi-nations-list-json-ready');
panel.setAttribute('data-nation-list-year-loaded', String(data.year || getPanelEra(panel)));
}
function isNationListPanelHidden(panel) {
var node = panel;
while (node && node !== document && node.nodeType === 1) {
if (node.hasAttribute('hidden') || node.getAttribute('aria-hidden') === 'true') return true;
node = node.parentElement;
}
return false;
}
function initNationListPanel(panel) {
var era;
if (!panel || panel.getAttribute('data-nation-list-source') !== '1') return;
if (isNationListPanelHidden(panel)) return;
if (panel.getAttribute('data-nation-list-loading') === '1') return;
if (panel.getAttribute('data-nation-list-year-loaded') === getPanelEra(panel)) return;
era = getPanelEra(panel);
purgeLegacyNationIndexFileImages(panel);
panel.setAttribute('data-nation-list-loading', '1');
Promise.all([
fetchNationList(panel, era),
fetchNationLinkMap(panel, era)
]).then(function (results) {
var data = applyNationLinkMapFlagFallback(results[0], results[1]);
return resolveNationFlagFileUrls(collectNationFlagFileNames(data)).then(function () {
renderNationListPanel(panel, data);
});
}).catch(function () {
panel.classList.add('clbi-nations-list-json-fallback');
}).finally(function () {
panel.removeAttribute('data-nation-list-loading');
});
}
function initContinentPanel(panel) {
var tabs;
var bodies;
if (!panel) return;
bindNationListHoverFocus(panel);
if (panel.getAttribute('data-nations-tabpanel-ready') === '1') return;
panel.setAttribute('data-nations-tabpanel-ready', '1');
tabs = toArray(panel.querySelectorAll('.clbi-nations-tabpanel-tab[data-continent]'));
bodies = toArray(panel.querySelectorAll('.clbi-nations-tabpanel-continent[data-continent-panel]'));
function activate(continent) {
var activeTab = null;
tabs.forEach(function (tab) {
if (tab.getAttribute('data-continent') === continent) activeTab = tab;
});
if (!activeTab && tabs.length) {
activeTab = tabs[0];
continent = activeTab.getAttribute('data-continent');
}
setActiveButton(tabs, activeTab);
activatePanelsByAttribute(toArray(panel.querySelectorAll('.clbi-nations-tabpanel-continent[data-continent-panel]')), 'data-continent-panel', continent);
}
tabs.forEach(function (tab) {
tab.setAttribute('role', 'tab');
tab.setAttribute('tabindex', tab.classList.contains('is-active') ? '0' : '-1');
tab.addEventListener('click', function () {
playNationsPanelClickSound();
activate(tab.getAttribute('data-continent'));
});
tab.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
playNationsPanelClickSound();
activate(tab.getAttribute('data-continent'));
}
});
});
activate((panel.querySelector('.clbi-nations-tabpanel-tab.is-active[data-continent]') || tabs[0] || {}).getAttribute && (panel.querySelector('.clbi-nations-tabpanel-tab.is-active[data-continent]') || tabs[0]).getAttribute('data-continent'));
}
function initHistoryYearPanel(panel) {
var tabs;
var pages;
if (!panel || panel.getAttribute('data-nations-history-ready') === '1') return;
panel.setAttribute('data-nations-history-ready', '1');
tabs = toArray(panel.querySelectorAll('.clbi-nations-history-year-button[data-year]'));
pages = toArray(panel.querySelectorAll('.clbi-nations-history-page[data-year-panel]'));
function activate(year) {
var activeTab = null;
tabs.forEach(function (tab) {
if (tab.getAttribute('data-year') === year) activeTab = tab;
});
if (!activeTab && tabs.length) {
activeTab = tabs[0];
year = activeTab.getAttribute('data-year');
}
setActiveButton(tabs, activeTab);
activatePanelsByAttribute(pages, 'data-year-panel', year);
}
tabs.forEach(function (tab) {
tab.setAttribute('role', 'tab');
tab.setAttribute('tabindex', tab.classList.contains('is-active') ? '0' : '-1');
tab.addEventListener('click', function () {
playNationsPanelClickSound();
activate(tab.getAttribute('data-year'));
});
tab.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
playNationsPanelClickSound();
activate(tab.getAttribute('data-year'));
}
});
});
activate((panel.querySelector('.clbi-nations-history-year-button.is-active[data-year]') || tabs[0] || {}).getAttribute && (panel.querySelector('.clbi-nations-history-year-button.is-active[data-year]') || tabs[0]).getAttribute('data-year'));
}
function initEraStack(stack) {
var eras;
var titleNode;
var titlePlates;
var contentPanels;
var leftButton;
var rightButton;
var globe;
var currentEra;
if (!stack || stack.getAttribute('data-nations-era-controller-ready') === '1') return;
stack.setAttribute('data-nations-era-controller-ready', '1');
eras = parseEraList(stack);
ensureEraContentPanels(stack, eras);
titleNode = stack.querySelector('[data-nations-era-title]');
titlePlates = toArray(stack.querySelectorAll('.clbi-nations-era-title-plate[data-era]'));
contentPanels = toArray(stack.querySelectorAll('.clbi-nations-era-content[data-era-content]'));
leftButton = stack.querySelector('[data-nations-era-move="prev"], .clbi-nations-era-side-button-left');
rightButton = stack.querySelector('[data-nations-era-move="next"], .clbi-nations-era-side-button-right');
globe = stack.querySelector('.clbi-nations-globe-window');
currentEra = stack.getAttribute('data-nations-current-era') || stack.getAttribute('data-era') || eras[0];
function setEra(era, options) {
var index;
var prevEra;
var nextEra;
var reload;
options = options || {};
era = String(era || eras[0]);
index = getEraIndex(eras, era);
era = eras[index];
prevEra = getWrappedEra(eras, index - 1);
nextEra = getWrappedEra(eras, index + 1);
reload = !!options.reloadGlobe;
stack.setAttribute('data-nations-current-era', era);
stack.setAttribute('data-era', era);
if (titleNode) {
titleNode.textContent = era + '년';
titleNode.setAttribute('data-era', era);
}
titlePlates.forEach(function (plate) {
setHidden(plate, plate.getAttribute('data-era') !== era);
});
if (leftButton) {
leftButton.setAttribute('data-target-era', prevEra);
leftButton.setAttribute('title', prevEra + '년으로 이동');
leftButton.setAttribute('aria-label', prevEra + '년으로 이동');
}
if (rightButton) {
rightButton.setAttribute('data-target-era', nextEra);
rightButton.setAttribute('title', nextEra + '년으로 이동');
rightButton.setAttribute('aria-label', nextEra + '년으로 이동');
}
contentPanels.forEach(function (panel) {
var inactive = panel.getAttribute('data-era-content') !== era;
setHidden(panel, inactive);
if (!inactive) {
toArray(panel.querySelectorAll('.clbi-nations-tabpanel')).forEach(initNationListPanel);
}
});
applyGlobeEra(globe, era, reload);
}
function move(direction) {
var active = stack.getAttribute('data-nations-current-era') || currentEra || eras[0];
var index = getEraIndex(eras, active);
var target = getWrappedEra(eras, index + direction);
if (!target) return false;
setEra(target, { reloadGlobe: true });
return true;
}
if (leftButton) {
leftButton.addEventListener('click', function (event) {
event.preventDefault();
move(-1);
});
}
if (rightButton) {
rightButton.addEventListener('click', function (event) {
event.preventDefault();
move(1);
});
}
stack.CLBI_NationsEraController = {
eras: eras.slice(),
setEra: function (era) { setEra(era, { reloadGlobe: true }); },
move: move
};
setEra(currentEra, { reloadGlobe: false });
}
function init(root) {
var scope = root && root.querySelectorAll ? root : document;
purgeLegacyNationIndexFileImages(scope);
toArray(scope.querySelectorAll('.clbi-nations-panel-stack')).forEach(initEraStack);
toArray(scope.querySelectorAll('.clbi-nations-tabpanel')).forEach(initContinentPanel);
toArray(scope.querySelectorAll('.clbi-nations-history-panel')).forEach(initHistoryYearPanel);
toArray(scope.querySelectorAll('.clbi-nations-tabpanel')).forEach(initNationListPanel);
}
function findEraStack() {
return document.querySelector('.clbi-nations-panel-stack');
}
function moveEra(direction) {
var stack = findEraStack();
if (!stack || !stack.CLBI_NationsEraController) return false;
return stack.CLBI_NationsEraController.move(direction);
}
function setEra(era) {
var stack = findEraStack();
if (!stack || !stack.CLBI_NationsEraController) return false;
stack.CLBI_NationsEraController.setEra(era);
return true;
}
function refresh(root) {
var scope = root && root.querySelectorAll ? root : document;
nationRuntimeCacheBust = String(Date.now());
nationListCache = {};
nationLinkMapCache = {};
toArray(scope.querySelectorAll('.clbi-nations-tabpanel[data-nation-list-source="1"]')).forEach(function (panel) {
panel.removeAttribute('data-nation-list-loading');
panel.removeAttribute('data-nation-list-year-loaded');
panel.classList.remove('clbi-nations-list-json-ready', 'clbi-nations-list-json-fallback');
});
init(scope);
}
function diagnostics() {
var flags = toArray(document.querySelectorAll('.clbi-nations-list-flag-slot')).map(function (slot) {
var img = slot.querySelector('img');
return {
file: slot.getAttribute('data-flag-file') || '',
src: img ? img.getAttribute('src') : '',
missing: slot.classList.contains('is-missing')
};
});
var legacyImages = toArray(document.images).filter(function (img) {
return isLegacyNationIndexFileUrl(img.currentSrc || img.getAttribute('src') || '');
}).map(function (img) {
return img.currentSrc || img.getAttribute('src') || '';
});
var perfLegacy = (window.performance && performance.getEntriesByType ? performance.getEntriesByType('resource') : []).filter(function (entry) {
return isLegacyNationIndexFileUrl(entry && entry.name);
}).map(function (entry) { return entry.name; });
return {
build: NATIONS_PANEL_BUILD,
resolvedFileCount: Object.keys(nationResolvedFileUrlCache || {}).length,
unresolvedFiles: Object.keys(nationResolvedFileUrlCache || {}).filter(function (key) {
return nationResolvedFileUrlCache[key] === '';
}),
renderedFlagCount: flags.length,
missingRenderedFlags: flags.filter(function (flag) { return flag.missing || !flag.src; }),
mediaWikiThumbRenderedFlags: flags.filter(function (flag) { return /\/images\/thumb\//i.test(flag.src || ''); }).length,
legacyImageCount: legacyImages.length,
legacyImages: legacyImages.slice(0, 40),
performanceLegacyRequests: perfLegacy.slice(-40),
sampleFlags: flags.slice(0, 20)
};
}
window.CLBI_NATIONS_PANEL = {
build: NATIONS_PANEL_BUILD,
init: init,
refresh: refresh,
moveEra: moveEra,
setEra: setEra,
diagnostics: diagnostics
};
if (window.mw && mw.hook) {
mw.hook('wikipage.content').add(function ($content) {
init($content && $content[0] ? $content[0] : document);
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function () { init(document); });
} else {
init(document);
}
}());