User:Unready/ui.clock.js

/** * Implement a UTC clock and calendar * Attach it to the portlet bar * * Version 1.0: 18 Jul 2014 *  Original version for Wikia *  Purge on click *  Use the interval idea from *    mw:MediaWiki:Gadget-UTCLiveClock.js * Version 2.0: 8 Oct 2016 *  Rewrite and refactor *  Remove purge & add calendar *  Support generic MediaWiki skins only */ ((window.user = window.user || {}).ui = user.ui || {}).clock = user.ui.clock || (function (mw, $) {	'use strict';

var self = { run : run, stop : stop, message: new Date.toISOString + ' Initializing', version : 'Version 2.0: 8 Oct 2016' },		gCancel = false, gID = -1,  // cannot run = -1; okay to run = 0; already running > 0 gLast = -1, // current month on the last tick gTime = document.createTextNode('');

// 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;	}

// generate an array of weeks for a month table // m = month, 0 = January // y = 4-digit year function month(m, y) { var month = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],			last = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], cal = [ ' ' +					month[m] + ' ' + y + ' ',				' ' +					' Su  Mo  Tu  We ' + ' Th Fr  Sa ' + ' '			],			i, offset, tr;

// leap year if (((y % 100 !== 0) && (y % 4 === 0)) || (y % 400 === 0)) { last[1] = 29; }		offset = (zeller(1, m + 1, y) + 6) % 7; // 0 = Sunday if (offset) { tr = '  '; }		for ( i = 1; i <= last[m]; ++i ) { if (offset === 0) { tr = ' '; }			tr += ' ' + i + ' '; if (++offset === 7) { tr += ' '; cal.push(tr); offset = 0; }		}		if (offset) { tr += ' '; cal.push(tr); }		return cal; }

// generate 3 months of calendars // m = current month, 0 = January // y = 4-digit year function updateCal(m, y) { var tbody = $('tbody', '#js-clock-cal').empty;

if (--m < 0) { m = 11; --y; }		tbody.append(month(m, y)); if (++m > 11) { m = 0; ++y; }		tbody.append(month(m, y)); if (++m > 11) { m = 0; ++y; }		tbody.append(month(m, y)); }

// update the displayed time function onTick { var n = Date.now, d = new Date(n), m = d.getUTCMonth, y = d.getUTCFullYear, s = d.toUTCString // mostly RFC-822/RFC-1123 time string .replace(/\d{4}/, '$&,') .replace('GMT', '(UTC)') .replace(/ 0/g, ' ') .substr(5);

if (!gCancel) { gID = setTimeout(onTick, 1100 - n % 1000); gTime.data = s;			if (m !== gLast) { gLast = m;				updateCal(m, y); }		}	}

// start the clock, if it's stopped function run { if (gID === 0) { gCancel = false; self.message += '\n' + new Date.toISOString + ' Restarted'; onTick; }	}

// stop the clock, if it's running function stop { if (gID > 0) { clearTimeout(gID); gID = 0; gCancel = true; self.message += '\n' + new Date.toISOString + ' Stopped'; }	}

// insert nodes into the DOM & run $(function {		var			wgSkin = mw.config.get('skin'),			a = [				$('').append(gTime),				' '			];

// insert the clock into the DOM // support generic MediaWiki skins only switch (wgSkin) { case 'cologneblue': $('#syslinks') .prepend(document.createTextNode(' | ')) .prepend(					$(' ')						.append(a)				); break; case 'modern': $('#p-personal > .pBody > ul') .append(					$('')						.append(a)				); break; case 'monobook': $('#p-personal > .pBody > ul') .prepend(					$('')						.append(a)				); break; case 'vector': $('#p-personal > ul') .prepend(					$('')						.append(a)				); break; default: self.message += '\n' + new Date.toISOString + ' main :: unsupported skin : ' + wgSkin; delete self.run; delete self.stop; return; }		// run it		onTick; });

return self; }(mediaWiki, jQuery));