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 251: Line 251:
}
}


});
/* Page Preview Popup - inside $(document).ready */
 
/* Page Preview Popup */
(function() {
(function() {
     var popup = null;
     var popup = null;
     var hideTimer = null;
     var hideTimer = null;
     var showTimer = null;
     var showTimer = null;
     var cache = {};
     var previewCache = {};
    var currentRequest = null;


     function createPopup() {
     function createPopup() {
Line 294: Line 291:


     function fetchPreview(title, callback) {
     function fetchPreview(title, callback) {
         if (cache[title]) {
         if (previewCache[title]) {
             callback(cache[title]);
             callback(previewCache[title]);
             return;
             return;
         }
         }


         var url = '/api.php?action=parse&page=' + encodeURIComponent(title) + '&prop=text&format=json&redirects=1';
         var apiUrl = mw.util.wikiScript('api') + '?action=parse&page=' + encodeURIComponent(title) + '&prop=text&format=json&redirects=1';


         var xhr = new XMLHttpRequest();
         $.ajax({
        currentRequest = xhr;
            url: apiUrl,
        xhr.open('GET', url);
            dataType: 'json',
        xhr.onload = function() {
            success: function(data) {
            if (xhr !== currentRequest) return;
            try {
                var data = JSON.parse(xhr.responseText);
                 if (data.parse && data.parse.text) {
                 if (data.parse && data.parse.text) {
                     var html = data.parse.text['*'];
                     var html = data.parse.text['*'];
Line 339: Line 333:


                     var result = { image: img, text: text, title: title };
                     var result = { image: img, text: text, title: title };
                     cache[title] = result;
                     previewCache[title] = result;
                     callback(result);
                     callback(result);
                 }
                 }
             } catch(e) {
             },
                 console.log('Preview fetch error:', e);
            error: function() {
                 console.log('Preview request failed for:', title);
             }
             }
         };
         });
        xhr.onerror = function() {
            console.log('Preview request failed for:', title);
        };
        xhr.send();
     }
     }


Line 386: Line 377:
     }
     }


     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
    // Strip all native tooltips from content links
        content.querySelectorAll('a[title]').forEach(function(a) { a.removeAttribute('title'); });
    $(content).find('a[title]').removeAttr('title');


        content.addEventListener('mouseover', function(e) {
    $(content).on('mouseover', 'a', function(e) {
            var link = e.target.closest('a');
        var link = this;
            if (!link) return;
        if ($(link).closest('.flatmmo-preview').length) return;
            if (link.closest('.flatmmo-preview')) return;


            clearTimeout(hideTimer);
        clearTimeout(hideTimer);
            clearTimeout(showTimer);
        clearTimeout(showTimer);


            if (link.getAttribute('title')) {
        // Catch any title that got added dynamically
                link.removeAttribute('title');
        if (link.getAttribute('title')) {
            }
            link.removeAttribute('title');
        }


            showTimer = setTimeout(function() {
        showTimer = setTimeout(function() {
                showPreview(link, e);
            showPreview(link, e);
            }, 300);
        }, 300);
        });
    });


        content.addEventListener('mouseout', function(e) {
    $(content).on('mouseout', 'a', function() {
             var link = e.target.closest('a');
        clearTimeout(showTimer);
            if (!link) return;
        hideTimer = setTimeout(function() {
             if (popup) popup.style.display = 'none';
        }, 200);
    });


            clearTimeout(showTimer);
    console.log('Page preview popup initialized');
})();


            hideTimer = setTimeout(function() {
});
                if (popup) popup.style.display = 'none';
            }, 200);
        });
    });
})();

Revision as of 05:04, 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 /* Page Preview Popup - inside $(document).ready */
254 (function() {
255     var popup = null;
256     var hideTimer = null;
257     var showTimer = null;
258     var previewCache = {};
259 
260     function createPopup() {
261         popup = document.createElement('div');
262         popup.className = 'flatmmo-preview';
263         document.body.appendChild(popup);
264 
265         popup.addEventListener('mouseenter', function() {
266             clearTimeout(hideTimer);
267         });
268         popup.addEventListener('mouseleave', function() {
269             hideTimer = setTimeout(function() {
270                 popup.style.display = 'none';
271             }, 200);
272         });
273     }
274 
275     function positionPopup(e) {
276         var x = e.pageX + 15;
277         var y = e.pageY + 15;
278         var popupWidth = 340;
279         var popupHeight = 200;
280 
281         if (x + popupWidth > document.documentElement.scrollLeft + window.innerWidth) {
282             x = e.pageX - popupWidth - 15;
283         }
284         if (y + popupHeight > document.documentElement.scrollTop + window.innerHeight) {
285             y = e.pageY - popupHeight - 15;
286         }
287 
288         popup.style.left = x + 'px';
289         popup.style.top = y + 'px';
290     }
291 
292     function fetchPreview(title, callback) {
293         if (previewCache[title]) {
294             callback(previewCache[title]);
295             return;
296         }
297 
298         var apiUrl = mw.util.wikiScript('api') + '?action=parse&page=' + encodeURIComponent(title) + '&prop=text&format=json&redirects=1';
299 
300         $.ajax({
301             url: apiUrl,
302             dataType: 'json',
303             success: function(data) {
304                 if (data.parse && data.parse.text) {
305                     var html = data.parse.text['*'];
306                     var temp = document.createElement('div');
307                     temp.innerHTML = html;
308 
309                     var img = null;
310                     var infoboxImg = temp.querySelector('.flatmmo-infobox-image img, .flatmmo-infobox img');
311                     if (infoboxImg) {
312                         img = infoboxImg.src;
313                     } else {
314                         var firstImg = temp.querySelector('img');
315                         if (firstImg && firstImg.width > 20) {
316                             img = firstImg.src;
317                         }
318                     }
319 
320                     var text = '';
321                     var paragraphs = temp.querySelectorAll('p');
322                     for (var i = 0; i < paragraphs.length; i++) {
323                         var t = paragraphs[i].textContent.trim();
324                         if (t.length > 10) {
325                             text = t;
326                             break;
327                         }
328                     }
329 
330                     if (text.length > 250) {
331                         text = text.substring(0, 247) + '...';
332                     }
333 
334                     var result = { image: img, text: text, title: title };
335                     previewCache[title] = result;
336                     callback(result);
337                 }
338             },
339             error: function() {
340                 console.log('Preview request failed for:', title);
341             }
342         });
343     }
344 
345     function showPreview(link, e) {
346         if (!popup) createPopup();
347 
348         var href = link.getAttribute('href');
349         if (!href) return;
350 
351         var match = href.match(/\/index\.php\/(.+)/);
352         if (!match) return;
353 
354         var title = decodeURIComponent(match[1]).replace(/_/g, ' ');
355 
356         if (title.match(/^Special:|^Talk:|^User:|^Category:|^File:|^Template:|^MediaWiki:/i)) return;
357         if (href.indexOf('action=edit') !== -1) return;
358         if (link.classList.contains('new')) return;
359 
360         positionPopup(e);
361         popup.innerHTML = '<div class="flatmmo-preview-title">' + title + '</div><div class="flatmmo-preview-loading">Loading...</div>';
362         popup.style.display = 'block';
363 
364         fetchPreview(title, function(data) {
365             var html = '<div class="flatmmo-preview-title">' + data.title + '</div>';
366             if (data.image) {
367                 html += '<div class="flatmmo-preview-image"><img src="' + data.image + '"></div>';
368             }
369             if (data.text) {
370                 html += '<div class="flatmmo-preview-text">' + data.text + '</div>';
371             }
372             if (!data.image && !data.text) {
373                 html += '<div class="flatmmo-preview-text" style="color:#999;">No preview available.</div>';
374             }
375             popup.innerHTML = html;
376         });
377     }
378 
379     var content = document.getElementById('mw-content-text') || document.getElementById('bodyContent') || document.body;
380 
381     // Strip all native tooltips from content links
382     $(content).find('a[title]').removeAttr('title');
383 
384     $(content).on('mouseover', 'a', function(e) {
385         var link = this;
386         if ($(link).closest('.flatmmo-preview').length) return;
387 
388         clearTimeout(hideTimer);
389         clearTimeout(showTimer);
390 
391         // Catch any title that got added dynamically
392         if (link.getAttribute('title')) {
393             link.removeAttribute('title');
394         }
395 
396         showTimer = setTimeout(function() {
397             showPreview(link, e);
398         }, 300);
399     });
400 
401     $(content).on('mouseout', 'a', function() {
402         clearTimeout(showTimer);
403         hideTimer = setTimeout(function() {
404             if (popup) popup.style.display = 'none';
405         }, 200);
406     });
407 
408     console.log('Page preview popup initialized');
409 })();
410 
411 });