MediaWiki:Common.js: различия между версиями
Pok (обсуждение | вклад) Нет описания правки |
Pok (обсуждение | вклад) Нет описания правки |
||
| (не показаны 3 промежуточные версии этого же участника) | |||
| Строка 629: | Строка 629: | ||
// Для "Шаблон:Ajax" | // Для "Шаблон:Ajax" | ||
function initAjaxLoader() { | function initAjaxLoader() { | ||
var | var ajaxContainers = document.querySelectorAll('.ajax-load, .ajax-load-link'); | ||
var BATCH_SIZE = 1000; | var BATCH_SIZE = 1000; | ||
var queue = []; | var queue = []; | ||
| Строка 647: | Строка 646: | ||
var newContainer = document.createElement("span"); | var newContainer = document.createElement("span"); | ||
newContainer.innerHTML = parsedHTML; | newContainer.innerHTML = parsedHTML; | ||
if (placeholder && placeholder.parentNode) { | if (placeholder && placeholder.parentNode) { | ||
placeholder.replaceWith(newContainer); | placeholder.replaceWith(newContainer); | ||
| Строка 661: | Строка 661: | ||
parent.replaceChild(scriptNode, scr); | parent.replaceChild(scriptNode, scr); | ||
} else { | } else { | ||
try { | try { $.globalEval(scr.textContent || scr.innerText || ""); } catch (e) {} | ||
parent.removeChild(scr); | parent.removeChild(scr); | ||
} | } | ||
| Строка 705: | Строка 703: | ||
.always(function () { | .always(function () { | ||
remaining--; | remaining--; | ||
if (remaining === 0) | if (remaining === 0) nextBatch(); | ||
}); | }); | ||
}); | }); | ||
| Строка 715: | Строка 711: | ||
} | } | ||
var | ajaxContainers.forEach(function (container) { | ||
var contentEl = container.querySelector('.ajax-load-content'); | |||
var loadingEl = container.querySelector('.ajax-load-loading'); | |||
if (!contentEl) return; | |||
var wikiText = (contentEl.textContent || contentEl.innerText || "").trim(); | |||
if (!wikiText) return; | |||
var loadingText = (loadingEl && (loadingEl.textContent || loadingEl.innerText || "").trim()) || "Загрузка..."; | |||
if (loadingEl && loadingEl.parentNode) { | |||
loadingEl.parentNode.removeChild(loadingEl); | |||
loadingEl = null; | |||
} | } | ||
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 = document.createElement("span"); | |||
placeholder.className = "ajax-load-placeholder"; | |||
placeholder.textContent = loadingText; | |||
if (container && container.parentNode) { | |||
container.parentNode.replaceChild(placeholder, container); | |||
} else { | |||
if (contentEl && contentEl.parentNode) { | |||
contentEl.parentNode.replaceChild(placeholder, contentEl); | |||
} | |||
} | |||
queue.push({ wikiText: wikiText, placeholder: placeholder }); | |||
processQueue(); | |||
}, { once: true }); | |||
} else { | |||
var placeholder = document.createElement("span"); | var placeholder = document.createElement("span"); | ||
placeholder. | placeholder.className = "ajax-load-placeholder"; | ||
placeholder.textContent = loadingText; | |||
if (contentEl && contentEl.parentNode) { | |||
contentEl.parentNode.replaceChild(placeholder, contentEl); | |||
} | |||
queue.push({ wikiText: wikiText, placeholder: placeholder }); | queue.push({ wikiText: wikiText, placeholder: placeholder }); | ||
} | |||
} | |||
}); | }); | ||
| Строка 748: | Строка 766: | ||
// Для "Шаблон:CheckboxCreator" | // Для "Шаблон:CheckboxCreator" | ||
function initCheckboxCreator() { | function initCheckboxCreator() { | ||
var containers = document. | var containers = document.getElementsByClassName('js-checkbox-generator'); | ||
function parseBool(v) { | function parseBool(v) { | ||
if (v === undefined || v === null) return false; | if (v === true) return true; | ||
if (v === false || v === undefined || v === null) return false; | |||
return | var s = String(v).trim().toLowerCase(); | ||
return s === '1' || s === 'true' || s === 'yes' || s === 'checked'; | |||
} | |||
function escHtml(s) { | |||
return String(s === undefined || s === null ? '' : s) | |||
.replace(/&/g, '&') | |||
.replace(/</g, '<') | |||
.replace(/>/g, '>') | |||
.replace(/"/g, '"') | |||
.replace(/'/g, '''); | |||
} | } | ||
var HTML_BATCH_THRESHOLD = 200; | |||
var | |||
for (var ci = 0; ci < containers.length; ci++) { | |||
var container = containers[ci]; | |||
if (container.getAttribute('data-checkbox-initialized') === '1') { | |||
continue; | |||
} | |||
var defaultCls = container.getAttribute('data-cbox-class') || ''; | |||
var itemsRaw = container.getAttribute('data-cbox-items'); | |||
if (itemsRaw) { | |||
var arr = null; | |||
try { | |||
arr = JSON.parse(itemsRaw); | |||
} catch (e) { | |||
container.setAttribute('data-checkbox-initialized', '1'); | |||
continue; | |||
} | |||
if (!Array.isArray(arr) || arr.length === 0) { | |||
container.setAttribute('data-checkbox-initialized', '1'); | |||
continue; | |||
} | |||
if (arr.length >= HTML_BATCH_THRESHOLD) { | |||
var html = ''; | |||
for (var i = 0; i < arr.length; i++) { | |||
var it = arr[i]; | |||
var label = ''; | |||
var cls = defaultCls; | |||
var checked = false; | |||
var name = ''; | |||
var id = ''; | |||
var disabled = false; | |||
if (typeof it === 'string' || typeof it === 'number') { | |||
label = it; | |||
} else if (typeof it === 'object' && it !== null) { | |||
label = it.label || ''; | |||
cls = (it["class"] || it.cls || defaultCls); | |||
checked = parseBool(it.checked); | |||
name = it.name || ''; | |||
id = it.id || ''; | |||
disabled = parseBool(it.disabled); | |||
} | |||
html += '<span class="js-checkbox-gen-item">'; | |||
html += '<input type="checkbox"'; | |||
if (cls) html += ' class="' + escHtml(cls) + '"'; | |||
if (name) html += ' name="' + escHtml(name) + '"'; | |||
if (id) html += ' id="' + escHtml(id) + '"'; | |||
if (checked) html += ' checked'; | |||
if (disabled) html += ' disabled'; | |||
html += '>'; | |||
html += '<label'; | |||
if (id) html += ' for="' + escHtml(id) + '"'; | |||
html += '>' + escHtml(label) + '</label>'; | |||
html += '</span>'; | |||
} | |||
container.insertAdjacentHTML('beforeend', html); | |||
} else { | |||
var frag = document.createDocumentFragment(); | |||
for (var j = 0; j < arr.length; j++) { | |||
var item = arr[j]; | |||
var labelText = ''; | |||
var itemCls = defaultCls; | |||
var itemChecked = false; | |||
var itemName = ''; | |||
var itemId = ''; | |||
var itemDisabled = false; | |||
if (typeof item === 'string' || typeof item === 'number') { | |||
labelText = item; | |||
} else if (typeof item === 'object' && item !== null) { | |||
labelText = item.label || ''; | |||
itemCls = (item["class"] || item.cls || defaultCls); | |||
itemChecked = parseBool(item.checked); | |||
itemName = item.name || ''; | |||
itemId = item.id || ''; | |||
itemDisabled = parseBool(item.disabled); | |||
} | |||
var wrapper = document.createElement('span'); | |||
wrapper.className = 'js-checkbox-gen-item'; | |||
var input = document.createElement('input'); | |||
input.type = 'checkbox'; | |||
if (itemCls) input.className = itemCls; | |||
if (itemName) input.name = itemName; | |||
if (itemId) input.id = itemId; | |||
if (itemChecked) input.checked = true; | |||
if (itemDisabled) input.disabled = true; | |||
var labelEl = document.createElement('label'); | |||
if (itemId) labelEl.htmlFor = itemId; | |||
labelEl.textContent = labelText; | |||
wrapper.appendChild(input); | |||
wrapper.appendChild(labelEl); | |||
frag.appendChild(wrapper); | |||
} | } | ||
container.appendChild(frag); | |||
} | |||
} else { | } else { | ||
var singleLabel = container.getAttribute('data-cbox-label') || ''; | |||
var singleCls = container.getAttribute('data-cbox-class') || ''; | |||
var singleChecked = parseBool(container.getAttribute('data-cbox-checked')); | |||
var singleName = container.getAttribute('data-cbox-name') || ''; | |||
var singleId = container.getAttribute('data-cbox-id') || ''; | |||
var singleDisabled = parseBool(container.getAttribute('data-cbox-disabled')); | |||
var w = document.createElement('span'); | |||
w.className = 'js-checkbox-gen-item'; | |||
var inp = document.createElement('input'); | |||
inp.type = 'checkbox'; | |||
if (singleCls) inp.className = singleCls; | |||
if (singleName) inp.name = singleName; | |||
if (singleId) inp.id = singleId; | |||
if (singleChecked) inp.checked = true; | |||
if (singleDisabled) inp.disabled = true; | |||
var lab = document.createElement('label'); | |||
if (singleId) lab.htmlFor = singleId; | |||
lab.textContent = singleLabel; | |||
w.appendChild(inp); | |||
w.appendChild(lab); | |||
container.appendChild(w); | |||
} | } | ||
container. | container.setAttribute('data-checkbox-initialized', '1'); | ||
} | } | ||
} | } | ||
// Привязка expand/collapse к чекбоксу по id | // Привязка expand/collapse к чекбоксу по id | ||
function registerCheckboxExpander(checkboxId, options) { | function registerCheckboxExpander(checkboxId, options) { | ||
options = options || {}; | |||
// если нужно — использовать только expand (по умолчанию false = делаем и collapse) | |||
var onlyExpand = !!options.onlyExpand; | |||
var checkbox = document.getElementById(checkboxId); | |||
if (!checkbox) { | |||
// Если чекбокс ещё не на странице — попробуем навесить через делегирование (MutationObserver опционально) | |||
console.warn('registerCheckboxExpander: checkbox not found by id:', checkboxId); | |||
return; | |||
} | |||
function expandAll() { | |||
var collapsed = document.querySelectorAll('.mw-collapsed'); | |||
for (var i = 0; i < collapsed.length; i++) { | |||
collapsed[i].classList.remove('mw-collapsed'); | |||
} | |||
var togglesCollapsed = document.querySelectorAll('.mw-collapsible-toggle-collapsed'); | |||
for (var j = 0; j < togglesCollapsed.length; j++) { | |||
togglesCollapsed[j].classList.remove('mw-collapsible-toggle-collapsed'); | |||
togglesCollapsed[j].classList.add('mw-collapsible-toggle-expanded'); | |||
} | |||
var contents = document.querySelectorAll('.mw-collapsible-content'); | |||
for (var k = 0; k < contents.length; k++) { | |||
if (contents[k].style && contents[k].style.display) { | |||
contents[k].style.removeProperty('display'); | |||
} | |||
} | |||
} | |||
function collapseAll() { | |||
var collapsibleContainers = document.querySelectorAll('.mw-collapsible'); | |||
for (var i = 0; i < collapsibleContainers.length; i++) { | |||
var el = collapsibleContainers[i]; | |||
if (!el.classList.contains('mw-collapsed')) el.classList.add('mw-collapsed'); | |||
} | |||
var togglesExpanded = document.querySelectorAll('.mw-collapsible-toggle-expanded'); | |||
for (var j = 0; j < togglesExpanded.length; j++) { | |||
togglesExpanded[j].classList.remove('mw-collapsible-toggle-expanded'); | |||
togglesExpanded[j].classList.add('mw-collapsible-toggle-collapsed'); | |||
} | |||
var contents = document.querySelectorAll('.mw-collapsible-content'); | |||
for (var k = 0; k < contents.length; k++) { | |||
contents[k].style.setProperty('display', 'none', 'important'); | |||
} | |||
} | |||
checkbox.addEventListener('change', function (e) { | |||
if (checkbox.checked) { | |||
try { expandAll(); } catch (err) { console.error(err); } | |||
} else { | |||
if (!onlyExpand) { | |||
try { collapseAll(); } catch (err) { console.error(err); } | |||
} | |||
} | |||
}); | |||
if (checkbox.checked) { | |||
try { expandAll(); } catch (err) { console.error(err); } | |||
} | |||
} | } | ||
const currentPageTitle = document.title; | const currentPageTitle = document.title; | ||