140 lines
6.4 KiB
JavaScript
140 lines
6.4 KiB
JavaScript
// Generic inline-modal shell, loaded on every page (see _Layout.cshtml / _AdminLayout.cshtml),
|
||
// used to replace what used to be four standalone pages: Person.cshtml (a person's profile),
|
||
// People.cshtml (family-tree-roots index), PeopleGraph.cshtml (whole-site relationship graph) and
|
||
// FamilyTree.cshtml (one person's family-tree chart). Those pages had no independent purpose of
|
||
// their own - they only ever existed to show data reachable from somewhere else (a poem's tagged
|
||
// persons, a category's "شخصیتها" tab, an admin moderation queue) - so instead of navigating
|
||
// away, callers open one of these three windows over whatever page they're already on:
|
||
//
|
||
// PersonWindow.open(id) - a small modal: one person's bio/relations/affiliations/poems,
|
||
// fetched from /PersonWindow/{id} (Person.cshtml's old content,
|
||
// stripped of site chrome - see PersonWindow.cshtml).
|
||
// PeopleExplorer.open() - a large modal: the whole-site force-directed graph (formerly
|
||
// /PeopleGraph) plus the family-tree-roots list (formerly /People),
|
||
// merged into one fragment fetched from /PeopleExplorer.
|
||
// FamilyTreeWindow.open(id) - a large modal: one person's connected-kinship-component tree
|
||
// chart (formerly /FamilyTree/{id}), fetched from
|
||
// /FamilyTreeWindow/{id} - see FamilyTreeWindow.cshtml.
|
||
//
|
||
// All three render into the same reusable overlay/modal shell built here on first use.
|
||
(function () {
|
||
'use strict';
|
||
|
||
var STYLE_ID = 'up-modal-styles';
|
||
var overlay, modal, body, closeBtn;
|
||
|
||
function ensureStyles() {
|
||
if (document.getElementById(STYLE_ID)) return;
|
||
var style = document.createElement('style');
|
||
style.id = STYLE_ID;
|
||
style.textContent =
|
||
'.up-modal-overlay{position:fixed;inset:0;background:rgba(30,20,10,.55);z-index:9000;' +
|
||
'display:none;align-items:flex-start;justify-content:center;overflow-y:auto;padding:5vh 16px;}' +
|
||
'.up-modal-overlay--open{display:flex;}' +
|
||
'.up-modal{position:relative;background:#fffdf7;border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.35);' +
|
||
'padding:20px 24px;max-width:640px;width:100%;max-height:90vh;overflow-y:auto;direction:rtl;text-align:right;}' +
|
||
'.up-modal--lg{max-width:900px;}' +
|
||
'.up-modal-close{position:absolute;left:12px;top:10px;border:none;background:none;font-size:22px;' +
|
||
'line-height:1;cursor:pointer;color:#7a4a2a;}' +
|
||
'.up-modal-loading{text-align:center;padding:30px 0;}' +
|
||
'body.up-modal-noscroll{overflow:hidden;}';
|
||
document.head.appendChild(style);
|
||
}
|
||
|
||
function ensureShell() {
|
||
if (overlay) return;
|
||
ensureStyles();
|
||
overlay = document.createElement('div');
|
||
overlay.id = 'up-modal-overlay';
|
||
overlay.className = 'up-modal-overlay';
|
||
overlay.innerHTML =
|
||
'<div class="up-modal" id="up-modal">' +
|
||
'<button type="button" class="up-modal-close" id="up-modal-close" aria-label="بند کریں">×</button>' +
|
||
'<div class="up-modal-body" id="up-modal-body"></div>' +
|
||
'</div>';
|
||
document.body.appendChild(overlay);
|
||
modal = document.getElementById('up-modal');
|
||
body = document.getElementById('up-modal-body');
|
||
closeBtn = document.getElementById('up-modal-close');
|
||
|
||
closeBtn.addEventListener('click', closeModal);
|
||
overlay.addEventListener('click', function (evt) {
|
||
if (evt.target === overlay) closeModal();
|
||
});
|
||
document.addEventListener('keydown', function (evt) {
|
||
if (evt.key === 'Escape' && overlay.classList.contains('up-modal-overlay--open')) {
|
||
closeModal();
|
||
}
|
||
});
|
||
}
|
||
|
||
function openModal(large) {
|
||
ensureShell();
|
||
modal.classList.toggle('up-modal--lg', !!large);
|
||
body.innerHTML = '<div class="up-modal-loading"><img src="/image/loading.gif" alt="لوڈ کریں" /></div>';
|
||
overlay.classList.add('up-modal-overlay--open');
|
||
document.body.classList.add('up-modal-noscroll');
|
||
}
|
||
|
||
function closeModal() {
|
||
if (!overlay) return;
|
||
overlay.classList.remove('up-modal-overlay--open');
|
||
document.body.classList.remove('up-modal-noscroll');
|
||
}
|
||
|
||
function loadInto(url, onReady) {
|
||
$.ajax({
|
||
type: 'GET',
|
||
url: url,
|
||
error: function () {
|
||
if (body) body.innerHTML = '<p>معلومات لوڈ کرنے میں خرابی.</p>';
|
||
},
|
||
success: function (data) {
|
||
body.innerHTML = data;
|
||
if (onReady) onReady();
|
||
}
|
||
});
|
||
}
|
||
|
||
function openPerson(id) {
|
||
openModal(false);
|
||
loadInto('/PersonWindow/' + String(id));
|
||
}
|
||
|
||
function openExplorer() {
|
||
openModal(true);
|
||
loadInto('/PeopleExplorer', function () {
|
||
var dataEl = document.getElementById('pge-data');
|
||
if (dataEl && window.DivanPeopleGraph) {
|
||
var graphData = JSON.parse(dataEl.textContent);
|
||
DivanPeopleGraph.render({
|
||
containerId: 'pge-container',
|
||
svgId: 'pge-svg',
|
||
tableBodyId: 'pge-table-body',
|
||
legendId: 'pge-legend',
|
||
searchInputId: 'pge-search',
|
||
resetButtonId: 'pge-reset',
|
||
data: graphData
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
function openFamilyTree(id) {
|
||
openModal(true);
|
||
loadInto('/FamilyTreeWindow/' + String(id), function () {
|
||
var dataEl = document.getElementById('ftw-data');
|
||
var rootIdEl = document.getElementById('ftw-root-id');
|
||
if (dataEl && rootIdEl && window.DivanFamilyTree) {
|
||
var treeData = JSON.parse(dataEl.textContent);
|
||
var rootId = parseInt(rootIdEl.value, 10);
|
||
DivanFamilyTree.render('familytree-container', 'familytree-svg', 'familytree-tooltip', treeData, rootId);
|
||
}
|
||
});
|
||
}
|
||
|
||
window.PersonWindow = { open: openPerson, close: closeModal };
|
||
window.PeopleExplorer = { open: openExplorer, close: closeModal };
|
||
window.FamilyTreeWindow = { open: openFamilyTree, close: closeModal };
|
||
})();
|