MediaWiki:Common.js: различия между версиями

Нет описания правки
Нет описания правки
Строка 628: Строка 628:
}
}
// Для "Шаблон:Ajax"
// Для "Шаблон:Ajax"
function initAjaxLoader() {
function fetchParsedData(wikiText) {
var ajaxContainers = document.querySelectorAll('.ajax-load, .ajax-load-link');
var apiUrl = mw.util.wikiScript('api') + '?action=parse&format=json&prop=text&text=' + encodeURIComponent(wikiText) + '&origin=*';
var BATCH_SIZE = 1000;
return $.ajax({
var queue = [];
url: apiUrl,
var processing = false;
method: 'GET',
dataType: 'json'
});
}
 
function applyParsedHTML(parsedHTML, placeholder) {
var newContainer = document.createElement('span');
newContainer.innerHTML = parsedHTML;
 
if (placeholder && placeholder.parentNode) {
placeholder.replaceWith(newContainer);
}
 
var scripts = Array.prototype.slice.call(newContainer.querySelectorAll('script'));
scripts.forEach(function (scr) {
var parent = scr.parentNode;
var scriptNode = document.createElement('script');
if (scr.src) {
scriptNode.src = scr.src;
if (scr.defer) scriptNode.defer = true;
if (scr.async) scriptNode.async = true;
parent.replaceChild(scriptNode, scr);
} else {
try { $.globalEval(scr.textContent || scr.innerText || ''); } catch (e) {}
parent.removeChild(scr);
}
});
 
mw.loader.using(['jquery.tablesorter', 'jquery.makeCollapsible'], function () {
$(newContainer).find('table.sortable').tablesorter();
$(newContainer).find('.mw-collapsible').makeCollapsible();
});
 
mw.hook('wikipage.content').fire(newContainer);
mw.loader.load('//station14.ru/w/index.php?title=MediaWiki:Common.js&action=raw&ctype=text/javascript');
}


function parseWikiTextWithLoading(wikiText, placeholder, loadingText) {
var loadingImgHTML = '<img alt="Файл:Silva-loading.gif" src="/images/4/45/Silva-loading.gif?20260316201152" decoding="async" width="16" height="16" data-file-width="16" data-file-height="16" style="vertical-align:middle;margin-right:6px">';
var loadingImgHTML = '<img alt="Файл:Silva-loading.gif" src="/images/4/45/Silva-loading.gif?20260316201152" decoding="async" width="16" height="16" data-file-width="16" data-file-height="16" style="vertical-align:middle;margin-right:6px">';


function fetchParsedData(wikiText) {
function createFallbackPlaceholder(text) {
var apiUrl = "https://station14.ru/api.php?action=parse&format=json&prop=text&text=" + encodeURIComponent(wikiText) + "&origin=*";
var p = document.createElement('span');
return $.ajax({
p.className = 'ajax-load-placeholder';
url: apiUrl,
p.innerHTML = loadingImgHTML + '<span class="ajax-load-text">' + (text || '') + '</span>';
method: "GET",
return p;
dataType: "json"
});
}
}


function applyParsedHTML(parsedHTML, placeholder) {
var actualPlaceholder = placeholder;
var newContainer = document.createElement("span");
if (!actualPlaceholder) {
newContainer.innerHTML = parsedHTML;
actualPlaceholder = createFallbackPlaceholder(loadingText || 'Загрузка...');
}


if (placeholder && placeholder.parentNode) {
return fetchParsedData(wikiText)
placeholder.replaceWith(newContainer);
.done(function (data) {
}
if (data.parse && data.parse.text) {
 
var parsedHTML = data.parse.text["*"] || '';
var scripts = Array.prototype.slice.call(newContainer.querySelectorAll("script"));
applyParsedHTML(parsedHTML, actualPlaceholder);
scripts.forEach(function (scr) {
} else if (actualPlaceholder) {
var parent = scr.parentNode;
actualPlaceholder.textContent = 'API не вернул ожидаемых данных.';
var scriptNode = document.createElement("script");
}
if (scr.src) {
})
scriptNode.src = scr.src;
.fail(function () {
if (scr.defer) scriptNode.defer = true;
if (actualPlaceholder) {
if (scr.async) scriptNode.async = true;
actualPlaceholder.textContent = 'Ошибка при выполнении запроса к API.';
parent.replaceChild(scriptNode, scr);
} else {
try { $.globalEval(scr.textContent || scr.innerText || ""); } catch (e) {}
parent.removeChild(scr);
}
}
});
});
}


mw.loader.using(['jquery.tablesorter', 'jquery.makeCollapsible'], function () {
function initAjaxLoader() {
$(newContainer).find('table.sortable').tablesorter();
var ajaxContainers = document.querySelectorAll('.ajax-load, .ajax-load-link');
$(newContainer).find('.mw-collapsible').makeCollapsible();
var BATCH_SIZE = 1000;
});
var queue = [];
 
var processing = false;
mw.hook('wikipage.content').fire(newContainer);
mw.loader.load('//station14.ru/w/index.php?title=MediaWiki:Common.js&action=raw&ctype=text/javascript');
}


function processQueue() {
function processQueue() {
Строка 691: Строка 720:


batch.forEach(function (job) {
batch.forEach(function (job) {
fetchParsedData(job.wikiText)
parseWikiTextWithLoading(job.wikiText, job.placeholder, job.loadingText)
.done(function (data) {
if (data.parse && data.parse.text) {
var parsedHTML = data.parse.text["*"] || "";
applyParsedHTML(parsedHTML, job.placeholder);
} else {
if (job.placeholder) job.placeholder.textContent = "API не вернул ожидаемых данных.";
}
})
.fail(function () {
if (job.placeholder) job.placeholder.textContent = "Ошибка при выполнении запроса к API.";
})
.always(function () {
.always(function () {
remaining--;
remaining--;
Строка 719: Строка 737:
if (!contentEl) return;
if (!contentEl) return;


var wikiText = (contentEl.textContent || contentEl.innerText || "").trim();
var wikiText = (contentEl.textContent || contentEl.innerText || '').trim();
if (!wikiText) return;
if (!wikiText) return;


var loadingText = (loadingEl && (loadingEl.textContent || loadingEl.innerText || "").trim()) || "Загрузка...";
var loadingText = (loadingEl && (loadingEl.textContent || loadingEl.innerText || '').trim()) || 'Загрузка...';


if (loadingEl && loadingEl.parentNode) {
if (loadingEl && loadingEl.parentNode) {
Строка 730: Строка 748:


function createPlaceholderWithSpinner(text) {
function createPlaceholderWithSpinner(text) {
var placeholder = document.createElement("span");
var placeholder = document.createElement('span');
placeholder.className = "ajax-load-placeholder";
placeholder.className = 'ajax-load-placeholder';
placeholder.innerHTML = loadingImgHTML + '<span class="ajax-load-text">' + (text || '') + '</span>';
placeholder.innerHTML = '<img alt="Файл:Silva-loading.gif" src="/images/4/45/Silva-loading.gif?20260316201152" decoding="async" width="16" height="16" data-file-width="16" data-file-height="16" style="vertical-align:middle;margin-right:6px"><span class="ajax-load-text">' + (text || '') + '</span>';
return placeholder;
return placeholder;
}
}
Строка 740: Строка 758:
ev.preventDefault && ev.preventDefault();
ev.preventDefault && ev.preventDefault();


if (container.dataset.ajaxLoaded === "1") return;
if (container.dataset.ajaxLoaded === '1') return;
container.dataset.ajaxLoaded = "1";
container.dataset.ajaxLoaded = '1';


var placeholder = createPlaceholderWithSpinner(loadingText);
var placeholder = createPlaceholderWithSpinner(loadingText);
Строка 747: Строка 765:
if (container && container.parentNode) {
if (container && container.parentNode) {
container.parentNode.replaceChild(placeholder, container);
container.parentNode.replaceChild(placeholder, container);
} else {
} else if (contentEl && contentEl.parentNode) {
if (contentEl && contentEl.parentNode) {
contentEl.parentNode.replaceChild(placeholder, contentEl);
contentEl.parentNode.replaceChild(placeholder, contentEl);
}
}
}


queue.push({ wikiText: wikiText, placeholder: placeholder });
queue.push({ wikiText: wikiText, placeholder: placeholder, loadingText: loadingText });
processQueue();
processQueue();
}, { once: true });
}, { once: true });
Строка 763: Строка 779:
}
}


queue.push({ wikiText: wikiText, placeholder: placeholder });
queue.push({ wikiText: wikiText, placeholder: placeholder, loadingText: loadingText });
}
}
});
});
Строка 1003: Строка 1019:
}
}


function getCurrentPageWikitext() {
function getPageWikitext() {
var title = mw.config.get('wgPageName');
var title = mw.config.get('wgPageName');
var apiUrl = mw.util.wikiScript('api') +
var apiUrl = mw.util.wikiScript('api') + '?action=query&prop=revisions&rvslots=main&rvprop=content&titles=' + encodeURIComponent(title) + '&format=json&formatversion=2&origin=*';
'?action=query' +
'&prop=revisions' +
'&rvslots=main' +
'&rvprop=content' +
'&titles=' + encodeURIComponent(title) +
'&format=json' +
'&formatversion=2' +
'&origin=*';


return $.ajax({
return $.ajax({
Строка 1020: Строка 1028:
dataType: 'json'
dataType: 'json'
}).then(function (data) {
}).then(function (data) {
if (!data || !data.query || !data.query.pages || !data.query.pages.length) {
if (!data || !data.query || !data.query.pages || !data.query.pages.length) return '';
return '';
}
 
var page = data.query.pages[0];
var page = data.query.pages[0];
if (!page.revisions || !page.revisions.length) {
if (!page.revisions || !page.revisions.length) return '';
return '';
}
 
var rev = page.revisions[0];
var rev = page.revisions[0];
if (rev.slots && rev.slots.main && typeof rev.slots.main.content === 'string') {
if (rev.slots && rev.slots.main && typeof rev.slots.main.content === 'string') return rev.slots.main.content;
return rev.slots.main.content;
if (typeof rev.content === 'string') return rev.content;
}
 
if (typeof rev.content === 'string') {
return rev.content;
}
 
return '';
return '';
});
});
Строка 1043: Строка 1039:


function stripProjectSelectionTemplate(text) {
function stripProjectSelectionTemplate(text) {
if (!text) return '';
return String(text || '').replace(/\{\{\s*projectselectiongenerator\b[\s\S]*?\}\}/ig, '');
 
return text.replace(/\{\{\s*projectSelectionGenerator\b[\s\S]*?\}\}/ig, '');
}
 
function buildWikitextForProject(text, projectName) {
var cleanedText = stripProjectSelectionTemplate(text);
 
return '{{#vardefine:Path|' + projectName + '}}\n' + cleanedText;
}
 
function parseWikiText(wikiText) {
var apiUrl = mw.util.wikiScript('api') +
'?action=parse' +
'&format=json' +
'&formatversion=2' +
'&prop=text' +
'&text=' + encodeURIComponent(wikiText) +
'&disablelimitreport=1' +
'&disableeditsection=1' +
'&disabletoc=1' +
'&origin=*';
 
return $.ajax({
url: apiUrl,
method: 'GET',
dataType: 'json'
});
}
 
function applyParsedHTML(parsedHTML, preservedMenus) {
var contentRoot = getContentRoot();
if (!contentRoot) return;
 
contentRoot.innerHTML = parsedHTML;
 
if (preservedMenus && preservedMenus.length > 0) {
for (var i = 0; i < preservedMenus.length; i++) {
contentRoot.insertBefore(preservedMenus[i], contentRoot.firstChild);
}
}
 
mw.hook('wikipage.content').fire(contentRoot);
}
}


function refreshPageForProject(projectName, preservedMenus) {
function refreshForProject(projectName, menuNode) {
getCurrentPageWikitext()
getPageWikitext()
.then(function (sourceText) {
.then(function (sourceText) {
var newText = buildWikitextForProject(sourceText, projectName);
var newText = '{{#vardefine:Path|' + projectName + '}}\n' + stripProjectSelectionTemplate(sourceText);
return parseWikiText(newText);
return fetchParsedData(newText);
})
})
.then(function (data) {
.then(function (data) {
if (data && data.parse && data.parse.text) {
if (data && data.parse && data.parse.text) {
var parsedHTML = data.parse.text["*"] || data.parse.text || "";
var parsedHTML = data.parse.text["*"] || '';
applyParsedHTML(parsedHTML, preservedMenus);
var root = getContentRoot();
if (!root) return;
root.innerHTML = parsedHTML;
if (menuNode) {
root.insertBefore(menuNode, root.firstChild);
}
mw.hook('wikipage.content').fire(root);
}
}
})
})
.fail(function () {
.fail(function () {
console.error('Не удалось перепарсить страницу для проекта:', projectName);
console.error('Не удалось перепарсить страницу');
});
});
}
}
Строка 1107: Строка 1067:
for (var ci = 0; ci < containers.length; ci++) {
for (var ci = 0; ci < containers.length; ci++) {
var container = containers[ci];
var container = containers[ci];
if (container.getAttribute('data-project-selection-initialized') === '1') {
continue;
}


var rawText = container.textContent || '';
var rawText = container.textContent || '';
Строка 1118: Строка 1074:
for (var i = 0; i < items.length; i++) {
for (var i = 0; i < items.length; i++) {
var item = items[i].trim();
var item = items[i].trim();
if (item) {
if (item) projects.push(item);
projects.push(item);
}
}
}


if (projects.length <= 1) {
if (projects.length <= 1) continue;
continue;
}


var form = document.createElement('form');
var form = document.createElement('form');
Строка 1142: Строка 1094:
input.id = projectId;
input.id = projectId;


if (j === 0) {
if (j === 0) input.checked = true;
input.checked = true;
}


var label = document.createElement('label');
var label = document.createElement('label');
Строка 1158: Строка 1108:
container.appendChild(form);
container.appendChild(form);


(function (menuContainer) {
(function (menuNode) {
var radios = menuContainer.querySelectorAll('input[type="radio"][name="js-project-selection"]');
var radios = menuNode.querySelectorAll('input[type="radio"][name="js-project-selection"]');
 
for (var r = 0; r < radios.length; r++) {
for (var r = 0; r < radios.length; r++) {
radios[r].addEventListener('change', function () {
radios[r].addEventListener('change', function () {
if (!this.checked) return;
if (!this.checked) return;
 
refreshForProject(this.value, menuNode);
var projectName = this.value;
 
var preservedMenus = [];
var menuNode = menuContainer;
if (menuNode && menuNode.parentNode) {
preservedMenus.push(menuNode);
}
 
refreshPageForProject(projectName, preservedMenus);
});
});
}
}
})(container);
})(container);
container.setAttribute('data-project-selection-initialized', '1');
}
}
}
}