미디어위키:Gadget-Vector.js

식물 vs 좀비 위키
Brokey (토론 | 기여)님의 2026년 7월 30일 (목) 00:30 판
둘러보기로 이동 검색으로 이동

참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.

  • 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
  • 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
  • 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
(function () {
	'use strict';

	var SPIN_CLASS = 'pvz-watch-spinning';
	var WATCHED_CLASS = 'pvz-watch-watched';
	var NOT_WATCHED_CLASS = 'pvz-watch-not-watched';
	var SPIN_TIME = 360;
	var cleanupTimer = 0;

	function getContainer() {
		return document.querySelector(
			'#ca-watch, #ca-unwatch, li.mw-watchlink, a.mw-watchlink'
		);
	}

	function getLink(container) {
		if (!container) {
			return null;
		}

		return container.matches('a') ? container : container.querySelector('a');
	}

	function applyState(isWatched) {
		var container = getContainer();

		if (!container) {
			return;
		}

		container.classList.toggle(WATCHED_CLASS, !!isWatched);
		container.classList.toggle(NOT_WATCHED_CLASS, !isWatched);
	}

	function syncFromMarkup() {
		var container = getContainer();
		var link = getLink(container);
		var href;

		if (!container || !link) {
			return;
		}

		href = link.getAttribute('href') || '';

		applyState(
			container.id === 'ca-unwatch' ||
			href.indexOf('action=unwatch') !== -1
		);
	}

	function spin() {
		var container = getContainer();

		if (!container) {
			return;
		}

		window.clearTimeout(cleanupTimer);
		container.classList.remove(SPIN_CLASS);
		void container.offsetWidth;
		container.classList.add(SPIN_CLASS);

		cleanupTimer = window.setTimeout(function () {
			container.classList.remove(SPIN_CLASS);
		}, SPIN_TIME + 40);
	}

	function handleClick(event) {
		var link = event.target.closest(
			'#ca-watch > a, #ca-unwatch > a, li.mw-watchlink > a, a.mw-watchlink'
		);

		if (link) {
			spin();
		}
	}

	function shortenHistoryLabel() {
		var historyLink = document.querySelector('#ca-history > a');

		if (!historyLink) {
			return;
		}

		Array.prototype.forEach.call(historyLink.childNodes, function (node) {
			if (node.nodeType === Node.TEXT_NODE) {
				node.nodeValue = node.nodeValue.replace(/역사 보기/g, '역사');
			}
		});

		if (historyLink.textContent.trim() === '역사 보기') {
			historyLink.textContent = '역사';
		}

		historyLink.setAttribute('title', '역사');
	}

	function init() {
		var observer;

		shortenHistoryLabel();
		syncFromMarkup();
		document.addEventListener('click', handleClick, true);

		observer = new MutationObserver(function () {
			shortenHistoryLabel();
			syncFromMarkup();
		});

		observer.observe(document.body, {
			subtree: true,
			childList: true,
			attributes: true,
			attributeFilter: ['id', 'href']
		});

		if (window.mw && mw.hook) {
			mw.hook('wikipage.watchlistChange').add(function (isWatched) {
				applyState(isWatched);
				spin();
			});
		}
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', init, { once: true });
	} else {
		init();
	}
}());


(function () {
	'use strict';

	function installSearchButtonIcon(wrapper) {
		var simpleSearch;
		var searchButton;
		var icon;

		if (!wrapper) {
			return;
		}

		simpleSearch = wrapper.querySelector('#simpleSearch');

		if (!simpleSearch) {
			return;
		}

		searchButton =
			simpleSearch.querySelector('#searchButton') ||
			simpleSearch.querySelector('.searchButton:not(#mw-searchButton)');

		if (!searchButton) {
			return;
		}

		searchButton.classList.add('pvz-primary-search-button');

		icon = simpleSearch.querySelector('.pvz-search-button-icon');

		if (!icon) {
			icon = document.createElement('span');
			icon.className = 'pvz-search-button-icon';
			icon.setAttribute('aria-hidden', 'true');
			simpleSearch.appendChild(icon);
		}
	}

	function installTopSearch() {
		var content = document.querySelector('.skin-vector-legacy #content');
		var form = document.querySelector('#searchform');
		var wrapper;

		if (!content || !form || !document.body) {
			return;
		}

		wrapper = document.getElementById('pvz-content-search');

		if (!wrapper) {
			wrapper = document.createElement('div');
			wrapper.id = 'pvz-content-search';
			wrapper.setAttribute('role', 'search');
			wrapper.setAttribute('aria-label', '사이트 검색');
		}

		if (wrapper.parentNode !== document.body) {
			document.body.insertBefore(wrapper, content);
		}

		if (form.parentNode !== wrapper) {
			wrapper.appendChild(form);
		}

		installSearchButtonIcon(wrapper);
		document.documentElement.classList.add('pvz-content-search-ready');
	}

	function initTopSearch() {
		var observer;

		installTopSearch();

		observer = new MutationObserver(function () {
			installTopSearch();
		});

		observer.observe(document.body, {
			childList: true,
			subtree: true
		});
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', initTopSearch, { once: true });
	} else {
		initTopSearch();
	}
}());


(function () {
	'use strict';

	function syncSearchLeft() {
		var content = document.querySelector('.skin-vector-legacy #content');
		var left;

		if (!content) {
			return;
		}

		left = content.getBoundingClientRect().left + window.scrollX;
		document.documentElement.style.setProperty('--pvz-content-left', left + 'px');
	}

	function initSearchAlignment() {
		syncSearchLeft();
		window.addEventListener('resize', syncSearchLeft, { passive: true });
		window.addEventListener('orientationchange', syncSearchLeft, { passive: true });
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', initSearchAlignment, { once: true });
	} else {
		initSearchAlignment();
	}
}());


(function () {
	'use strict';

	function removeObsoleteInterface() {
		var ids = [
			'pvz-related-toggle',
			'pvz-related-menu',
			'pvz-right-panel',
			'pvz-left-panel-toggle',
			'pvz-right-panel-toggle'
		];

		ids.forEach(function (id) {
			var element = document.getElementById(id);

			if (element) {
				element.remove();
			}
		});
	}

	function restoreLogoToPanel(panel) {
		var wrapper = document.getElementById('pvz-sidebar-logo');
		var logo =
			(wrapper && wrapper.querySelector('#p-logo')) ||
			document.querySelector('#p-logo');

		if (!panel || !logo) {
			return;
		}

		if (logo.parentNode !== panel) {
			panel.insertBefore(logo, panel.firstChild);
		}

		if (wrapper) {
			wrapper.remove();
		}
	}

	function syncPanelTop() {
		var content = document.querySelector('.skin-vector-legacy #content');
		var top;

		if (!content) {
			return;
		}

		top = content.getBoundingClientRect().top + window.scrollY;
		document.documentElement.style.setProperty('--pvz-content-top', top + 'px');
	}

	function syncSearchLeft() {
		var content = document.querySelector('.skin-vector-legacy #content');
		var left;

		if (!content) {
			return;
		}

		left = content.getBoundingClientRect().left + window.scrollX;
		document.documentElement.style.setProperty('--pvz-content-left', left + 'px');
	}

	function installV27Interface() {
		var panel = document.querySelector('.skin-vector-legacy #mw-panel');

		removeObsoleteInterface();
		restoreLogoToPanel(panel);
		syncPanelTop();
		syncSearchLeft();
	}

	function initV27Interface() {
		installV27Interface();

		window.addEventListener('resize', function () {
			syncPanelTop();
			syncSearchLeft();
		}, { passive: true });

		window.addEventListener('orientationchange', function () {
			syncPanelTop();
			syncSearchLeft();
		}, { passive: true });
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', initV27Interface, { once: true });
	} else {
		initV27Interface();
	}
}());


(function () {
	'use strict';

	function syncRightNavigation() {
		var content = document.querySelector('#content');
		var navigation = document.getElementById('right-navigation');
		var views;
		var actions;
		var rightGap;

		if (!content || !navigation) {
			return;
		}

		rightGap = Math.max(
			0,
			window.innerWidth - content.getBoundingClientRect().right
		);

		document.documentElement.style.setProperty(
			'--pvz-content-right-gap',
			rightGap + 'px'
		);

		navigation.style.setProperty('position', 'absolute', 'important');
		navigation.style.setProperty('top', '30px', 'important');
		navigation.style.setProperty('right', rightGap + 'px', 'important');
		navigation.style.setProperty('left', 'auto', 'important');
		navigation.style.setProperty('display', 'flex', 'important');
		navigation.style.setProperty('justify-content', 'flex-end', 'important');
		navigation.style.setProperty('align-items', 'flex-end', 'important');
		navigation.style.setProperty('width', 'max-content', 'important');
		navigation.style.setProperty('float', 'none', 'important');
		navigation.style.setProperty('margin', '0', 'important');
		navigation.style.setProperty('transform', 'none', 'important');

		views = navigation.querySelector('#p-views');
		actions = navigation.querySelector('#p-cactions');

		[views, actions].forEach(function (menu) {
			if (!menu) {
				return;
			}

			menu.style.setProperty('float', 'none', 'important');
			menu.style.setProperty('right', 'auto', 'important');
			menu.style.setProperty('left', 'auto', 'important');
			menu.style.setProperty('margin-right', '0', 'important');
			menu.style.setProperty('transform', 'none', 'important');
		});
	}

	function initRightNavigationAlignment() {
		var observer;

		syncRightNavigation();

		window.addEventListener('resize', syncRightNavigation, { passive: true });
		window.addEventListener(
			'orientationchange',
			syncRightNavigation,
			{ passive: true }
		);

		observer = new MutationObserver(function () {
			window.requestAnimationFrame(syncRightNavigation);
		});

		observer.observe(document.body, {
			childList: true,
			subtree: true
		});
	}

	if (document.readyState === 'loading') {
		document.addEventListener(
			'DOMContentLoaded',
			initRightNavigationAlignment,
			{ once: true }
		);
	} else {
		initRightNavigationAlignment();
	}
}());


(function () {
	'use strict';

	function syncV32Navigation() {
		var content = document.querySelector('#content');
		var leftNavigation = document.getElementById('left-navigation');
		var rightNavigation = document.getElementById('right-navigation');
		var rightGap;
		var navigationTop;

		if (!content || !leftNavigation || !rightNavigation) {
			return;
		}

		rightGap = Math.max(
			0,
			window.innerWidth - content.getBoundingClientRect().right
		);

		navigationTop =
			leftNavigation.getBoundingClientRect().top +
			window.scrollY;

		document.documentElement.style.setProperty(
			'--pvz-content-right-gap',
			rightGap + 'px'
		);

		document.documentElement.style.setProperty(
			'--pvz-navigation-top',
			navigationTop + 'px'
		);

		rightNavigation.style.setProperty(
			'top',
			navigationTop + 'px',
			'important'
		);

		rightNavigation.style.setProperty(
			'right',
			(rightGap + 15) + 'px',
			'important'
		);

		rightNavigation.style.setProperty(
			'left',
			'auto',
			'important'
		);
	}

	function initV32Navigation() {
		var observer;

		syncV32Navigation();

		window.addEventListener(
			'resize',
			syncV32Navigation,
			{ passive: true }
		);

		window.addEventListener(
			'orientationchange',
			syncV32Navigation,
			{ passive: true }
		);

		observer = new MutationObserver(function () {
			window.requestAnimationFrame(syncV32Navigation);
		});

		observer.observe(document.body, {
			childList: true,
			subtree: true
		});
	}

	if (document.readyState === 'loading') {
		document.addEventListener(
			'DOMContentLoaded',
			initV32Navigation,
			{ once: true }
		);
	} else {
		initV32Navigation();
	}
}());