MediaWiki:Common.js: различия между версиями
Pok (обсуждение | вклад) Нет описания правки |
Pok (обсуждение | вклад) Нет описания правки Метки: с мобильного устройства из мобильной версии через расширенный мобильный режим |
||
| (не показаны 54 промежуточные версии этого же участника) | |||
| Строка 63: | Строка 63: | ||
name: "server-marines", | name: "server-marines", | ||
connect: "https://game1.station14.ru/marines-main/server/status", | connect: "https://game1.station14.ru/marines-main/server/status", | ||
serverconnect: "ss14s:// | serverconnect: "ss14s://corvaxforge.ru/server/cm" | ||
}, { | }, { | ||
name: "server-wega", | name: "server-wega", | ||
| Строка 627: | Строка 627: | ||
}); | }); | ||
} | } | ||
var ProjectSelectionState = { | |||
function | jsonPath: '' | ||
var | }; | ||
var | |||
var | function trimText(value) { | ||
return String(value === undefined || value === null ? '' : value).trim(); | |||
} | |||
function normalizeJsonPath(value) { | |||
return trimText(value); | |||
} | |||
function getFirstProjectFromPage() { | |||
var generator = document.querySelector('.js-project-selection-generator'); | |||
if (!generator) return ''; | |||
var rawText = generator.textContent || ''; | |||
var items = rawText.split(','); | |||
for (var i = 0; i < items.length; i++) { | |||
var item = trimText(items[i]); | |||
if (item) return item; | |||
} | |||
return ''; | |||
} | |||
function setCurrentJsonPath(value) { | |||
ProjectSelectionState.jsonPath = normalizeJsonPath(value); | |||
} | |||
function getCurrentJsonPath() { | |||
if (ProjectSelectionState.jsonPath) { | |||
return ProjectSelectionState.jsonPath; | |||
} | |||
var fromPage = getFirstProjectFromPage(); | |||
if (fromPage) { | |||
return | ProjectSelectionState.jsonPath = fromPage; | ||
return fromPage; | |||
} | } | ||
function | return ''; | ||
} | |||
function wrapWikiTextWithJsonPath(wikiText) { | |||
var jsonPath = getCurrentJsonPath(); | |||
if (!jsonPath) return String(wikiText || ''); | |||
return '{{#vardefine:JsonPath|' + jsonPath + '}}' + String(wikiText || ''); | |||
} | |||
function fetchParsedData(wikiText) { | |||
return $.ajax({ | |||
url: mw.util.wikiScript('api'), | |||
method: 'POST', | |||
dataType: 'json', | |||
data: { | |||
action: 'parse', | |||
format: 'json', | |||
prop: 'text', | |||
text: wikiText, | |||
origin: '*' | |||
} | } | ||
}); | |||
} | |||
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); | |||
initPage(); | |||
} | |||
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) { | |||
wikiText = wrapWikiTextWithJsonPath(wikiText); | |||
return fetchParsedData(wikiText) | |||
.done(function (data) { | |||
if (data && data.parse && data.parse.text) { | |||
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 = 3; | |||
var queue = []; | |||
var processing = false; | |||
function processQueue() { | function processQueue() { | ||
| Строка 689: | Строка 806: | ||
batch.forEach(function (job) { | batch.forEach(function (job) { | ||
parseAndInjectWikiText(job.wikiText, { placeholder: job.placeholder }) | |||
.always(function () { | .always(function () { | ||
remaining--; | remaining--; | ||
| Строка 715: | Строка 821: | ||
var loadingEl = container.querySelector('.ajax-load-loading'); | var loadingEl = container.querySelector('.ajax-load-loading'); | ||
if (!contentEl) return; | |||
var | var wikiText = (contentEl.textContent || contentEl.innerText || "").trim(); | ||
if (!wikiText) return; | |||
var loadingHTML = loadingEl ? (loadingEl.innerHTML || "").trim() : ""; | |||
if (loadingEl && loadingEl.parentNode) { | if (loadingEl && loadingEl.parentNode) { | ||
loadingEl.parentNode.removeChild(loadingEl); | loadingEl.parentNode.removeChild(loadingEl); | ||
} | } | ||
if ( | if (container.classList.contains('ajax-load-link')) { | ||
container.addEventListener('click', function (ev) { | |||
ev.preventDefault && ev.preventDefault(); | |||
if (container.dataset.ajaxLoaded === "1") return; | |||
container.dataset.ajaxLoaded = "1"; | |||
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); | contentEl.parentNode.replaceChild(placeholder, contentEl); | ||
} | } | ||
queue.push({ wikiText: wikiText, placeholder: placeholder }); | |||
queue.push({ | processQueue(); | ||
}, { once: true }); | |||
} else { | |||
var placeholder = createPlaceholderWithSpinner(loadingHTML); | |||
if ( | if (contentEl && contentEl.parentNode) { | ||
contentEl.parentNode.replaceChild(placeholder, contentEl); | |||
} | } | ||
queue.push({ wikiText: wikiText, placeholder: placeholder }); | |||
} | } | ||
}); | }); | ||
| Строка 942: | Строка 1021: | ||
function registerCheckboxExpander(checkboxId, options) { | function registerCheckboxExpander(checkboxId, options) { | ||
options = options || {}; | options = options || {}; | ||
var onlyExpand = !!options.onlyExpand; | var onlyExpand = !!options.onlyExpand; | ||
var checkbox = document.getElementById(checkboxId); | var checkbox = document.getElementById(checkboxId); | ||
if (!checkbox) { | if (!checkbox) { | ||
console.warn('registerCheckboxExpander: checkbox not found by id:', checkboxId); | console.warn('registerCheckboxExpander: checkbox not found by id:', checkboxId); | ||
return; | return; | ||
| Строка 1004: | Строка 1081: | ||
try { expandAll(); } catch (err) { console.error(err); } | try { expandAll(); } catch (err) { console.error(err); } | ||
} | } | ||
} | |||
// Для "Шаблон:Переключатель_проекта" | |||
function initProjectSelectionGenerator() { | |||
var COOKIE_PROJECT = 'ss14_preferredProject'; | |||
var containers = document.getElementsByClassName('js-project-selection-generator'); | |||
function normalizeIdPart(s) { | |||
return String(s === undefined || s === null ? '' : s) | |||
.trim() | |||
.replace(/\s+/g, '-') | |||
.replace(/[^A-Za-z0-9_\-\u0400-\u04FF]/g, ''); | |||
} | |||
function normalizeProjectName(s) { | |||
return String(s === undefined || s === null ? '' : s) | |||
.trim() | |||
.toLowerCase(); | |||
} | |||
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 buildWikitext(text, projectName) { | |||
return '{{#vardefine:JsonPath|' + projectName + '}}' + text; | |||
} | |||
function refreshForProject(projectName) { | |||
setCurrentJsonPath(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 = 'Ошибка загрузки страницы.'; | |||
}); | |||
} | |||
function createProjectMenu(projects, activeProject) { | |||
var form = document.createElement('form'); | |||
form.className = 'js-project-menu'; | |||
for (var j = 0; j < projects.length; j++) { | |||
var projectName = projects[j]; | |||
var projectId = 'project-' + normalizeIdPart(projectName); | |||
var div = document.createElement('div'); | |||
var input = document.createElement('input'); | |||
input.type = 'radio'; | |||
input.name = 'js-project-selection'; | |||
input.value = projectName; | |||
input.id = projectId; | |||
if (projectName === activeProject) { | |||
input.checked = true; | |||
} | |||
var label = document.createElement('label'); | |||
label.htmlFor = projectId; | |||
label.textContent = projectName; | |||
div.appendChild(input); | |||
div.appendChild(label); | |||
form.appendChild(div); | |||
} | |||
form.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); | |||
}); | |||
return form; | |||
} | |||
function ensureAssociatedPagesContainer() { | |||
var associatedPages = document.getElementById('p-associated-pages'); | |||
if (associatedPages) { | |||
return associatedPages; | |||
} | |||
var headingHolder = document.querySelector('.heading-holder'); | |||
var pageHeading = document.querySelector('.heading-holder .page-heading'); | |||
if (!headingHolder) { | |||
return null; | |||
} | |||
associatedPages = document.createElement('ul'); | |||
associatedPages.id = 'p-associated-pages'; | |||
associatedPages.className = 'minerva__tab-container'; | |||
if (pageHeading && pageHeading.parentNode === headingHolder) { | |||
if (pageHeading.nextSibling) { | |||
headingHolder.insertBefore(associatedPages, pageHeading.nextSibling); | |||
} else { | |||
headingHolder.appendChild(associatedPages); | |||
} | |||
} else { | |||
headingHolder.appendChild(associatedPages); | |||
} | |||
return associatedPages; | |||
} | |||
function getTargetContainers() { | |||
var targets = []; | |||
var portletList = document.querySelector('#mw-content .mw-portlet-body ul'); | |||
if (portletList) { | |||
targets.push(portletList); | |||
} | |||
var associatedPages = ensureAssociatedPagesContainer(); | |||
if (associatedPages) { | |||
targets.push(associatedPages); | |||
} | |||
return targets; | |||
} | |||
for (var ci = 0; ci < containers.length; ci++) { | |||
var container = containers[ci]; | |||
var rawText = container.textContent || ''; | |||
var items = rawText.split(','); | |||
var projects = []; | |||
for (var i = 0; i < items.length; i++) { | |||
var item = items[i].trim(); | |||
if (item) { | |||
projects.push(item); | |||
} | |||
} | |||
if (projects.length <= 1) { | |||
continue; | |||
} | |||
var preferredProject = $.cookie(COOKIE_PROJECT) || ''; | |||
var preferredNorm = normalizeProjectName(preferredProject); | |||
var activeProject = projects[0]; | |||
if (preferredProject && preferredNorm !== 'corvax') { | |||
for (var p = 0; p < projects.length; p++) { | |||
if (normalizeProjectName(projects[p]) === preferredNorm) { | |||
activeProject = projects[p]; | |||
break; | |||
} | |||
} | |||
} | |||
if (!getCurrentJsonPath()) { | |||
setCurrentJsonPath(activeProject); | |||
} | |||
var targets = getTargetContainers(); | |||
for (var t = 0; t < targets.length; t++) { | |||
targets[t].appendChild(createProjectMenu(projects, activeProject)); | |||
} | |||
if (preferredProject && preferredNorm !== 'corvax') { | |||
for (var k = 0; k < projects.length; k++) { | |||
if (normalizeProjectName(projects[k]) === preferredNorm) { | |||
refreshForProject(projects[k]); | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
function initPage() { | |||
var checkboxExist = document.querySelectorAll('.js-checkbox-generator'); | |||
if (checkboxExist.length > 0) { | |||
initCheckboxCreator(); | |||
} | |||
registerCheckboxExpander('js-checkbox-mw-collapsible'); | |||
} | } | ||
const currentPageTitle = document.title; | const currentPageTitle = document.title; | ||
| Строка 1101: | Строка 1406: | ||
initAjaxLoader(); | initAjaxLoader(); | ||
} | } | ||
var | var projectSelectionExist = document.querySelectorAll('.js-project-selection-generator'); | ||
if ( | if (projectSelectionExist.length > 0) { | ||
initProjectSelectionGenerator(); | |||
} | } | ||
initPage(); | |||
}); | }); | ||
/*WikiEditor/Викификатор*/ | /*WikiEditor/Викификатор*/ | ||