MediaWiki:Common.js: различия между версиями
Pok (обсуждение | вклад) Нет описания правки |
Pok (обсуждение | вклад) Нет описания правки |
||
| Строка 628: | Строка 628: | ||
} | } | ||
// Для "Шаблон:Ajax" | // Для "Шаблон:Ajax" | ||
function | function fetchParsedData(wikiText) { | ||
var | var apiUrl = mw.util.wikiScript('api') + '?action=parse&format=json&prop=text&text=' + encodeURIComponent(wikiText) + '&origin=*'; | ||
var | return $.ajax({ | ||
var | url: apiUrl, | ||
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 | function createFallbackPlaceholder(text) { | ||
var | var p = document.createElement('span'); | ||
return | p.className = 'ajax-load-placeholder'; | ||
p.innerHTML = loadingImgHTML + '<span class="ajax-load-text">' + (text || '') + '</span>'; | |||
return p; | |||
} | } | ||
var actualPlaceholder = placeholder; | |||
if (!actualPlaceholder) { | |||
actualPlaceholder = createFallbackPlaceholder(loadingText || 'Загрузка...'); | |||
} | |||
return fetchParsedData(wikiText) | |||
.done(function (data) { | |||
if (data.parse && data.parse.text) { | |||
var parsedHTML = data.parse.text["*"] || ''; | |||
applyParsedHTML(parsedHTML, actualPlaceholder); | |||
} else if (actualPlaceholder) { | |||
actualPlaceholder.textContent = 'API не вернул ожидаемых данных.'; | |||
} | |||
if ( | }) | ||
.fail(function () { | |||
if (actualPlaceholder) { | |||
actualPlaceholder.textContent = 'Ошибка при выполнении запроса к API.'; | |||
} | } | ||
}); | }); | ||
} | |||
function initAjaxLoader() { | |||
var ajaxContainers = document.querySelectorAll('.ajax-load, .ajax-load-link'); | |||
var BATCH_SIZE = 1000; | |||
var queue = []; | |||
var processing = false; | |||
function processQueue() { | function processQueue() { | ||
| Строка 691: | Строка 720: | ||
batch.forEach(function (job) { | batch.forEach(function (job) { | ||
parseWikiTextWithLoading(job.wikiText, job.placeholder, job.loadingText) | |||
.always(function () { | .always(function () { | ||
remaining--; | remaining--; | ||
| Строка 719: | Строка 737: | ||
if (!contentEl) return; | if (!contentEl) return; | ||
var wikiText = (contentEl.textContent || contentEl.innerText || | var wikiText = (contentEl.textContent || contentEl.innerText || '').trim(); | ||
if (!wikiText) return; | if (!wikiText) return; | ||
var loadingText = (loadingEl && (loadingEl.textContent || loadingEl.innerText || | 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( | var placeholder = document.createElement('span'); | ||
placeholder.className = | placeholder.className = 'ajax-load-placeholder'; | ||
placeholder.innerHTML = | 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 === | if (container.dataset.ajaxLoaded === '1') return; | ||
container.dataset.ajaxLoaded = | 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) { | ||
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 | 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=*'; | ||
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 ''; | ||
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 ''; | ||
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; | ||
if (typeof rev.content === 'string') return rev.content; | |||
if (typeof rev.content === 'string') | |||
return ''; | return ''; | ||
}); | }); | ||
| Строка 1043: | Строка 1039: | ||
function stripProjectSelectionTemplate(text) { | function stripProjectSelectionTemplate(text) { | ||
return String(text || '').replace(/\{\{\s*projectselectiongenerator\b[\s\S]*?\}\}/ig, ''); | |||
} | } | ||
function | function refreshForProject(projectName, menuNode) { | ||
getPageWikitext() | |||
.then(function (sourceText) { | .then(function (sourceText) { | ||
var newText = | var newText = '{{#vardefine:Path|' + projectName + '}}\n' + stripProjectSelectionTemplate(sourceText); | ||
return | 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["*"] || | var parsedHTML = data.parse.text["*"] || ''; | ||
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('Не удалось перепарсить страницу | 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]; | ||
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); | ||
} | } | ||
if (projects.length <= 1) | if (projects.length <= 1) 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; | ||
var label = document.createElement('label'); | var label = document.createElement('label'); | ||
| Строка 1158: | Строка 1108: | ||
container.appendChild(form); | container.appendChild(form); | ||
(function ( | (function (menuNode) { | ||
var radios = | 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); | |||
}); | }); | ||
} | } | ||
})(container); | })(container); | ||
} | } | ||
} | } | ||