Anonymous
×
Create a new article
Write your page title here:
We currently have 922 articles on WIKI - Flat MMO. Type your article name above or click on one of the titles below and start writing!



WIKI - Flat MMO
922Articles

MediaWiki:Common.js: Difference between revisions

Coolrock (talk | contribs)
No edit summary
Coolrock (talk | contribs)
No edit summary
Line 265: Line 265:


});
});
/* Page Preview Popup */
(function() {
    var popup = null;
    var hideTimer = null;
    var showTimer = null;
    var cache = {};
    var currentRequest = null;
    function createPopup() {
        popup = document.createElement('div');
        popup.className = 'flatmmo-preview';
        document.body.appendChild(popup);
        popup.addEventListener('mouseenter', function() {
            clearTimeout(hideTimer);
        });
        popup.addEventListener('mouseleave', function() {
            hideTimer = setTimeout(function() {
                popup.style.display = 'none';
            }, 200);
        });
    }
    function positionPopup(e) {
        var x = e.pageX + 15;
        var y = e.pageY + 15;
        var popupWidth = 340;
        var popupHeight = 200;
        if (x + popupWidth > document.documentElement.scrollLeft + window.innerWidth) {
            x = e.pageX - popupWidth - 15;
        }
        if (y + popupHeight > document.documentElement.scrollTop + window.innerHeight) {
            y = e.pageY - popupHeight - 15;
        }
        popup.style.left = x + 'px';
        popup.style.top = y + 'px';
    }
    function fetchPreview(title, callback) {
        if (cache[title]) {
            callback(cache[title]);
            return;
        }
        var api = '/index.php?action=api&format=json';
        // Use parse API to get rendered content
        var url = '/api.php?action=parse&page=' + encodeURIComponent(title) + '&prop=text&format=json&redirects=1';
        var xhr = new XMLHttpRequest();
        currentRequest = xhr;
        xhr.open('GET', url);
        xhr.onload = function() {
            if (xhr !== currentRequest) return;
            try {
                var data = JSON.parse(xhr.responseText);
                if (data.parse && data.parse.text) {
                    var html = data.parse.text['*'];
                    var temp = document.createElement('div');
                    temp.innerHTML = html;
                    // Get first image
                    var img = null;
                    var infoboxImg = temp.querySelector('.flatmmo-infobox-image img, .flatmmo-infobox img');
                    if (infoboxImg) {
                        img = infoboxImg.src;
                    } else {
                        var firstImg = temp.querySelector('img');
                        if (firstImg && firstImg.width > 20) {
                            img = firstImg.src;
                        }
                    }
                    // Get first paragraph text
                    var text = '';
                    var paragraphs = temp.querySelectorAll('p');
                    for (var i = 0; i < paragraphs.length; i++) {
                        var t = paragraphs[i].textContent.trim();
                        if (t.length > 10) {
                            text = t;
                            break;
                        }
                    }
                    // Truncate if too long
                    if (text.length > 250) {
                        text = text.substring(0, 247) + '...';
                    }
                    var result = { image: img, text: text, title: title };
                    cache[title] = result;
                    callback(result);
                }
            } catch(e) {}
        };
        xhr.send();
    }
    function showPreview(link, e) {
        if (!popup) createPopup();
        var href = link.getAttribute('href');
        if (!href) return;
        // Only handle internal wiki links
        var match = href.match(/\/index\.php\/(.+)/);
        if (!match) return;
        var title = decodeURIComponent(match[1]).replace(/_/g, ' ');
        // Skip special pages, edit links, red links
        if (title.match(/^Special:|^Talk:|^User:|^Category:|^File:|^Template:|^MediaWiki:/i)) return;
        if (href.indexOf('action=edit') !== -1) return;
        if (link.classList.contains('new')) return;
        positionPopup(e);
        popup.innerHTML = '<div class="flatmmo-preview-title">' + title + '</div><div class="flatmmo-preview-loading">Loading...</div>';
        popup.style.display = 'block';
        fetchPreview(title, function(data) {
            var html = '<div class="flatmmo-preview-title">' + data.title + '</div>';
            if (data.image) {
                html += '<div class="flatmmo-preview-image"><img src="' + data.image + '"></div>';
            }
            if (data.text) {
                html += '<div class="flatmmo-preview-text">' + data.text + '</div>';
            }
            if (!data.image && !data.text) {
                html += '<div class="flatmmo-preview-text" style="color:#999;">No preview available.</div>';
            }
            popup.innerHTML = html;
        });
    }
    // Attach to content area links
    document.addEventListener('DOMContentLoaded', function() {
        var content = document.getElementById('mw-content-text') || document.getElementById('bodyContent') || document.body;
        content.addEventListener('mouseover', function(e) {
            var link = e.target.closest('a');
            if (!link) return;
            if (link.closest('.flatmmo-preview')) return;
            clearTimeout(hideTimer);
            clearTimeout(showTimer);
            showTimer = setTimeout(function() {
                showPreview(link, e);
            }, 300);
        });
        content.addEventListener('mouseout', function(e) {
            var link = e.target.closest('a');
            if (!link) return;
            clearTimeout(showTimer);
            hideTimer = setTimeout(function() {
                if (popup) popup.style.display = 'none';
            }, 200);
        });
    });
})();

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