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.
/* Copyright (C) 2012 Lunarity
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*jshint curly:false, laxbreak:true, smarttabs:true, jquery:true*/
/*global mediaWiki */
( function( $, mw, window, Date ) {
"use strict";
// Double-run protection
if ( window.UTCClock ) return;
// Creating the UTCClock
window.UCX = $.extend( { }, window.UCX );
// Creating the configuration object
const config = $.extend(
{ },
window.DisplayClockJS, // For compatibility purposes
window.UTCClockConfig
);
config.kill = $.noop;
// Creating the UTCClock object
const UTCClock = {
defaults: Object.freeze( {
format: "%2H:%2M:%2S %d %b %Y (UTC)",
location: "navigation",
// Shannon's Sampling Theorem: Signal=1Hz, sample it at 2Hz for 100% accuracy
interval: 500,
fontFamily: "Rubik, Helvetica, Arial, sans-serif",
offset: 0,
hoverText: "UTC Clock",
render: null
} ),
interval: null,
killClock: function( ) {
if ( this.interval !== null ) {
clearInterval( this.interval );
this.interval = null;
this.$el.remove( );
}
delete this.config.kill;
},
init: function( ) {
this.config = $.extend(
{ },
config,
this.defaults
);
if ( typeof this.config.hoverText === "string" )
return this.load( );
const c = this;
importArticle( {
type: "script",
article: "u:dev:MediaWiki:I18n-js/code.js"
} ).then( function( ) {
mw.hook( "dev.i18n" ).add( c.loadMsg.bind( c ) );
} );
},
loadMsg: function( i18n ) {
i18n.loadMessages( this.name )
.then( this.setMsg.bind( this ) );
},
setMsg: function( i18n ) {
this.config.hoverText = i18n.msg( "hoverText" ).escape( );
return this.load( );
},
load: function( ) {
const $el = $( "<a>" ).prop( {
href: "?action=purge",
title: this.config.hoverText
} ).data( "UTCClock", this.config );
this.create( $el );
},
create: function( $el ) {
if ( $( "#displayClock, #displayTimer, #showdate" ).length ) return;
const append = Object.freeze( [ "toolbar", "navigation" ] );
const parents = Object.freeze( {
toolbar: $( ".toolbar > .tools" ),
navigation: $( ".fandom-community-header" ),
header: $( ".page-header" )
} );
const location =
parents.hasOwnProperty( this.config.location ) ?
this.config.location :
"toolbar";
const $parent = parents[ location ];
if ( !$parent.length ) {
return console.error( "UTCClock: Cannot find an attachment point. Aborting script." );
}
const $result = $parent.is( "ul" ) ?
$( "<li>" ).append( $el ) :
$el;
if ( $parent.is( ".tools" ) ) $result.css( {
"float": "right" ,
"border-right": "0"
} );
if (location === "navigation") {
mw.util.addCSS("\
.fandom-community-header__top-container {\
grid-column: 2 / span 2;\
}\
.has-no-logo .fandom-community-header__top-container {\
grid-column: 1 / span 3;\
}\
");
}
if ( append.includes( location ) )
$parent.append( $result.prop( "id", "UTCClock" ) );
else
$parent.prepend( $result.prop( "id", "UTCClock" ) );
this.$el = $el;
this.$el.css( {
fontFamily: this.config.fontFamily
} );
this.update( $el );
$el.data( "location", location );
const interval = Math.max(
500,
Math.min( this.config.interval , Infinity )
) || 500;
this.interval = window.setInterval(
this.update.bind( this, $el ),
interval
);
this.config.kill = this.killClock;
},
update: function( $el ) {
if ( !$el.data( "UTCClock" ) ) return this.killClock( );
const d = new Date( );
d.setMinutes(
d.getMinutes( ) +
d.getTimezoneOffset( ) +
this.config.offset
);
const c = this;
mw.loader.using( "mediawiki.language.months", function( ) {
const format = c.getFormatted( );
$el.text( format( d, c.config.format + "" ) );
} );
},
getFormatted: function( ) {
return this.format(
mw.language.months.names,
mw.language.months.abbrev
);
},
format: function( monthsLong, monthsShort, daysLong, daysShort ) {
/* jshint bitwise: false */
const cases = {
// Double percent (insert percent character)
"%": function( ) { return "%"; },
// Day of month (1-31)
d: function( d ) {
const r = d.getDate( );
return { v: r, i: r - 1 };
},
// ISO 8601 Year, used in conjunction with %V
G: function( d ) {
var r = d.getFullYear,
day = d.getDate( ),
month = d.getMonth;
if ( month === 0 && day < 4 ) {
day = d.getDay( );
if ( day === 0 || day > 4 ) r--;
} else if ( month === 11 && day > 28 ) {
month = d.getDay( );
if ( month !== 0 && month < day - 27 ) ++r;
}
return r;
},
// ISO 8601 Short 2 digit year
g: function( d ) { return cases.G( d ) % 100; },
// Hour number (0-23)
H: function( d ) { return d.getHours( ); },
// Hour number (1-12)
I: function( d ) {
const r = d.getHours( ) % 12;
return { i: r, v: r || 12 };
},
// Day of year (1-366)
j: function( d, ys ) {
const r = ( d - ys ) / 864e5 | 0;
return { i: r, v: r + 1 };
},
// Month (0-12)
m: function( d ) {
const r = d.getMonth( );
return { i: r, v: r + 1 };
},
// Minute (0-59)
M: function( d ) { return d.getMinutes( ); },
// AM/PM
p: function( d ) { return d.getHours( ) < 12 ? "AM" : "PM"; },
// Seconds (0-59)
S: function( d ) { return d.getSeconds( ); },
// Day of the week (1-7) [1=Monday]
u: function( d ) {
const r = ( d.getDay( ) + 6 ) % 7;
return { i: r, v: r + 1 };
},
// Week of year using Sunday as the first day of the week (0-53)
U: function( d, ys ) {
var doy = cases.j( d, ys ).i;
doy += ys.getDay( ) || 7;
return ( doy / 7 ) | 0;
},
// ISO 8601 Week (Monday is first day, Week 1 is the one with the first Thursday)
// Range: 1-53
V: function calculateISOWeek( d, ys ) {
var r = { v: cases.W( d, ys ) }, thurs = ys.getDay( );
if ( thurs > 1 && thurs < 5 ) {
++r.v;
} else if ( r.v === 0 ) {
r = d.getFullYear( ) - 1;
return calculateISOWeek( new Date( r, 11, 31 ), new Date( r, 0, 1 ) );
}
r.i = r.v - 1;
return r;
},
// Day of the week (1-7) [1=Sunday]
w: function( d ) {
const r = d.getDay( );
return { i: r, v: r + 1 };
},
// Week of the year using Monday as the first day of the week (0-53)
W: function( d, ys ) {
var doy = cases.j( d, ys ).i;
doy += ( ys.getDay( ) + 6 ) % 7 || 7;
return ( doy / 7 ) | 0;
},
// Locale dependent time string
X: function( d ) {
return d.toLocaleTimeString( );
},
// Locale dependent date string
x: function( d ) {
return d.toLocaleDateString( );
},
// Year (last two digits only)
y: function( d ) { return d.getFullYear( ) % 100; },
// Full year
Y: function( d ) { return d.getFullYear( ); }
};
if ( daysLong ) cases.A = function( d ) {
return daysLong[ d.getDay( ) ];
};
if ( daysShort ) cases.a = function( d ) {
return daysShort[ d.getDay( ) ];
};
if ( monthsLong ) cases.B = function( d ) {
return monthsLong[ d.getMonth( ) ];
};
if ( monthsShort ) cases.b = function( d ) {
return monthsShort[ d.getMonth( ) ];
};
function pad( s, l, c ) {
c = c || ( typeof s === "number" ? "0" : " " );
l = l - ( s += "" ).length | 0;
if ( l <= 0 ) return s;
do {
if ( ( l & 1 ) === 1 ) s = c + s;
c += c;
} while ( ( l >>>= 1 ) !== 0 );
return s;
}
function format( date, string ) {
const pattern = /%([0-9]*)(?:\{([^\}]*)\})?([A-Za-z%])/gi;
var result = "",
start = new Date( date.getFullYear( ), 0, 1 ),
lastIndex = 0,
match, list, parsed, dispatcher;
while ( ( match = pattern.exec( string ) ) !== null ) {
result += string.substring( lastIndex, match.index );
lastIndex = pattern.lastIndex;
dispatcher = cases[ match[ 3 ] ];
if ( typeof dispatcher !== "function" ) {
result += '¿' + match[3] + '?';
continue;
}
parsed = dispatcher( date, start );
if ( match[ 2 ] ) {
if ( typeof parsed === "object" ) {
parsed = parsed.i === void 0 ? parsed.v : parsed.i;
}
if ( typeof parsed === "number" ) {
list = match[ 2 ].split( ";" );
if ( !( parsed > 1 && parsed < list.length ) ) parsed = list.length - 1;
parsed = list[ parsed ];
}
} else if ( typeof parsed === "object" ) {
parsed = parsed.v;
}
result += pad( parsed, parseInt( match[ 1 ], 10 ) );
}
result += string.substr( lastIndex );
return result;
}
return format;
}
};
UTCClock.init( );
window.UTCClock = window.UCX.UTCClock = UTCClock;
mw.hook( "dev.utc-clock" ).fire( window.UTCClock );
} )( jQuery, mediaWiki, window, Date );