MediaWiki:Common.js: различия между версиями
Страница интерфейса MediaWiki
Дополнительные действия
Mobile redesign |
Mobile redesign |
||
| Строка 222: | Строка 222: | ||
img.setAttribute('fetchpriority', 'high'); | img.setAttribute('fetchpriority', 'high'); | ||
}); | }); | ||
} | |||
function removeNoopServiceWorker() { | |||
if (!('serviceWorker' in navigator) || !navigator.serviceWorker.getRegistrations) { | |||
return; | |||
} | |||
navigator.serviceWorker.getRegistrations().then(function (registrations) { | |||
registrations.forEach(function (registration) { | |||
var url = registration.active && registration.active.scriptURL; | |||
if (url && url.indexOf('skins.citizen.serviceWorker') !== -1) { | |||
registration.unregister(); | |||
} | |||
}); | |||
}).catch(function () {}); | |||
} | } | ||
onReady(function () { | onReady(function () { | ||
document.documentElement.classList.add('bc-ready'); | document.documentElement.classList.add('bc-ready'); | ||
removeNoopServiceWorker(); | |||
prioritizeMedia(); | prioritizeMedia(); | ||
initParticles(); | initParticles(); | ||
Версия от 01:57, 26 мая 2026
(function () {
'use strict';
function onReady(fn) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fn);
return;
}
fn();
}
function loadScript(src, done) {
if (document.querySelector('script[src="' + src + '"]')) {
done();
return;
}
var script = document.createElement('script');
script.src = src;
script.async = true;
script.onload = done;
document.head.appendChild(script);
}
function initParticles() {
var hero = document.querySelector('.bc-hero');
if (!hero || document.getElementById('bc-particles')) {
return;
}
var host = document.createElement('div');
host.id = 'bc-particles';
hero.insertBefore(host, hero.firstChild);
loadScript('https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js', function () {
if (!window.particlesJS) {
return;
}
window.particlesJS('bc-particles', {
particles: {
number: { value: 70, density: { enable: true, value_area: 820 } },
color: { value: ['#1d5f9f', '#e40046', '#2f6f73'] },
shape: { type: 'circle' },
opacity: { value: 0.42, random: true },
size: { value: 4, random: true },
line_linked: {
enable: true,
distance: 150,
color: '#1d5f9f',
opacity: 0.32,
width: 1.35
},
move: {
enable: true,
speed: 1.35,
direction: 'none',
random: true,
straight: false,
out_mode: 'out',
bounce: false
}
},
interactivity: {
detect_on: 'canvas',
events: {
onhover: { enable: true, mode: 'grab' },
onclick: { enable: true, mode: 'push' },
resize: true
},
modes: {
grab: { distance: 150, line_linked: { opacity: 0.26 } },
push: { particles_nb: 3 }
}
},
retina_detect: true
});
});
}
function makeSearchInteractive() {
var slot = document.querySelector('[data-bc-search]');
if (!slot) {
return;
}
var input = document.createElement('input');
input.className = 'bc-search-input';
input.type = 'search';
input.autocomplete = 'off';
input.placeholder = window.innerWidth < 560 ? 'страна, сервис или мера...' : slot.textContent.trim();
input.setAttribute('aria-label', 'Поиск по BRICSCompass');
slot.replaceChildren(input);
slot.classList.add('is-live');
var cards = Array.prototype.slice.call(document.querySelectorAll('.bc-card, .bc-country'));
var tags = Array.prototype.slice.call(document.querySelectorAll('[data-bc-query]'));
var arrow = document.querySelector('.bc-arrow');
function filter(value) {
var query = value.trim().toLowerCase();
cards.forEach(function (card) {
var text = card.textContent.toLowerCase();
var match = !query || text.indexOf(query) !== -1;
card.classList.toggle('is-match', !!query && match);
card.classList.toggle('is-dim', !!query && !match);
});
tags.forEach(function (tag) {
tag.classList.toggle('is-active', query && tag.getAttribute('data-bc-query').toLowerCase() === query);
});
}
input.addEventListener('input', function () {
filter(input.value);
});
tags.forEach(function (tag) {
tag.addEventListener('click', function () {
input.value = tag.getAttribute('data-bc-query') || '';
filter(input.value);
input.focus();
});
});
function getCardLink(card) {
var link = card.closest('a');
if (link && link.href) {
return link.href;
}
return '';
}
function submitSearch() {
var query = input.value.trim().toLowerCase();
var target = null;
if (!query) {
input.focus();
return;
}
cards.some(function (card) {
var titleNode = card.querySelector('strong');
var title = (titleNode || card).textContent.trim().toLowerCase();
var text = card.textContent.trim().toLowerCase();
if (title === query) {
target = card;
return true;
}
if (!target && text.indexOf(query) !== -1) {
target = card;
}
return false;
});
var href = target && getCardLink(target);
if (href) {
window.location.href = href;
return;
}
window.location.href = (mw.config.get('wgScriptPath') || '') + '/index.php?search=' + encodeURIComponent(input.value.trim());
}
input.addEventListener('keydown', function (event) {
if (event.key === 'Enter') {
event.preventDefault();
submitSearch();
}
});
if (arrow) {
arrow.setAttribute('role', 'button');
arrow.setAttribute('tabindex', '0');
arrow.setAttribute('aria-label', 'Найти раздел');
arrow.addEventListener('click', submitSearch);
arrow.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
submitSearch();
}
});
}
}
function animateStats() {
var stats = Array.prototype.slice.call(document.querySelectorAll('.bc-stat-value'));
if (!stats.length || !('IntersectionObserver' in window)) {
return;
}
var observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (!entry.isIntersecting) {
return;
}
var node = entry.target;
var target = parseInt(node.textContent.replace(/\D/g, ''), 10);
if (!target || node.getAttribute('data-animated')) {
return;
}
node.setAttribute('data-animated', 'true');
var start = performance.now();
var duration = 900;
function tick(now) {
var progress = Math.min((now - start) / duration, 1);
var eased = 1 - Math.pow(1 - progress, 3);
node.lastChild.nodeValue = String(Math.round(target * eased));
if (progress < 1) {
requestAnimationFrame(tick);
}
}
node.textContent = '0';
requestAnimationFrame(tick);
observer.unobserve(node);
});
}, { threshold: 0.35 });
stats.forEach(function (stat) {
observer.observe(stat);
});
}
function prioritizeMedia() {
Array.prototype.forEach.call(document.querySelectorAll('.bc-photo img, .bc-section-photo img'), function (img) {
img.loading = 'eager';
img.decoding = 'async';
img.setAttribute('fetchpriority', 'high');
});
}
function removeNoopServiceWorker() {
if (!('serviceWorker' in navigator) || !navigator.serviceWorker.getRegistrations) {
return;
}
navigator.serviceWorker.getRegistrations().then(function (registrations) {
registrations.forEach(function (registration) {
var url = registration.active && registration.active.scriptURL;
if (url && url.indexOf('skins.citizen.serviceWorker') !== -1) {
registration.unregister();
}
});
}).catch(function () {});
}
onReady(function () {
document.documentElement.classList.add('bc-ready');
removeNoopServiceWorker();
prioritizeMedia();
initParticles();
makeSearchInteractive();
animateStats();
});
})();