MediaWiki:Common.js

From TimeRO Wiki
Revision as of 16:34, 13 April 2026 by Admin (talk | contribs)
Jump to navigation Jump to search

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)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* Any JavaScript here will be loaded for all users on every page load. */
(function ($, mw) {
	'use strict';

	function setLogoHref() {
		var logoLink = document.querySelector('#p-logo a');
		if (logoLink) {
			logoLink.setAttribute('href', 'https://timero.com.br/');
		}
	}

	function ensureFontAwesome() {
		if (!document.querySelector('link[data-timero-fa]')) {
			var fa = document.createElement('link');
			fa.rel = 'stylesheet';
			fa.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css';
			fa.setAttribute('data-timero-fa', '1');
			document.head.appendChild(fa);
		}
	}

	/* =========================
	   ROUTES
	========================= */

	function resetRoutePill(pill) {
		if (!pill) return;
		pill.style.transform = '';
		pill.style.fontWeight = '800';
		pill.style.boxShadow = 'none';
		pill.style.filter = 'none';
	}

	function activateRoutePill(pill) {
		if (!pill) return;
		pill.style.transform = 'translateY(-1px)';
		pill.style.fontWeight = '900';
		pill.style.boxShadow = '0 0 0 1px rgba(255,255,255,0.05) inset, 0 0 22px rgba(255,255,255,0.05)';
		pill.style.filter = 'brightness(1.08)';
	}

	function closeAllRoutes(section) {
		if (!section) return;

		var details = section.querySelectorAll('.route-detail');
		for (var i = 0; i < details.length; i++) {
			details[i].style.display = 'none';
		}

		var pills = section.querySelectorAll('.route-pill[data-route]');
		for (var j = 0; j < pills.length; j++) {
			resetRoutePill(pills[j]);
		}

		section.setAttribute('data-open-route', '');
	}

	window.expandRoute = function (routeId) {
		var section = document.getElementById('routes-section');
		if (!section) return;

		var target = document.getElementById(routeId);
		if (!target) return;

		var currentOpen = section.getAttribute('data-open-route');

		if (currentOpen === routeId) {
			closeAllRoutes(section);
			return;
		}

		closeAllRoutes(section);

		target.style.display = 'block';
		target.style.animation = 'route-in 0.3s ease both';
		section.setAttribute('data-open-route', routeId);

		var activePill = document.getElementById('pill-' + routeId);
		activateRoutePill(activePill);

		if (typeof target.scrollIntoView === 'function') {
			setTimeout(function () {
				target.scrollIntoView({
					behavior: 'smooth',
					block: 'nearest'
				});
			}, 80);
		}
	};

	function bindRouteViewer(context) {
		var scope = context && context.querySelector ? context : document;
		var section = scope.querySelector('#routes-section') || document.getElementById('routes-section');
		if (!section) return;

		var pills = section.querySelectorAll('.route-pill[data-route]');
		for (var i = 0; i < pills.length; i++) {
			var pill = pills[i];
			if (pill.dataset.timeroBound === '1') continue;

			pill.dataset.timeroBound = '1';
			pill.setAttribute('role', 'button');
			pill.setAttribute('tabindex', '0');

			pill.addEventListener('click', function () {
				expandRoute(this.getAttribute('data-route'));
			});

			pill.addEventListener('keydown', function (e) {
				if (e.key === 'Enter' || e.key === ' ') {
					e.preventDefault();
					expandRoute(this.getAttribute('data-route'));
				}
			});
		}

		var closeButtons = section.querySelectorAll('.route-close[data-route]');
		for (var j = 0; j < closeButtons.length; j++) {
			var closeBtn = closeButtons[j];
			if (closeBtn.dataset.timeroBound === '1') continue;

			closeBtn.dataset.timeroBound = '1';
			closeBtn.setAttribute('role', 'button');
			closeBtn.setAttribute('tabindex', '0');

			closeBtn.addEventListener('click', function () {
				expandRoute(this.getAttribute('data-route'));
			});

			closeBtn.addEventListener('keydown', function (e) {
				if (e.key === 'Enter' || e.key === ' ') {
					e.preventDefault();
					expandRoute(this.getAttribute('data-route'));
				}
			});
		}
	}

	/* =========================
	   METHODS
	========================= */

	function resetMethodTab(tab, type) {
		if (!tab) return;

		tab.style.background = 'transparent';
		tab.style.fontWeight = '700';

		if (type === 'grind') tab.style.color = 'rgba(249,197,0,0.60)';
		if (type === 'market') tab.style.color = 'rgba(0,212,255,0.60)';
		if (type === 'passive') tab.style.color = 'rgba(176,108,255,0.60)';
	}

	function activateMethodTab(tab, type) {
		if (!tab) return;

		tab.style.fontWeight = '900';

		if (type === 'grind') {
			tab.style.background = 'linear-gradient(135deg,rgba(249,197,0,0.18),rgba(249,197,0,0.07))';
			tab.style.color = '#f9c500';
		}

		if (type === 'market') {
			tab.style.background = 'linear-gradient(135deg,rgba(0,212,255,0.14),rgba(0,212,255,0.05))';
			tab.style.color = '#00d4ff';
		}

		if (type === 'passive') {
			tab.style.background = 'linear-gradient(135deg,rgba(176,108,255,0.14),rgba(176,108,255,0.05))';
			tab.style.color = '#b06cff';
		}
	}

	window.switchMethod = function (methodId) {
		var section = document.getElementById('methods-section');
		if (!section) return;

		var panels = section.querySelectorAll('.method-panel');
		for (var i = 0; i < panels.length; i++) {
			panels[i].style.display = 'none';
		}

		var tabs = section.querySelectorAll('.method-tab[data-method]');
		for (var j = 0; j < tabs.length; j++) {
			resetMethodTab(tabs[j], tabs[j].getAttribute('data-method'));
		}

		var activePanel = document.getElementById('method-' + methodId);
		if (activePanel) {
			activePanel.style.display = 'grid';
			activePanel.style.animation = 'method-in 0.3s ease both';
		}

		var activeTab = document.getElementById('mtab-' + methodId);
		activateMethodTab(activeTab, methodId);

		section.setAttribute('data-open-method', methodId);
	};

	function bindMethodViewer(context) {
		var scope = context && context.querySelector ? context : document;
		var section = scope.querySelector('#methods-section') || document.getElementById('methods-section');
		if (!section) return;

		var tabs = section.querySelectorAll('.method-tab[data-method]');
		for (var i = 0; i < tabs.length; i++) {
			var tab = tabs[i];
			if (tab.dataset.timeroBound === '1') continue;

			tab.dataset.timeroBound = '1';
			tab.setAttribute('role', 'button');
			tab.setAttribute('tabindex', '0');

			tab.addEventListener('click', function () {
				switchMethod(this.getAttribute('data-method'));
			});

			tab.addEventListener('keydown', function (e) {
				if (e.key === 'Enter' || e.key === ' ') {
					e.preventDefault();
					switchMethod(this.getAttribute('data-method'));
				}
			});
		}

		if (!section.getAttribute('data-open-method')) {
			switchMethod('grind');
		}
	}

	/* =========================
	   CALCULATOR
	========================= */

	var calcState = {
		hours: 2,
		booster: false,
		weeklyTarget: 12000
	};

	function formatMillions(value) {
		var rounded = Math.round(value * 10) / 10;

		if (rounded >= 1000) {
			var billions = rounded / 1000;
			var bText = (Math.round(billions * 10) / 10).toString().replace('.0', '').replace('.', ',');
			return bText + 'B z';
		}

		var mText = rounded.toString().replace('.0', '').replace('.', ',');
		return mText + 'M z';
	}

	window.adjustCalc = function (field, delta) {
		if (field !== 'hours') return;
		calcState.hours = Math.max(0.5, Math.min(24, calcState.hours + delta));
		updateCalc();
	};

	window.setBooster = function (enabled) {
		calcState.booster = !!enabled;
		updateCalc();
	};

	window.updateCalc = function () {
		var section = document.getElementById('calculator-section');
		if (!section) return;

		var hoursEl = document.getElementById('calc-hours');
		var methodEl = document.getElementById('calc-method');
		var resultSession = document.getElementById('result-session');
		var resultDay = document.getElementById('result-day');
		var resultWeek = document.getElementById('result-week');
		var resultPct = document.getElementById('result-pct');
		var resultBar = document.getElementById('result-bar');
		var boostNo = document.getElementById('boost-no');
		var boostYes = document.getElementById('boost-yes');

		if (!hoursEl || !methodEl || !resultSession || !resultDay || !resultWeek || !resultPct || !resultBar || !boostNo || !boostYes) {
			return;
		}

		var baseRate = parseFloat(methodEl.value || '0');
		var effectiveRate = calcState.booster ? baseRate * 1.5 : baseRate;
		var session = calcState.hours * effectiveRate;
		var day = session;
		var week = day * 7;
		var pct = Math.max(0, Math.min(100, Math.round((week / calcState.weeklyTarget) * 100)));

		hoursEl.textContent = calcState.hours % 1 === 0 ? String(calcState.hours) : String(calcState.hours).replace('.', ',');
		resultSession.textContent = formatMillions(session);
		resultDay.textContent = formatMillions(day);
		resultWeek.textContent = formatMillions(week);
		resultPct.textContent = pct + '%';
		resultBar.style.width = pct + '%';

		if (calcState.booster) {
			boostNo.style.background = 'rgba(255,255,255,0.04)';
			boostNo.style.borderColor = 'rgba(255,255,255,0.09)';
			boostNo.style.color = 'rgba(122,144,176,0.60)';
			boostNo.style.fontWeight = '700';

			boostYes.style.background = 'rgba(0,212,255,0.15)';
			boostYes.style.borderColor = 'rgba(0,212,255,0.30)';
			boostYes.style.color = '#00d4ff';
			boostYes.style.fontWeight = '800';
		} else {
			boostNo.style.background = 'rgba(255,61,90,0.15)';
			boostNo.style.borderColor = 'rgba(255,61,90,0.30)';
			boostNo.style.color = '#ff3d5a';
			boostNo.style.fontWeight = '800';

			boostYes.style.background = 'rgba(255,255,255,0.04)';
			boostYes.style.borderColor = 'rgba(255,255,255,0.09)';
			boostYes.style.color = 'rgba(122,144,176,0.60)';
			boostYes.style.fontWeight = '700';
		}
	};

	function bindCalculator(context) {
		var scope = context && context.querySelector ? context : document;
		var section = scope.querySelector('#calculator-section') || document.getElementById('calculator-section');
		if (!section) return;

		var adjusters = section.querySelectorAll('[data-calc-adjust]');
		for (var i = 0; i < adjusters.length; i++) {
			var adjuster = adjusters[i];
			if (adjuster.dataset.timeroBound === '1') continue;

			adjuster.dataset.timeroBound = '1';
			adjuster.setAttribute('role', 'button');
			adjuster.setAttribute('tabindex', '0');

			adjuster.addEventListener('click', function () {
				adjustCalc(this.getAttribute('data-calc-adjust'), parseFloat(this.getAttribute('data-delta') || '0'));
			});

			adjuster.addEventListener('keydown', function (e) {
				if (e.key === 'Enter' || e.key === ' ') {
					e.preventDefault();
					adjustCalc(this.getAttribute('data-calc-adjust'), parseFloat(this.getAttribute('data-delta') || '0'));
				}
			});
		}

		var methodSelect = section.querySelector('#calc-method');
		if (methodSelect && methodSelect.dataset.timeroBound !== '1') {
			methodSelect.dataset.timeroBound = '1';
			methodSelect.addEventListener('change', function () {
				updateCalc();
			});
		}

		var boosters = section.querySelectorAll('[data-booster]');
		for (var j = 0; j < boosters.length; j++) {
			var booster = boosters[j];
			if (booster.dataset.timeroBound === '1') continue;

			booster.dataset.timeroBound = '1';
			booster.setAttribute('role', 'button');
			booster.setAttribute('tabindex', '0');

			booster.addEventListener('click', function () {
				setBooster(this.getAttribute('data-booster') === '1');
			});

			booster.addEventListener('keydown', function (e) {
				if (e.key === 'Enter' || e.key === ' ') {
					e.preventDefault();
					setBooster(this.getAttribute('data-booster') === '1');
				}
			});
		}

		updateCalc();
	}

	/* =========================
	   LOADOUT
	========================= */

	function setLoadoutItemState(item, active) {
		var check = item.querySelector('.li-check');
		if (!check) return;

		if (active) {
			item.classList.add('is-active');
			item.style.background = 'rgba(176,108,255,0.08)';
			item.style.borderColor = 'rgba(176,108,255,0.24)';
			item.style.boxShadow = '0 0 0 1px rgba(176,108,255,0.05) inset';
			check.style.background = 'rgba(176,108,255,0.16)';
			check.style.borderColor = 'rgba(176,108,255,0.45)';
			check.style.color = '#b06cff';
			check.innerHTML = '✓';
		} else {
			item.classList.remove('is-active');
			item.style.background = 'rgba(255,255,255,0.03)';
			item.style.borderColor = 'rgba(255,255,255,0.07)';
			item.style.boxShadow = 'none';
			check.style.background = 'rgba(176,108,255,0.04)';
			check.style.borderColor = 'rgba(176,108,255,0.30)';
			check.style.color = 'transparent';
			check.innerHTML = '';
		}
	}

	function updateLoadoutSummary() {
		var section = document.getElementById('loadout-section');
		if (!section) return;

		var items = section.querySelectorAll('.loadout-item');
		var total = 0;
		var count = 0;

		for (var i = 0; i < items.length; i++) {
			if (items[i].classList.contains('is-active')) {
				total += parseFloat(items[i].getAttribute('data-cost') || '0');
				count += 1;
			}
		}

		var totalEl = document.getElementById('loadout-total');
		var countEl = document.getElementById('loadout-count');

		if (totalEl) totalEl.textContent = total + 'k z';
		if (countEl) countEl.textContent = String(count);
	}

	window.toggleLoadout = function (element) {
		if (!element) return;
		var active = !element.classList.contains('is-active');
		setLoadoutItemState(element, active);
		updateLoadoutSummary();
	};

	window.clearLoadout = function () {
		var section = document.getElementById('loadout-section');
		if (!section) return;

		var items = section.querySelectorAll('.loadout-item');
		for (var i = 0; i < items.length; i++) {
			setLoadoutItemState(items[i], false);
		}

		updateLoadoutSummary();
	};

	function bindLoadout(context) {
		var scope = context && context.querySelector ? context : document;
		var section = scope.querySelector('#loadout-section') || document.getElementById('loadout-section');
		if (!section) return;

		var items = section.querySelectorAll('.loadout-item');
		for (var i = 0; i < items.length; i++) {
			var item = items[i];
			if (item.dataset.timeroBound === '1') continue;

			item.dataset.timeroBound = '1';
			item.setAttribute('role', 'button');
			item.setAttribute('tabindex', '0');

			setLoadoutItemState(item, false);

			item.addEventListener('click', function () {
				toggleLoadout(this);
			});

			item.addEventListener('keydown', function (e) {
				if (e.key === 'Enter' || e.key === ' ') {
					e.preventDefault();
					toggleLoadout(this);
				}
			});
		}

		var clearBtn = section.querySelector('.loadout-clear');
		if (clearBtn && clearBtn.dataset.timeroBound !== '1') {
			clearBtn.dataset.timeroBound = '1';
			clearBtn.setAttribute('role', 'button');
			clearBtn.setAttribute('tabindex', '0');

			clearBtn.addEventListener('click', function () {
				clearLoadout();
			});

			clearBtn.addEventListener('keydown', function (e) {
				if (e.key === 'Enter' || e.key === ' ') {
					e.preventDefault();
					clearLoadout();
				}
			});
		}

		updateLoadoutSummary();
	}

	function init(context) {
		setLogoHref();
		ensureFontAwesome();
		bindMethodViewer(context || document);
		bindRouteViewer(context || document);
		bindCalculator(context || document);
		bindLoadout(context || document);
	}

	$(function () {
		init(document);
	});

	if (mw && mw.hook) {
		mw.hook('wikipage.content').add(function ($content) {
			init(($content && $content[0]) || document);
		});
	}
})(jQuery, mediaWiki);