Jump to content

MediaWiki:Common.js

From WikiPStory
Revision as of 11:13, 14 September 2026 by WikiSysop (talk | contribs) (Corrige o filtro de tipo de conta: comparava "Free" com "free" e zerava a lista)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
(function () {
	function grupo(rotulo, conteudo) {
		var g = document.createElement('div');
		g.className = 'pxgq-filter-group';
		var l = document.createElement('label');
		l.textContent = rotulo;
		g.appendChild(l);
		g.appendChild(conteudo);
		return g;
	}

	function montarFiltros(cards) {
		var regioes = [];
		var contas = [];
		var min = 9999;
		var max = 0;
		cards.forEach(function (c) {
			var r = c.getAttribute('data-region');
			var a = c.getAttribute('data-account');
			if (r && regioes.indexOf(r) === -1) { regioes.push(r); }
			if (a && contas.indexOf(a) === -1) { contas.push(a); }
			min = Math.min(min, parseInt(c.getAttribute('data-level-min') || '0', 10));
			max = Math.max(max, parseInt(c.getAttribute('data-level-max') || '0', 10));
		});
		regioes.sort();
		contas.sort();

		var barra = document.createElement('div');
		barra.className = 'pxgq-filters';

		var busca = document.createElement('input');
		busca.className = 'js-pxgq-search';
		busca.type = 'search';
		busca.placeholder = 'Nome, NPC, recompensa...';
		barra.appendChild(grupo('Buscar', busca));

		var sel = document.createElement('select');
		sel.className = 'js-pxgq-region';
		var todas = document.createElement('option');
		todas.value = 'all';
		todas.textContent = 'Todas as regioes';
		sel.appendChild(todas);
		regioes.forEach(function (r) {
			var o = document.createElement('option');
			o.value = r;
			o.textContent = r;
			sel.appendChild(o);
		});
		barra.appendChild(grupo('Regiao', sel));

		var linha = document.createElement('div');
		linha.className = 'pxgq-level-row';
		var de = document.createElement('input');
		de.className = 'js-pxgq-min';
		de.type = 'number';
		de.placeholder = String(min);
		var ate = document.createElement('input');
		ate.className = 'js-pxgq-max';
		ate.type = 'number';
		ate.placeholder = String(max);
		linha.appendChild(de);
		linha.appendChild(ate);
		barra.appendChild(grupo('Nivel', linha));

		var toggle = document.createElement('div');
		toggle.className = 'pxgq-account-toggle';
		[['all', 'Todas']].concat(contas.map(function (c) { return [c, c]; }))
			.forEach(function (par, i) {
				// <button> de verdade: o CSS estiliza
				// '.pxgq-account-toggle button', e como este elemento nasce no JS
				// ele nao passa pelo sanitizador do wikitext
				var b = document.createElement('button');
				b.type = 'button';
				b.className = 'js-pxgq-account' + (i === 0 ? ' is-active' : '');
				b.setAttribute('data-account', par[0]);
				b.textContent = par[1];
				toggle.appendChild(b);
			});
		barra.appendChild(grupo('Tipo de conta', toggle));

		return barra;
	}

	window.montarFiltros = montarFiltros;
}());

(function () {
	function initQuestPage() {
		var cards = Array.prototype.slice.call(document.querySelectorAll('.pxgq-card'));
		if (!cards.length) {
			return;
		}

		// A barra de filtros e montada aqui, e nao escrita no wikitext, porque o
		// sanitizador do MediaWiki escapa <input>, <select> e <option>. Como ela
		// nasce dos data-* dos cards, as regioes e a faixa de nivel acompanham
		// sozinhas qualquer quest que for acrescentada a pagina.
		var grade = cards[0].parentNode;
		if (!document.querySelector('.js-pxgq-search')) {
			grade.parentNode.insertBefore(montarFiltros(cards), grade);
		}

		// O sanitizador tambem remove o atributo hidden do wikitext (testado),
		// entao o spoiler nasceria aberto. Fecha aqui, na carga.
		document.querySelectorAll('.pxgq-card-spoiler').forEach(function (sp) {
			sp.setAttribute('hidden', 'hidden');
		});

		var searchInput = document.querySelector('.js-pxgq-search');
		var regionSelect = document.querySelector('.js-pxgq-region');
		var minInput = document.querySelector('.js-pxgq-min');
		var maxInput = document.querySelector('.js-pxgq-max');
		var accountButtons = Array.prototype.slice.call(document.querySelectorAll('.js-pxgq-account'));
		var currentAccount = 'all';

		function normalize(value) {
			return (value || '').toLowerCase().trim();
		}

		function applyFilters() {
			var search = normalize(searchInput && searchInput.value);
			var region = normalize(regionSelect && regionSelect.value);
			var min = parseInt((minInput && minInput.value) || '0', 10);
			var max = parseInt((maxInput && maxInput.value) || '9999', 10);

			cards.forEach(function (card) {
				var cardSearch = normalize(card.getAttribute('data-search'));
				var cardRegion = normalize(card.getAttribute('data-region'));
				var cardAccount = normalize(card.getAttribute('data-account'));
				var cardMin = parseInt(card.getAttribute('data-level-min') || '0', 10);
				var cardMax = parseInt(card.getAttribute('data-level-max') || '9999', 10);

				var okSearch = !search || cardSearch.indexOf(search) !== -1;
				var okRegion = region === 'all' || !region || cardRegion === region;
				var okAccount = currentAccount === 'all' || cardAccount === currentAccount;
				var okLevel = cardMax >= min && cardMin <= max;

				card.classList.toggle('is-hidden', !(okSearch && okRegion && okAccount && okLevel));
			});
		}

		if (searchInput) {
			searchInput.addEventListener('input', applyFilters);
		}
		if (regionSelect) {
			regionSelect.addEventListener('change', applyFilters);
		}
		if (minInput) {
			minInput.addEventListener('input', applyFilters);
		}
		if (maxInput) {
			maxInput.addEventListener('input', applyFilters);
		}

		accountButtons.forEach(function (button) {
			button.addEventListener('click', function () {
				accountButtons.forEach(function (btn) {
					btn.classList.remove('is-active');
				});
				button.classList.add('is-active');
				// normalize aqui tambem: cardAccount vem em minusculas, e sem isto
				// 'free' nunca bate com o 'Free' do atributo do botao
				currentAccount = normalize(button.getAttribute('data-account')) || 'all';
				applyFilters();
			});
		});

		document.querySelectorAll('.js-pxgq-spoiler').forEach(function (button) {
			button.addEventListener('click', function () {
				var card = button.closest('.pxgq-card');
				if (!card) {
					return;
				}
				var spoiler = card.querySelector('.pxgq-card-spoiler');
				if (!spoiler) {
					return;
				}
				var isHidden = spoiler.hasAttribute('hidden');
				if (isHidden) {
					spoiler.removeAttribute('hidden');
					button.textContent = 'Ocultar spoiler';
				} else {
					spoiler.setAttribute('hidden', 'hidden');
					button.textContent = 'Ver spoiler';
				}
			});
		});

		applyFilters();
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', initQuestPage);
	} else {
		initQuestPage();
	}
}());

/* =========================================================================
   Fichas de Campeao do Champion's Path  (Module:Campeao)
   Duas coisas: as abas de dificuldade e o alternador de tema.
   Tudo degrada bem sem JS: sem script, a ficha mostra a dificuldade Normal
   e o botao de tema permanece oculto.
   ========================================================================= */
(function () {
	'use strict';

	var CHAVE_TEMA = 'pst-cp-tema';

	function trocarDificuldade(ficha, dif) {
		var i;
		var abas = ficha.querySelectorAll('.cp-tab');
		for (i = 0; i < abas.length; i++) {
			if (abas[i].getAttribute('data-dif') === dif) {
				abas[i].classList.add('is-active');
			} else {
				abas[i].classList.remove('is-active');
			}
		}
		var blocos = ficha.querySelectorAll('[data-dif]');
		for (i = 0; i < blocos.length; i++) {
			if (blocos[i].classList.contains('cp-tab')) continue;
			if (blocos[i].getAttribute('data-dif') === dif) {
				blocos[i].classList.remove('is-hidden');
			} else {
				blocos[i].classList.add('is-hidden');
			}
		}
	}

	function aplicarTema(ficha, tema) {
		ficha.setAttribute('data-tema', tema);
		var botao = ficha.querySelector('[data-cp-tema]');
		if (botao) {
			botao.textContent = tema === 'escuro' ? 'Modo claro' : 'Modo escuro';
		}
	}

	// Seletor de habilidade: troca o detalhe exibido dentro de um grupo.
	function ligarSeletorDeHabilidade(grupo) {
		var picks = grupo.querySelectorAll('.cp-skill-pick');
		for (var i = 0; i < picks.length; i++) {
			picks[i].addEventListener('click', function () {
				var alvo = this.getAttribute('data-skill');
				var j;
				for (j = 0; j < picks.length; j++) {
					if (picks[j].getAttribute('data-skill') === alvo) {
						picks[j].classList.add('is-active');
					} else {
						picks[j].classList.remove('is-active');
					}
				}
				var dets = grupo.querySelectorAll('.cp-skill-detail');
				for (j = 0; j < dets.length; j++) {
					if (dets[j].getAttribute('data-skill') === alvo) {
						dets[j].classList.remove('is-hidden');
					} else {
						dets[j].classList.add('is-hidden');
					}
				}
			});
		}
	}

	function iniciar(ficha) {
		// Seletor de habilidade, um por dificuldade
		var grupos = ficha.querySelectorAll('.cp-skills');
		for (var g = 0; g < grupos.length; g++) {
			ligarSeletorDeHabilidade(grupos[g]);
		}

		// Abas de dificuldade
		var abas = ficha.querySelectorAll('.cp-tab');
		for (var i = 0; i < abas.length; i++) {
			abas[i].addEventListener('click', function () {
				trocarDificuldade(ficha, this.getAttribute('data-dif'));
			});
		}

		// Alternador de tema: so aparece se o JS rodou
		var botao = ficha.querySelector('[data-cp-tema]');
		if (botao) {
			botao.style.display = '';
			var salvo = 'claro';
			try {
				salvo = window.localStorage.getItem(CHAVE_TEMA) || 'claro';
			} catch (e) {}
			aplicarTema(ficha, salvo);

			botao.addEventListener('click', function () {
				var novo = ficha.getAttribute('data-tema') === 'escuro' ? 'claro' : 'escuro';
				aplicarTema(ficha, novo);
				try {
					window.localStorage.setItem(CHAVE_TEMA, novo);
				} catch (e) {}
			});
		}
	}

	function pronto() {
		var fichas = document.querySelectorAll('.cp-boss');
		for (var i = 0; i < fichas.length; i++) {
			iniciar(fichas[i]);
		}
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', pronto);
	} else {
		pronto();
	}
}());