MediaWiki:Common.js
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.
// load various utilities from the commons wiki, including l10nFactory and isEditorActive
mw.loader.getScript( 'https://commons.wiki.gg/MediaWiki:Common-base.js?action=raw\u0026ctype=text/javascript' ).then(function(){
////////////////////////////////////////////////////////////////////////////////
/* Now we can use l10nFactory and isEditorActive /
/* Example for l10nFactory:
var l10n = l10nFactory(mw.config.get('wgUserLanguage'), {
l10n_key {
'en': 'en_text',
'de': 'de_text',
'zh': 'zh_text',
},
l10n_key2 {
'en': 'en_text2',
'zh': 'zh_text2',
}
});
var text = l10n('l10n_key');
*/
////////////////////////////////////////////////////////////////////////////////
/*end of .then() callback*/ });
mw.loader.load("https://commons.wiki.gg/wiki/MediaWiki:DiscordIntegrator.js?action=raw\u0026ctype=text/javascript");
$(document).ready(function() {
// Menu toggle
$('<div class="menu-toggle"/>').insertAfter($('#p-logo')).on("click", function(event){
event.stopPropagation();
$(this).toggleClass('expanded');
});
// Function to update time for a specific element
function updateTime(timeUTC, elementId) {
// Step 1: Parse the fixed UTC time
var utcHour = parseInt(timeUTC.split(':')[0]);
var utcMinute = parseInt(timeUTC.split(':')[1]);
// Step 2: Get the user's timezone and offset
var userTimezone = new Date().toLocaleTimeString('en', { timeZoneName: 'short' }).split(' ')[2];
// Replace "GMT" with "UTC"
if (userTimezone.includes('GMT')) {
userTimezone = userTimezone.replace('GMT', 'UTC');
}
if (elementId === 'time-1') {
userTimezone = userTimezone.replace('UTC', 'DST: UTC');
}
if (elementId === 'time-2') {
userTimezone = userTimezone.replace('UTC', 'ST: UTC');
}
var now = new Date();
var userOffset = -1 * now.getTimezoneOffset(); // in minutes
// Step 3: Calculate the user's local time
var localHour = utcHour + Math.floor(userOffset / 60); // Add hours
var localMinute = utcMinute + userOffset % 60; // Add minutes
// Adjust for overflow and underflow minutes
if (localMinute < 0) {
localHour -= 1;
localMinute += 60;
}
if (localMinute >= 60) {
localHour += 1;
localMinute -= 60;
}
// Adjust for overflow and underflow hours
if (localHour < 0) {
localHour += 24;
}
if (localHour >= 24) {
localHour -= 24;
}
// Step 4: Format the time in HH:MM format
var formattedTime = (localHour < 10 ? '0' : '') + localHour + ':' + (localMinute < 10 ? '0' : '') + localMinute;
// Step 5: Update the HTML content
var rewardElement = document.getElementById(elementId);
if (rewardElement) {
rewardElement.textContent = formattedTime + ' (' + userTimezone + ')';
}
}
// Call updateTime function for each time
updateTime('22:00', 'time-1');
updateTime('23:00', 'time-2');
updateTime('00:00', 'time-3');
updateTime('07:00', 'time-4');
updateTime('12:00', 'time-5');
});
////////////////////////////////////////////////////////////////////////////////
// modified version of https://dev.fandom.com/wiki/MediaWiki:TZclock.js
/**
* Implement a timezone-adjusted clock
* . Looks for elements with class "js-tzclock"
* . Supports any timezone, not just the user's or UTC
* . Supports multiple clocks per page
* . Supports optional daylight saving time
*
* Configuration is adapted from tzdata format
* . Optional comments begin with # (pound/octothorpe)
* . Spaces in strings must use _ (underscore)
* . Underscore is replaced with a space when running
* . + (plus) is optional for positive time offsets
* . Basic zone definition must come before any rules
* . Rules, if there are any, must be in chronological order
* . NAME is location name displayed in clock (any string)
* . UTCOFF is offset from UTC ([+|-]hh[:mm])
* . ZONE is the timezone name (any string)
* . IN is the month name for a rule (3-letter in English)
* . ON is the date (numerical date, lastDay, or Day>=date)
* . If used, Day is 3-letter in English
* . AT is the standard time at which the rule takes effect (24-hour)
* . SAVE is the amount of time added to standard time (hh[:mm])
* . LETTERS is the zone name when the rule is in effect (any string)
*
* Example clock configurations:
*
* <div class="js-tzclock"><nowiki>
* # NAME UTCOFF ZONE
* New_York -5:00 EST
* # IN ON AT SAVE LETTERS
* Mar Sun>=8 2:00 1 EDT # 2nd Sunday in March
* Nov Sun>=1 2:00 0 EST # 1st Sunday in November
* </nowiki></div>
*
* <div class="js-tzclock"><nowiki>
* # NAME UTCOFF ZONE
* London 0:00 GMT
* # IN ON AT SAVE LETTERS
* Mar lastSun 1:00 1 BST # last Sunday in March
* Oct lastSun 1:00 0 GMT # last Sunday in October
* </nowiki></div>
*
* <div class="js-tzclock"><nowiki>
* # NAME UTCOFF ZONE
* Tokyo 9:00 JST # no daylight time in Japan
* </nowiki></div>
*
* <div class="js-tzclock"><nowiki>
* # NAME UTCOFF ZONE
* Adelaide +9:30 CST
* # IN ON AT SAVE LETTERS
* Apr Sun>=1 2:00 0 CST # 1st Sunday in April
* Oct Sun>=1 2:00 1 CDT # 1st Sunday in October
* </nowiki></div>
*
* <nowiki> ... </nowiki> may not be essential
* for all clock configurations, but it is recommended
* to stop MediaWiki from interfering with them
*/
;(function ($) {
'use strict';
var msg;
var
clock = []; // all clock data
// calculate day of week using Zeller's algorithm
// 0 = Saturday, ..., 6 = Friday
function zeller(d, m, y) {
var
Y = y - (m < 3 ? 1 : 0),
c = Math.floor(Y / 100),
w;
m += (m < 3) ? 12 : 0;
y = Y % 100;
w = (d + Math.floor(13 * (m + 1) / 5) + y +
Math.floor(y / 4) + Math.floor(c / 4) - 2 * c) % 7;
return (w < 0) ? w + 7 : w;
}
// convert [+|-]h[:m] to seconds
function parseHM(s) {
var
sign = s.charAt(0) === '-' ? -1 : 1;
s = (s.replace(/[+\-]/, '') + ':0').split(':');
return sign * (parseInt(s[0], 10) * 60 + parseInt(s[1], 10)) * 60;
}
// parse the daylight saving rule for the given year
// return epoch seconds (local time)
function parseRule(year, rule) {
var
inMonth = rule[0],
onDay = rule[1],
atHour = rule[2],
week = ['Sat', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
m = $.inArray(inMonth, [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
]) + 1,
last = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m - 1],
d;
if ((m === 2) &&
(((year % 100 !== 0) && (year % 4 === 0)) || (year % 400 === 0))) {
// leap year, in the unlikely event daylight saving switches in Feb
last = 29;
}
if (/^\d+$/.test(onDay)) {
// pure number
d = parseInt(onDay, 10);
} else if (onDay.substr(0, 4) === 'last') {
// last day of week of month
d = last;
d -= (zeller(d, m, year) + 7 - $.inArray(onDay.substr(4), week)) % 7;
} else if (onDay.substr(3, 2) === '>=') {
// day of week at/after date
d = parseInt(onDay.substr(5), 10);
d += ($.inArray(onDay.substr(0, 3), week) + 7 - zeller(d, m, year)) % 7;
} else {
// error
return;
}
// ISO format the date and return epoch seconds
// atHour is local time, so the return is local time, despite the Z
return Date.parse(
year.toString() + '-' + ('0' + m.toString()).substr(-2) +
'-' + ('0' + d.toString()).substr(-2) + 'T00:00:00Z'
) / 1000 + atHour;
}
// read tz configs from clock elements
// populate the clock global object
// data = jQuery collection of clock elements
// NB: strings inserted into the DOM with $().text()
// CANNOT be escaped per OWASP XSS recommendations,
// because $().text() uses document.createTextNode,
// which does not unescape the entities
// NB: text nodes are unparsed by the DOM engine
// hence there is no XSS or injection risk
// NB: literal strings that use $().text are
// name (0), zone (2), and letters (7 & 12)
function getConfig(data) {
var
i;
data.each(function (_, e) {
var
text = $(e).text()
.replace(/#.*?(\n|$)/g, '$1') // remove all comments
.replace(/\s+/g, ' ') // compress whitespace
.replace(/^\s|\s$/g, '') // trim
.split(' '), // tokenize
c;
// process tokens, sanitizing them along the way
if ((text.length === 3) || (text.length === 13)) {
// basic zone definition
clock.push({
e: $(e),
name: text[0] // location description
.replace(/_/g, ' '), // translate spaces
utcoff: parseHM(text[1] // [+|-]hh:mm UTC offset
.replace(/[^+\-\d:]/g, '')
),
zone: text[2] // zone designator
.replace(/_/g, ' '), // translate spaces
});
c = clock[clock.length - 1];
if (text.length === 13) {
// daylight time rules
c.year = 1; // truthy, but purposefully wrong
c.rule1 = [
text[3] // in month (Jan - Dec)
.replace(/[^a-zA-Z]/g, ''),
text[4] // on day (number, last, >=)
.replace(/[^a-zA-Z>=\d]/g, ''),
parseHM(text[5] // at time hh:mm
.replace(/[^\d:]/g, '')
)
];
c.rule2 = [
text[8] // in month (Jan - Dec)
.replace(/[^a-zA-Z]/g, ''),
text[9] // on day (number, last, >=)
.replace(/[^a-zA-Z>=\d]/g, ''),
parseHM(text[10] // at time hh:mm
.replace(/[^\d:]/g, '')
)
];
c.save1 = parseHM(text[6] // daylight adjust hh:mm
.replace(/[^\d:]/g, '')
);
c.save2 = parseHM(text[11] // daylight adjust hh:mm
.replace(/[^\d:]/g, '')
);
c.letters1 = text[7] // zone designator
.replace(/_/g, ' '); // translate spaces
c.letters2 = text[12] // zone designator
.replace(/_/g, ' '); // translate spaces
}
} else {
// error
$(e).empty().text(msg('error').plain());
}
});
}
// handle timer event
function onTick() {
var
now = Math.floor(Date.now() / 1000), // epoch in seconds
time, year, i, c;
for ( i = 0; i < clock.length; ++i ) {
c = clock[i];
time = now + c.utcoff; // local epoch
year = (new Date(time * 1000)).getUTCFullYear(); // Date() takes msec
if (c.year) {
if (year !== c.year) {
// Happy New Year (maybe)
// (re)parse the rules for the calendar year
c.year = year;
c.switch1 = parseRule(year, c.rule1);
c.switch2 = parseRule(year, c.rule2);
}
// apply the rules
if ((time >= c.switch1) && (time < c.switch2)) {
time += c.save1;
c.zone = c.letters1;
} else {
time += c.save2;
c.zone = c.letters2;
}
}
// mostly RFC-822/RFC-1123 time string
// See comment about $().text() at getConfig()
var thetime;
if (window.TZclockSimpleFormat) {
thetime = (new Date(time * 1000)).toUTCString()
.replace(/Sun, |Mon, |Tue, |Wed, |Thu, |Fri, |Sat, /, '') // remove day name
.replace(/\s\d\d\d\d/, ',') // remove year
.replace(/:\d\d\sGMT/, ''); // remove seconds and GMT
} else {
thetime = (new Date(time * 1000)).toUTCString()
.replace(/\d{4}/, '$&,') // add comma after year
.replace(/ 0/g, ' ') // no leading zero on date/hour
.replace(/UT|GMT/, '(' + c.zone + ')'); // "local" zone designation
}
$('.js-tzclock-time', c.e).text(thetime);
}
// set timeout for next tick
setTimeout(onTick, 1100 - Date.now() % 1000);
}
// main routine
// look for signature classes, init, and run
function init($content) {
var
data = $content.find('.js-tzclock:not(.loaded)'),
dom = String.prototype.concat(
'<div class="js-tzclock-wrap">',
'<div class="js-tzclock-lctn"></div>',
'<div class="js-tzclock-time"></div>',
'</div>'
),
// Avoid nesting <div> in <span> - for valid HTML but also
// to allow embedding the clock inline
spanDom = String.prototype.concat(
'<span class="js-tzclock-wrap">',
'<span class="js-tzclock-lctn"></span>',
'<span class="js-tzclock-time"></span>',
'</span>'
),
e, i;
if (data.length) {
data.addClass('loaded');
getConfig(data);
if (clock.length) {
// init formats with names
for ( i = 0; i < clock.length; ++i ) {
e = clock[i].e.empty().append(
clock[i].e.prop('tagName') === 'SPAN' ? spanDom : dom);
// See comment about $().text() at getConfig()
$('.js-tzclock-lctn', e).text(clock[i].name);
}
// fake the first tick
setTimeout(onTick);
}
}
}
$(function(){init($('#content'));});
})(jQuery);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
(function(mw, $) {
/**
* Countdown
*
* @version 2.1
*
* @author Pecoes <https://c.wikia.com/wiki/User:Pecoes>
* @author Asaba <https://dev.wikia.com/wiki/User:Asaba>
*
* Version 1 authors:
* - Splarka <https://c.wikia.com/wiki/User:Splarka>
* - Eladkse <https://c.wikia.com/wiki/User:Eladkse>
*
* documentation and examples at:
* <https://dev.wikia.com/wiki/Countdown>
*/
/*jshint jquery:true, browser:true, devel:true, camelcase:true, curly:false, undef:true, bitwise:true, eqeqeq:true, forin:true, immed:true, latedef:true, newcap:true, noarg:true, unused:true, regexp:true, strict:true, trailing:false */
/*global mediaWiki:true*/
(function (module, mw, $, undefined) {
'use strict';
var translations = $.extend(true, {
// English (English)
en: {
and: 'and',
second: 'second',
seconds: 'seconds',
minute: 'minute',
minutes: 'minutes',
hour: 'hour',
hours: 'hours',
day: 'day',
days: 'days'
}
}, module.translations || {}),
i18n = translations[
mw.config.get('wgContentLanguage')
] || translations.en;
var countdowns = [];
var NO_LEADING_ZEROS = 1,
SHORT_FORMAT = 2,
NO_ZEROS = 4;
function output (i, diff) {
/*jshint bitwise:false*/
var delta, result, parts = [];
delta = diff % 60;
result = ' ' + i18n[delta === 1 ? 'second' : 'seconds'];
if (countdowns[i].opts & SHORT_FORMAT) result = result.charAt(1);
parts.unshift(delta + result);
diff = Math.floor(diff / 60);
delta = diff % 60;
result = ' ' + i18n[delta === 1 ? 'minute' : 'minutes'];
if (countdowns[i].opts & SHORT_FORMAT) result = result.charAt(1);
parts.unshift(delta + result);
diff = Math.floor(diff / 60);
delta = diff % 24;
result = ' ' + i18n[delta === 1 ? 'hour' : 'hours' ];
if (countdowns[i].opts & SHORT_FORMAT) result = result.charAt(1);
parts.unshift(delta + result);
diff = Math.floor(diff / 24);
result = ' ' + i18n[diff === 1 ? 'day' : 'days' ];
if (countdowns[i].opts & SHORT_FORMAT) result = result.charAt(1);
parts.unshift(diff + result);
result = parts.pop();
if (countdowns[i].opts & NO_LEADING_ZEROS) {
while (parts.length && parts[0][0] === '0') {
parts.shift();
}
}
if (countdowns[i].opts & NO_ZEROS) {
parts = parts.filter(function(part) {
return part[0] !== '0';
});
}
if (parts.length) {
if (countdowns[i].opts & SHORT_FORMAT) {
result = parts.join(' ') + ' ' + result;
} else {
result = parts.join(', ') + ' ' + i18n.and + ' ' + result;
}
}
countdowns[i].node.text(result);
}
function end(i) {
var c = countdowns[i].node.parent();
switch (c.attr('data-end')) {
case 'remove':
c.remove();
return true;
case 'stop':
output(i, 0);
return true;
case 'toggle':
var toggle = c.attr('data-toggle');
if (toggle && toggle == 'next') {
c.next().css('display', 'inline');
c.css('display', 'none');
return true;
}
if (toggle && $(toggle).length) {
$(toggle).css('display', 'inline');
c.css('display', 'none');
return true;
}
break;
case 'callback':
var callback = c.attr('data-callback');
if (callback && $.isFunction(module[callback])) {
output(i, 0);
module[callback].call(c);
return true;
}
break;
}
countdowns[i].countup = true;
output(i, 0);
return false;
}
function update () {
var now = Date.now();
var countdownsToRemove = [];
$.each(countdowns.slice(0), function (i, countdown) {
var diff = Math.floor((countdown.date - now) / 1000);
if (diff <= 0 && !countdown.countup) {
if (end(i)) countdownsToRemove.push(i);
} else {
output(i, Math.abs(diff));
}
});
var x;
while((x = countdownsToRemove.pop()) !== undefined) {
countdowns.splice(x, 1);
}
if (countdowns.length) {
window.setTimeout(function () {
update();
}, 1000);
}
}
function getOptions (node) {
/*jshint bitwise:false*/
var text = node.parent().attr('data-options'),
opts = 0;
if (text) {
if (/no-leading-zeros/.test(text)) {
opts |= NO_LEADING_ZEROS;
}
if (/short-format/.test(text)) {
opts |= SHORT_FORMAT;
}
if (/no-zeros/.test(text)) {
opts |= NO_ZEROS;
}
}
return opts;
}
function init() {
var countdown = $('.countdown:not(.handled)');
if (!countdown.length) return;
$('.nocountdown').css('display', 'none');
countdown
.css('display', 'inline')
.find('.countdowndate')
.each(function () {
var $this = $(this),
date = (new Date($this.text())).valueOf();
if (isNaN(date)) {
$this.text('BAD DATE');
return;
}
countdowns.push({
node: $this,
opts: getOptions($this),
date: date,
});
});
countdown.addClass('handled');
if (countdowns.length) {
update();
}
}
mw.hook('wikipage.content').add(init);
}(window.countdownTimer = window.countdownTimer || {}, mediaWiki, jQuery));
// End Countdown
})(mediaWiki, jQuery);