MediaWiki:Common.js: различия между версиями
Pok (обсуждение | вклад) Нет описания правки |
Pok (обсуждение | вклад) Нет описания правки |
||
| (не показано 15 промежуточных версий этого же участника) | |||
| Строка 627: | Строка 627: | ||
}); | }); | ||
} | } | ||
// | function fetchParsedData(wikiText) { | ||
function | var apiUrl = "https://station14.ru/api.php?action=parse&format=json&prop=text&text=" + encodeURIComponent(wikiText) + "&origin=*"; | ||
var | return $.ajax({ | ||
url: apiUrl, | |||
var | method: "GET", | ||
dataType: "json" | |||
}); | |||
} | |||
function enhanceParsedContent(root) { | |||
if (!root) return; | |||
var scripts = Array.prototype.slice.call(root.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 () { | |||
$(root).find('table.sortable').tablesorter(); | |||
$(root).find('.mw-collapsible').makeCollapsible(); | |||
}); | |||
mw.hook('wikipage.content').fire(root); | |||
initAjaxLoader(root); | |||
} | |||
function injectParsedHTML(parsedHTML, options) { | |||
options = options || {}; | |||
var container = document.createElement("span"); | |||
container.innerHTML = parsedHTML; | |||
if (options.keepNode) { | |||
container.insertBefore(options.keepNode, container.firstChild); | |||
} | |||
if (options.placeholder && options.placeholder.parentNode) { | |||
options.placeholder.replaceWith(container); | |||
} else if (options.targetRoot) { | |||
options.targetRoot.innerHTML = ""; | |||
while (container.firstChild) { | |||
options.targetRoot.appendChild(container.firstChild); | |||
} | |||
container = options.targetRoot; | |||
} | } | ||
enhanceParsedContent(container); | |||
return container; | |||
} | |||
function parseAndInjectWikiText(wikiText, options) { | |||
return fetchParsedData(wikiText) | |||
.done(function (data) { | |||
if (data && data.parse && data.parse.text) { | |||
if ( | var parsedHTML = data.parse.text["*"] || ""; | ||
injectParsedHTML(parsedHTML, options); | |||
} else if (options && options.placeholder) { | |||
options.placeholder.textContent = "API не вернул ожидаемых данных."; | |||
} | |||
}) | |||
.fail(function () { | |||
if (options && options.placeholder) { | |||
options.placeholder.textContent = "Ошибка при выполнении запроса к API."; | |||
} | } | ||
}); | }); | ||
} | |||
function createPlaceholderWithSpinner(text) { | |||
if (!text) { | |||
loadingImgHTML = '<img alt="Файл:Silva-loading.gif" src="/images/4/45/Silva-loading.gif" decoding="async" width="16" height="16" style="vertical-align:middle;margin-right:6px">'; | |||
text = loadingImgHTML + '<span class="ajax-load-text">Пожалуйста, подождите, содержимое загружается...</span>'; | |||
} | |||
var placeholder = document.createElement("span"); | |||
placeholder.className = "ajax-load-placeholder"; | |||
placeholder.innerHTML = text; | |||
return placeholder; | |||
} | |||
// Для "Шаблон:Ajax" | |||
function initAjaxLoader(root) { | |||
root = root || document; | |||
var ajaxContainers = root.querySelectorAll('.ajax-load, .ajax-load-link'); | |||
var BATCH_SIZE = 1000; | |||
var queue = []; | |||
var processing = false; | |||
function processQueue() { | function processQueue() { | ||
| Строка 691: | Строка 745: | ||
batch.forEach(function (job) { | batch.forEach(function (job) { | ||
parseAndInjectWikiText(job.wikiText, { placeholder: job.placeholder }) | |||
.always(function () { | .always(function () { | ||
remaining--; | remaining--; | ||
| Строка 722: | Строка 765: | ||
if (!wikiText) return; | if (!wikiText) return; | ||
var | var loadingHTML = loadingEl ? (loadingEl.innerHTML || "").trim() : ""; | ||
if (loadingEl && loadingEl.parentNode) { | if (loadingEl && loadingEl.parentNode) { | ||
loadingEl.parentNode.removeChild(loadingEl); | loadingEl.parentNode.removeChild(loadingEl); | ||
} | } | ||
| Строка 743: | Строка 778: | ||
container.dataset.ajaxLoaded = "1"; | container.dataset.ajaxLoaded = "1"; | ||
var placeholder = createPlaceholderWithSpinner( | var placeholder = createPlaceholderWithSpinner(loadingHTML); | ||
if (container && container.parentNode) { | if (container && container.parentNode) { | ||
container.parentNode.replaceChild(placeholder, container); | container.parentNode.replaceChild(placeholder, container); | ||
} else | } else if (contentEl && contentEl.parentNode) { | ||
contentEl.parentNode.replaceChild(placeholder, contentEl); | |||
} | } | ||
| Строка 757: | Строка 790: | ||
}, { once: true }); | }, { once: true }); | ||
} else { | } else { | ||
var placeholder = createPlaceholderWithSpinner( | var placeholder = createPlaceholderWithSpinner(loadingHTML); | ||
if (contentEl && contentEl.parentNode) { | if (contentEl && contentEl.parentNode) { | ||
| Строка 988: | Строка 1021: | ||
} | } | ||
} | } | ||
// | // Для "Шаблон:Переключатель_проекта" | ||
function initProjectSelectionGenerator() { | function initProjectSelectionGenerator() { | ||
var containers = document.getElementsByClassName('js-project-selection-generator'); | var containers = document.getElementsByClassName('js-project-selection-generator'); | ||
| Строка 997: | Строка 1030: | ||
.replace(/\s+/g, '-') | .replace(/\s+/g, '-') | ||
.replace(/[^A-Za-z0-9_\-\u0400-\u04FF]/g, ''); | .replace(/[^A-Za-z0-9_\-\u0400-\u04FF]/g, ''); | ||
} | |||
function getContentRoot() { | |||
return document.querySelector('#mw-content-text .mw-parser-output') || document.querySelector('#mw-content-text'); | |||
} | |||
function getPageWikitext() { | |||
var title = mw.config.get('wgPageName'); | |||
var apiUrl = mw.util.wikiScript('api') + '?action=query&prop=revisions&rvslots=main&rvprop=content&titles=' + encodeURIComponent(title) + '&format=json&formatversion=2&origin=*'; | |||
return $.ajax({ | |||
url: apiUrl, | |||
method: 'GET', | |||
dataType: 'json' | |||
}).then(function (data) { | |||
if (!data || !data.query || !data.query.pages || !data.query.pages.length) { | |||
return ''; | |||
} | |||
var page = data.query.pages[0]; | |||
if (!page.revisions || !page.revisions.length) { | |||
return ''; | |||
} | |||
var rev = page.revisions[0]; | |||
if (rev.slots && rev.slots.main && typeof rev.slots.main.content === 'string') { | |||
return rev.slots.main.content; | |||
} | |||
if (typeof rev.content === 'string') { | |||
return rev.content; | |||
} | |||
return ''; | |||
}); | |||
} | |||
function stripProjectSelectionTemplate(text) { | |||
return String(text || '').replace(/\{\{\s*переключатель проекта\b[\s\S]*?\}\}/ig, ''); | |||
} | |||
function buildWikitext(text, projectName) { | |||
return '{{#vardefine:JsonPath|' + projectName + '}}\n' + stripProjectSelectionTemplate(text); | |||
} | |||
function refreshForProject(projectName) { | |||
var root = getContentRoot(); | |||
if (!root) return; | |||
var placeholder = createPlaceholderWithSpinner(); | |||
root.innerHTML = ''; | |||
root.appendChild(placeholder); | |||
getPageWikitext() | |||
.then(function (sourceText) { | |||
var wikitext = buildWikitext(sourceText, projectName); | |||
return parseAndInjectWikiText(wikitext, { | |||
placeholder: placeholder, | |||
targetRoot: root | |||
}); | |||
}) | |||
.fail(function () { | |||
placeholder.textContent = 'Ошибка загрузки страницы.'; | |||
}); | |||
} | } | ||
| Строка 1018: | Строка 1117: | ||
var form = document.createElement('form'); | var form = document.createElement('form'); | ||
form.className = 'project-menu'; | form.className = 'js-project-menu'; | ||
for (var j = 0; j < projects.length; j++) { | for (var j = 0; j < projects.length; j++) { | ||
| Строка 1028: | Строка 1127: | ||
var input = document.createElement('input'); | var input = document.createElement('input'); | ||
input.type = 'radio'; | input.type = 'radio'; | ||
input.name = 'project-selection'; | input.name = 'js-project-selection'; | ||
input.value = projectName; | input.value = projectName; | ||
input.id = projectId; | input.id = projectId; | ||
| Строка 1045: | Строка 1144: | ||
} | } | ||
var portletList = document.querySelector('#mw-content .mw-portlet-body ul'); | |||
if (portletList) { | |||
portletList.appendChild(form); | |||
} | |||
(function (menuNode) { | |||
menuNode.addEventListener('change', function (event) { | |||
var target = event.target; | |||
if (!target || target.tagName !== 'INPUT') return; | |||
if (target.type !== 'radio') return; | |||
if (target.name !== 'js-project-selection') return; | |||
if (!target.checked) return; | |||
refreshForProject(target.value); | |||
}); | |||
})(form); | |||
} | } | ||
} | } | ||