No edit summary |
No edit summary |
||
| Line 6: | Line 6: | ||
============================================================ */ | ============================================================ */ | ||
(function() { | (function() { | ||
var saved = localStorage.getItem('flatmmo-theme') || 'dark'; | var saved = localStorage.getItem('flatmmo-theme') || 'dark'; | ||
document.documentElement.className += ' ' + saved + '-theme'; | document.documentElement.className += ' ' + saved + '-theme'; | ||
var searchMode = localStorage.getItem('flatmmo-search') || 'top'; | var searchMode = localStorage.getItem('flatmmo-search') || 'top'; | ||
document.documentElement.className += ' search-' + searchMode; | document.documentElement.className += ' search-' + searchMode; | ||
| Line 27: | Line 25: | ||
var currentTheme = localStorage.getItem('flatmmo-theme') || 'dark'; | var currentTheme = localStorage.getItem('flatmmo-theme') || 'dark'; | ||
document.body.classList.remove('dark-theme', 'light-theme'); | document.body.classList.remove('dark-theme', 'light-theme'); | ||
document.body.classList.add(currentTheme + '-theme'); | document.body.classList.add(currentTheme + '-theme'); | ||
var btn = document.createElement('button'); | var btn = document.createElement('button'); | ||
btn.className = 'theme-toggle-btn'; | btn.className = 'theme-toggle-btn'; | ||
| Line 50: | Line 46: | ||
}); | }); | ||
var target = document.querySelector('.cosmos-header__wiki-buttons') | var target = document.querySelector('.cosmos-header__wiki-buttons') | ||
|| document.querySelector('.cosmos-actions') | || document.querySelector('.cosmos-actions') | ||
| Line 57: | Line 52: | ||
if (target) { | if (target) { | ||
if (target.id === 'content') { | if (target.id === 'content') { | ||
target.insertBefore(btn, target.firstChild); | target.insertBefore(btn, target.firstChild); | ||
} else { | } else { | ||
| Line 70: | Line 64: | ||
var searchMode = localStorage.getItem('flatmmo-search') || 'top'; | var searchMode = localStorage.getItem('flatmmo-search') || 'top'; | ||
document.body.classList.remove('search-top', 'search-header'); | document.body.classList.remove('search-top', 'search-header'); | ||
document.body.classList.add('search-' + searchMode); | document.body.classList.add('search-' + searchMode); | ||
if (searchMode === 'header') { | if (searchMode === 'header') { | ||
window.scrollTo(0, 0); | window.scrollTo(0, 0); | ||
| Line 82: | Line 74: | ||
} | } | ||
var searchToggle = document.createElement('button'); | var searchToggle = document.createElement('button'); | ||
searchToggle.className = 'search-toggle-btn'; | searchToggle.className = 'search-toggle-btn'; | ||
| Line 101: | Line 92: | ||
}); | }); | ||
var searchWrap = document.createElement('div'); | var searchWrap = document.createElement('div'); | ||
searchWrap.className = 'header-search-wrap'; | searchWrap.className = 'header-search-wrap'; | ||
| Line 131: | Line 121: | ||
searchWrap.appendChild(searchBtn); | searchWrap.appendChild(searchBtn); | ||
var target = document.querySelector('.cosmos-header__wiki-buttons') | var target = document.querySelector('.cosmos-header__wiki-buttons') | ||
|| document.querySelector('.cosmos-actions') | || document.querySelector('.cosmos-actions') | ||
| Line 138: | Line 127: | ||
if (target && target.id !== 'content') { | if (target && target.id !== 'content') { | ||
target.appendChild(searchToggle); | target.appendChild(searchToggle); | ||
target.style.position = 'relative'; | target.style.position = 'relative'; | ||
target.appendChild(searchWrap); | target.appendChild(searchWrap); | ||
var bannerUser = document.querySelector('.cosmos-userButton-label') | var bannerUser = document.querySelector('.cosmos-userButton-label') | ||
|| document.querySelector('#p-personal-label'); | || document.querySelector('#p-personal-label'); | ||
| Line 401: | Line 388: | ||
document.addEventListener('DOMContentLoaded', function() { | document.addEventListener('DOMContentLoaded', function() { | ||
var content = document.getElementById('mw-content-text') || document.getElementById('bodyContent') || document.body; | var content = document.getElementById('mw-content-text') || document.getElementById('bodyContent') || document.body; | ||
// Remove all default browser tooltips from content links | |||
content.querySelectorAll('a[title]').forEach(function(a) { a.removeAttribute('title'); }); | |||
content.addEventListener('mouseover', function(e) { | content.addEventListener('mouseover', function(e) { | ||
| Line 411: | Line 401: | ||
if (link.getAttribute('title')) { | if (link.getAttribute('title')) { | ||
link.removeAttribute('title'); | link.removeAttribute('title'); | ||
} | } | ||
| Line 425: | Line 414: | ||
clearTimeout(showTimer); | clearTimeout(showTimer); | ||
hideTimer = setTimeout(function() { | hideTimer = setTimeout(function() { | ||
Revision as of 05:02, 18 February 2026
1 /* Any JavaScript here will be loaded for all users on every page load. */
2
3 /* ============================================================
4 THEME TOGGLE — Dark/Light mode switcher
5 Defaults to dark. Saves preference to localStorage.
6 ============================================================ */
7 (function() {
8 var saved = localStorage.getItem('flatmmo-theme') || 'dark';
9 document.documentElement.className += ' ' + saved + '-theme';
10
11 var searchMode = localStorage.getItem('flatmmo-search') || 'top';
12 document.documentElement.className += ' search-' + searchMode;
13
14 document.addEventListener('DOMContentLoaded', function() {
15 document.body.classList.add(saved + '-theme');
16 document.body.classList.add('search-' + searchMode);
17 });
18 })();
19
20 $(document).ready(function () {
21 console.log("loaded");
22
23 // --- Theme toggle button ---
24 (function() {
25 var currentTheme = localStorage.getItem('flatmmo-theme') || 'dark';
26
27 document.body.classList.remove('dark-theme', 'light-theme');
28 document.body.classList.add(currentTheme + '-theme');
29
30 var btn = document.createElement('button');
31 btn.className = 'theme-toggle-btn';
32 btn.title = 'Toggle light/dark mode';
33 btn.textContent = currentTheme === 'dark' ? '☀️' : '🌙';
34
35 btn.addEventListener('click', function() {
36 var isDark = document.body.classList.contains('dark-theme');
37 var newTheme = isDark ? 'light' : 'dark';
38
39 document.body.classList.remove('dark-theme', 'light-theme');
40 document.body.classList.add(newTheme + '-theme');
41 document.documentElement.classList.remove('dark-theme', 'light-theme');
42 document.documentElement.classList.add(newTheme + '-theme');
43
44 localStorage.setItem('flatmmo-theme', newTheme);
45 btn.textContent = newTheme === 'dark' ? '☀️' : '🌙';
46 });
47
48 var target = document.querySelector('.cosmos-header__wiki-buttons')
49 || document.querySelector('.cosmos-actions')
50 || document.querySelector('.wds-button-group')
51 || document.querySelector('#content');
52 if (target) {
53 if (target.id === 'content') {
54 target.insertBefore(btn, target.firstChild);
55 } else {
56 target.appendChild(btn);
57 }
58 }
59
60 })();
61
62 // --- Search bar toggle + compact header search bar ---
63 (function() {
64 var searchMode = localStorage.getItem('flatmmo-search') || 'top';
65
66 document.body.classList.remove('search-top', 'search-header');
67 document.body.classList.add('search-' + searchMode);
68
69 if (searchMode === 'header') {
70 window.scrollTo(0, 0);
71 document.addEventListener('DOMContentLoaded', function() {
72 window.scrollTo(0, 0);
73 });
74 }
75
76 var searchToggle = document.createElement('button');
77 searchToggle.className = 'search-toggle-btn';
78 searchToggle.title = 'Toggle search bar position';
79 searchToggle.textContent = searchMode === 'top' ? '🔍' : '🔎';
80
81 searchToggle.addEventListener('click', function() {
82 var isTop = document.body.classList.contains('search-top');
83 var newMode = isTop ? 'header' : 'top';
84
85 document.body.classList.remove('search-top', 'search-header');
86 document.body.classList.add('search-' + newMode);
87 document.documentElement.classList.remove('search-top', 'search-header');
88 document.documentElement.classList.add('search-' + newMode);
89
90 localStorage.setItem('flatmmo-search', newMode);
91 searchToggle.textContent = newMode === 'top' ? '🔍' : '🔎';
92 });
93
94 var searchWrap = document.createElement('div');
95 searchWrap.className = 'header-search-wrap';
96
97 var searchInput = document.createElement('input');
98 searchInput.type = 'text';
99 searchInput.className = 'header-search-input';
100 searchInput.placeholder = 'Search wiki...';
101 searchInput.setAttribute('autocomplete', 'off');
102
103 var searchBtn = document.createElement('button');
104 searchBtn.className = 'header-search-btn';
105 searchBtn.innerHTML = '🔍';
106 searchBtn.title = 'Search';
107
108 function doSearch() {
109 var q = searchInput.value.trim();
110 if (q) {
111 window.location.href = mw.util.getUrl('Special:Search') + '?search=' + encodeURIComponent(q);
112 }
113 }
114
115 searchBtn.addEventListener('click', doSearch);
116 searchInput.addEventListener('keydown', function(e) {
117 if (e.key === 'Enter') doSearch();
118 });
119
120 searchWrap.appendChild(searchInput);
121 searchWrap.appendChild(searchBtn);
122
123 var target = document.querySelector('.cosmos-header__wiki-buttons')
124 || document.querySelector('.cosmos-actions')
125 || document.querySelector('.wds-button-group')
126 || document.querySelector('#content');
127 if (target && target.id !== 'content') {
128 target.appendChild(searchToggle);
129 target.style.position = 'relative';
130 target.appendChild(searchWrap);
131
132 var bannerUser = document.querySelector('.cosmos-userButton-label')
133 || document.querySelector('#p-personal-label');
134 var userName = bannerUser ? bannerUser.textContent.trim() : '';
135 if (userName) {
136 var userLink = document.createElement('a');
137 userLink.className = 'relocated-user';
138 userLink.href = mw.util.getUrl('User:' + userName);
139 userLink.title = userName;
140
141 var userIcon = document.createElement('span');
142 userIcon.className = 'relocated-user-icon';
143 userIcon.innerHTML = '👤';
144
145 var userText = document.createElement('span');
146 userText.className = 'relocated-user-name';
147 userText.textContent = userName;
148
149 userLink.appendChild(userIcon);
150 userLink.appendChild(userText);
151 target.appendChild(userLink);
152 }
153 }
154 })();
155
156 $.getScript(mw.util.getUrl("MediaWiki:ProfileTags.js") + "?action=raw&ctype=text/javascript");
157 if (document.getElementById("interactiveMap")) {
158 console.log("map loaded")
159 $.getScript(mw.util.getUrl("MediaWiki:InteractiveMap/Objects.js") + "?action=raw&ctype=text/javascript", function() {
160 $.getScript(mw.util.getUrl("MediaWiki:InteractiveMap/NPCs.js") + "?action=raw&ctype=text/javascript", function() {
161 $.getScript(mw.util.getUrl("MediaWiki:InteractiveMap/Maps.js") + "?action=raw&ctype=text/javascript", function() {
162 $.getScript(mw.util.getUrl("MediaWiki:InteractiveMap.js") + "?action=raw&ctype=text/javascript", function() {
163 });
164 });
165 });
166 });
167 }
168
169 if (document.getElementById("wardrobe")) {
170 $.getScript(mw.util.getUrl("MediaWiki:Wardrobe.js") + "?action=raw&ctype=text/javascript");
171 console.log("wardrobe loaded")
172 }
173
174 if (document.getElementById("mapEditor")) {
175 $.getScript("https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js", function() {
176 $.getScript(mw.util.getUrl("MediaWiki:InteractiveMap/Objects.js") + "?action=raw&ctype=text/javascript", function() {
177 $.getScript(mw.util.getUrl("MediaWiki:InteractiveMap/NPCs.js") + "?action=raw&ctype=text/javascript", function() {
178 $.getScript(mw.util.getUrl("MediaWiki:InteractiveMap/Maps.js") + "?action=raw&ctype=text/javascript", function() {
179 $.getScript(mw.util.getUrl("MediaWiki:MapEditor.js") + "?action=raw&ctype=text/javascript", function() {
180 });
181 });
182 });
183 });
184 });
185 }
186 if (document.querySelector(".code")) {
187 $.getScript("../custom/highlight.min.js", ()=>{
188 document.querySelectorAll(".code").forEach(el=>hljs.highlightElement(el))
189 console.log('Code highlighted');
190 });
191 }
192
193 if (document.querySelector('[class*="Tracker"]') && !document.querySelector('[class*="page-MediaWiki"]')) {
194 $.getScript(mw.util.getUrl("MediaWiki:Trackers.js") + "?action=raw&ctype=text/javascript");
195 console.log("Tracker loaded");
196 }
197
198 if (document.getElementById("enemiesDB")) {
199 $.getScript(mw.util.getUrl("MediaWiki:Update_DB.js") + "?action=raw&ctype=text/javascript");
200 console.log("DB Updater Loaded")
201 }
202 function hitChance(accuracy, defence) {
203 accuracy = parseInt(accuracy);
204 defence = parseInt(defence);
205 let hitChance = 0;
206 if(accuracy >= defence) {
207 hitChance = 1;
208 } else {
209 hitChance = 1 / (1 + defence - accuracy)
210 }
211 return (hitChance * 100).toFixed(2);
212 }
213 if (document.querySelector('.hitChance')) {
214 document.querySelectorAll(".hitChance").forEach(el => {
215 let [acc, def] = el.innerText.split(",")
216 el.innerText = "";
217 const accSpan = document.createElement("span");
218 const defSpan = document.createElement("span");
219 const hitSpan = document.createElement("span");
220 const accInput = document.createElement("input");
221 const defInput = document.createElement("input");
222 const hitValueSpan = document.createElement("span");
223
224 accSpan.innerText = "Accuracy:";
225 defSpan.innerText = "Defence:";
226 hitSpan.innerText = "Hit Chance:";
227
228 accInput.type = "number";
229 defInput.type = "number";
230 accInput.min = 0;
231 defInput.min = 0;
232 if(acc !== "0") {
233 accInput.disabled = true;
234 }
235 if(def !== "0") {
236 defInput.disabled = true
237 }
238 def = def < 0 ? 0 : def;
239 acc = acc < 0 ? 0 : acc;
240 accInput.defaultValue = acc;
241 defInput.defaultValue = def;
242 accInput.onchange = function(){
243 hitValueSpan.innerText = hitChance(accInput.value, defInput.value) + "%";
244 }
245 defInput.onchange = function(){
246 hitValueSpan.innerText = hitChance(accInput.value, defInput.value) + "%";
247 }
248 el.append(accSpan, accInput, defSpan, defInput, hitSpan, hitValueSpan);
249 hitValueSpan.innerText = hitChance(accInput.value, defInput.value) + "%";
250 })
251 }
252
253 });
254
255 /* Page Preview Popup */
256 (function() {
257 var popup = null;
258 var hideTimer = null;
259 var showTimer = null;
260 var cache = {};
261 var currentRequest = null;
262
263 function createPopup() {
264 popup = document.createElement('div');
265 popup.className = 'flatmmo-preview';
266 document.body.appendChild(popup);
267
268 popup.addEventListener('mouseenter', function() {
269 clearTimeout(hideTimer);
270 });
271 popup.addEventListener('mouseleave', function() {
272 hideTimer = setTimeout(function() {
273 popup.style.display = 'none';
274 }, 200);
275 });
276 }
277
278 function positionPopup(e) {
279 var x = e.pageX + 15;
280 var y = e.pageY + 15;
281 var popupWidth = 340;
282 var popupHeight = 200;
283
284 if (x + popupWidth > document.documentElement.scrollLeft + window.innerWidth) {
285 x = e.pageX - popupWidth - 15;
286 }
287 if (y + popupHeight > document.documentElement.scrollTop + window.innerHeight) {
288 y = e.pageY - popupHeight - 15;
289 }
290
291 popup.style.left = x + 'px';
292 popup.style.top = y + 'px';
293 }
294
295 function fetchPreview(title, callback) {
296 if (cache[title]) {
297 callback(cache[title]);
298 return;
299 }
300
301 var url = '/api.php?action=parse&page=' + encodeURIComponent(title) + '&prop=text&format=json&redirects=1';
302
303 var xhr = new XMLHttpRequest();
304 currentRequest = xhr;
305 xhr.open('GET', url);
306 xhr.onload = function() {
307 if (xhr !== currentRequest) return;
308 try {
309 var data = JSON.parse(xhr.responseText);
310 if (data.parse && data.parse.text) {
311 var html = data.parse.text['*'];
312 var temp = document.createElement('div');
313 temp.innerHTML = html;
314
315 var img = null;
316 var infoboxImg = temp.querySelector('.flatmmo-infobox-image img, .flatmmo-infobox img');
317 if (infoboxImg) {
318 img = infoboxImg.src;
319 } else {
320 var firstImg = temp.querySelector('img');
321 if (firstImg && firstImg.width > 20) {
322 img = firstImg.src;
323 }
324 }
325
326 var text = '';
327 var paragraphs = temp.querySelectorAll('p');
328 for (var i = 0; i < paragraphs.length; i++) {
329 var t = paragraphs[i].textContent.trim();
330 if (t.length > 10) {
331 text = t;
332 break;
333 }
334 }
335
336 if (text.length > 250) {
337 text = text.substring(0, 247) + '...';
338 }
339
340 var result = { image: img, text: text, title: title };
341 cache[title] = result;
342 callback(result);
343 }
344 } catch(e) {
345 console.log('Preview fetch error:', e);
346 }
347 };
348 xhr.onerror = function() {
349 console.log('Preview request failed for:', title);
350 };
351 xhr.send();
352 }
353
354 function showPreview(link, e) {
355 if (!popup) createPopup();
356
357 var href = link.getAttribute('href');
358 if (!href) return;
359
360 var match = href.match(/\/index\.php\/(.+)/);
361 if (!match) return;
362
363 var title = decodeURIComponent(match[1]).replace(/_/g, ' ');
364
365 if (title.match(/^Special:|^Talk:|^User:|^Category:|^File:|^Template:|^MediaWiki:/i)) return;
366 if (href.indexOf('action=edit') !== -1) return;
367 if (link.classList.contains('new')) return;
368
369 positionPopup(e);
370 popup.innerHTML = '<div class="flatmmo-preview-title">' + title + '</div><div class="flatmmo-preview-loading">Loading...</div>';
371 popup.style.display = 'block';
372
373 fetchPreview(title, function(data) {
374 var html = '<div class="flatmmo-preview-title">' + data.title + '</div>';
375 if (data.image) {
376 html += '<div class="flatmmo-preview-image"><img src="' + data.image + '"></div>';
377 }
378 if (data.text) {
379 html += '<div class="flatmmo-preview-text">' + data.text + '</div>';
380 }
381 if (!data.image && !data.text) {
382 html += '<div class="flatmmo-preview-text" style="color:#999;">No preview available.</div>';
383 }
384 popup.innerHTML = html;
385 });
386 }
387
388 document.addEventListener('DOMContentLoaded', function() {
389 var content = document.getElementById('mw-content-text') || document.getElementById('bodyContent') || document.body;
390
391 // Remove all default browser tooltips from content links
392 content.querySelectorAll('a[title]').forEach(function(a) { a.removeAttribute('title'); });
393
394 content.addEventListener('mouseover', function(e) {
395 var link = e.target.closest('a');
396 if (!link) return;
397 if (link.closest('.flatmmo-preview')) return;
398
399 clearTimeout(hideTimer);
400 clearTimeout(showTimer);
401
402 if (link.getAttribute('title')) {
403 link.removeAttribute('title');
404 }
405
406 showTimer = setTimeout(function() {
407 showPreview(link, e);
408 }, 300);
409 });
410
411 content.addEventListener('mouseout', function(e) {
412 var link = e.target.closest('a');
413 if (!link) return;
414
415 clearTimeout(showTimer);
416
417 hideTimer = setTimeout(function() {
418 if (popup) popup.style.display = 'none';
419 }, 200);
420 });
421 });
422 })();
