편집 요약 없음 |
편집 요약 없음 |
||
| 184번째 줄: | 184번째 줄: | ||
reloadGlobe(globe); | 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 = {}; | |||
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) { | |||
return String(value || '') | |||
.trim() | |||
.replace(/^파일\s*:/i, '') | |||
.replace(/^File\s*:/i, '') | |||
.replace(/^이미지\s*:/i, '') | |||
.replace(/^Image\s*:/i, '') | |||
.replace(/^:+/, '') | |||
.trim(); | |||
} | |||
function buildNationFileUrl(file) { | |||
file = normalizeNationFile(file); | |||
return file ? '/index.php/Special:Redirect/file/' + encodeWikiTitle(file) : ''; | |||
} | |||
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 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(url, { credentials: 'same-origin', cache: 'no-cache' }) | |||
.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 renderNationFlag(flag) { | |||
var file; | |||
var url; | |||
var width; | |||
var classes; | |||
if (!flag) return ''; | |||
file = normalizeNationFile(flag.file || flag.flag_file || flag.flag || ''); | |||
if (!file) return ''; | |||
url = buildNationFileUrl(file); | |||
width = String(flag.width || flag.flag_width || '16px').trim() || '16px'; | |||
classes = 'clbi-nations-list-flag' + (flag.border !== false ? ' has-border' : '') + (flag.decorator === 'top' ? ' is-top' : ''); | |||
return '<img class="' + classes + '" src="' + escapeHtml(url) + '" alt="" style="width:' + escapeHtml(width) + ';">'; | |||
} | |||
function renderNationItem(item, index, items) { | |||
var flags = Array.isArray(item.flags) ? item.flags : []; | |||
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 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">' + 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 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(''); | |||
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); | |||
panel.setAttribute('data-nation-list-loading', '1'); | |||
fetchNationList(panel, era).then(function (data) { | |||
renderNationListPanel(panel, data); | |||
}).catch(function () { | |||
panel.classList.add('clbi-nations-list-json-fallback'); | |||
}).finally(function () { | |||
panel.removeAttribute('data-nation-list-loading'); | |||
}); | |||
} | } | ||
| 337번째 줄: | 583번째 줄: | ||
contentPanels.forEach(function (panel) { | 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); | |||
} | |||
}); | }); | ||
| 379번째 줄: | 629번째 줄: | ||
var scope = root && root.querySelectorAll ? root : document; | var scope = root && root.querySelectorAll ? root : document; | ||
toArray(scope.querySelectorAll('.clbi-nations-tabpanel')).forEach(initNationListPanel); | |||
toArray(scope.querySelectorAll('.clbi-nations-tabpanel')).forEach(initContinentPanel); | toArray(scope.querySelectorAll('.clbi-nations-tabpanel')).forEach(initContinentPanel); | ||
toArray(scope.querySelectorAll('.clbi-nations-history-panel')).forEach(initHistoryYearPanel); | toArray(scope.querySelectorAll('.clbi-nations-history-panel')).forEach(initHistoryYearPanel); | ||
2026년 7월 5일 (일) 04:05 판
/* =========================================
COASTLINE: BLACK ICE - Nations Panel
국가 및 조합: 시대 전환 / 역사 연도 / 대륙 탭 제어
========================================= */
(function () {
'use strict';
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 = {};
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) {
return String(value || '')
.trim()
.replace(/^파일\s*:/i, '')
.replace(/^File\s*:/i, '')
.replace(/^이미지\s*:/i, '')
.replace(/^Image\s*:/i, '')
.replace(/^:+/, '')
.trim();
}
function buildNationFileUrl(file) {
file = normalizeNationFile(file);
return file ? '/index.php/Special:Redirect/file/' + encodeWikiTitle(file) : '';
}
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 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(url, { credentials: 'same-origin', cache: 'no-cache' })
.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 renderNationFlag(flag) {
var file;
var url;
var width;
var classes;
if (!flag) return '';
file = normalizeNationFile(flag.file || flag.flag_file || flag.flag || '');
if (!file) return '';
url = buildNationFileUrl(file);
width = String(flag.width || flag.flag_width || '16px').trim() || '16px';
classes = 'clbi-nations-list-flag' + (flag.border !== false ? ' has-border' : '') + (flag.decorator === 'top' ? ' is-top' : '');
return '<img class="' + classes + '" src="' + escapeHtml(url) + '" alt="" style="width:' + escapeHtml(width) + ';">';
}
function renderNationItem(item, index, items) {
var flags = Array.isArray(item.flags) ? item.flags : [];
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 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">' + 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 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('');
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);
panel.setAttribute('data-nation-list-loading', '1');
fetchNationList(panel, era).then(function (data) {
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 || 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(bodies, '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 () {
activate(tab.getAttribute('data-continent'));
});
tab.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
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 () {
activate(tab.getAttribute('data-year'));
});
tab.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
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);
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;
toArray(scope.querySelectorAll('.clbi-nations-tabpanel')).forEach(initNationListPanel);
toArray(scope.querySelectorAll('.clbi-nations-tabpanel')).forEach(initContinentPanel);
toArray(scope.querySelectorAll('.clbi-nations-history-panel')).forEach(initHistoryYearPanel);
toArray(scope.querySelectorAll('.clbi-nations-panel-stack')).forEach(initEraStack);
}
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;
}
window.CLBI_NATIONS_PANEL = {
init: init,
moveEra: moveEra,
setEra: setEra
};
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);
}
}());