Jump to content

MediaWiki:Gadget-geonotice-core.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*  _____________________________________________________________________________
 * |                                                                             |
 * |                    === WARNING: GLOBAL GADGET FILE ===                      |
 * |                  Changes to this page affect many users.                    |
 * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. |
 * |_____________________________________________________________________________|
 *
 * Imported as of 8 august 2014 from [[testwiki:MediaWiki:Gadget-geonotice-core.js]]
 * Shows notices to registered users based on their location
 */

/* global jQuery, mediaWiki */

( function ( mw, $ ) {
'use strict';

mw.messages.set( {
	'gn-hideButton': 'Hide'
} );

/**
 * Namespace for all Geonotice methods and properties.
 * @class
 * @singleton
 */
var gn = {};

/**
 * @param {string} str Wiki-text of the link
 * @param {string} page The title of the target page of the link
 * @param {string} text The text to be used for the link
 */
/* jshint unused: true */

gn.geoWikiLinker = function (str, page, text) {
	text = text || page;
	return mw.html.element(
		'a', {
			href: mw.util.getUrl( page ),
			title: page
		}, text
	);
};

/**
 * Handle click events.
 *
 * @param {jQuery.Event} e Click event
 */
gn.hideGeonotice = function (e) {
	e.preventDefault();

	var parentId = $(e.target).closest('li').attr('id').replace( /^geonotice/, '');
	var hiddenNotices = gn.getHiddenNotices();

	hiddenNotices.push(parentId);
	gn.saveHiddenNotices(hiddenNotices);

	$( '#geonotice' + parentId ).hide();
	$( '#geonotice-hr' ).hide();

	return false;
};

/**
 * Boolean indicating whether this will be the first notice added to the page
 */
gn.firstnotice = true;

/**
 * Regular expression used to detect links in wiki-text
 */
gn.regexForInternalLinks = /\[\[([^{|}\[\]\n]+)(?:\|(.*?))?\]\]/g;

/**
 * A key used to store the array of hidden notices in Web Storage
 */
gn.storageKey = 'hidegeonotices';

/**
 * Get a list of the hidden notices
 */
gn.getHiddenNotices = function () {
	var hiddenNotices = mw.storage.get( gn.storageKey )
			|| mw.storage.session.get( gn.storageKey );

	try {
		return JSON.parse(hiddenNotices) || [];
	} catch (e) {
		return [];
	}
};

/**
 * Save the list of the hidden notices
 */
gn.saveHiddenNotices = function ( notices ) {
	notices = JSON.stringify( notices );
	mw.storage.set( gn.storageKey, notices )
		|| mw.storage.session.set( gn.storageKey, notices );
};

/**
 * Removes ids from localstorage that are no longer in use
 */
gn.expungeOldNotices = function( currentList ) {
	var savedList = gn.getHiddenNotices(),
		originalLength = savedList.length;
	for (var i = savedList.length - 1; i >= 0; i--) {
		if( !( savedList[i] in currentList ) ) {
			savedList.splice( i, 0 );
		}
	}
	if( originalLength !== savedList.length ) {
		gn.saveHiddenNotices( savedList );
	}
};

/**
 * Add a notice on top of the watchlist
 *
 * @param {Object} notice Object representing a notice
 */
gn.displayGeonotice = function (notice) {
	var geonoticeText = notice.text.replace( gn.regexForInternalLinks, gn.geoWikiLinker );

	if (gn.firstnotice) {
		gn.firstnotice = false;
		
		$('#watchlist-message').prepend(
			$( '<hr>' ).attr({ 'id' : 'geonotice-hr' })
		);
	}

	$('#watchlist-message').prepend(
		$('<li>')
			.attr({
				'class' : 'geonotice plainlinks',
				'id' : 'geonotice' + notice.id
			})
			.append(
				$( '<span>' )
					.html( geonoticeText ),
				$( '<small>' )
					.append(
						$('<a>')
							.text( mw.msg( 'gn-hideButton' ) )
							.click( gn.hideGeonotice )
							.attr( { 'href' : '#' } )
					)
			)
	).show();
};

/**
 * Determine which notices are still valid and are targeted to the location of the current user
 */
gn.runGeonotice = function () {
	var now = new Date(),
		hide, id, notice, minlat, maxlat, minlon, maxlon,
		startNotice, endNotice,
		hiddenNotices = gn.getHiddenNotices();

	for (id in gn.notices) {
		hide = hiddenNotices.indexOf( id ) >= 0;
		
		if (!hide) {

			notice = gn.notices[id];
			notice.id = id;

			if (!notice || !notice.begin || !notice.end) {
				continue;
			}

			startNotice = Date.parse(notice.begin);
			endNotice = Date.parse(notice.end);

			if ( now.getTime() > startNotice &&
				now.getTime() < endNotice ) {
				if (notice.country && Geo.country === notice.country) {
					gn.displayGeonotice(notice);
				} else {
					if (notice.corners) {
						minlat = Math.min(notice.corners[0][0], notice.corners[1][0]);
						maxlat = Math.max(notice.corners[0][0], notice.corners[1][0]);
						minlon = Math.min(notice.corners[0][1], notice.corners[1][1]);
						maxlon = Math.max(notice.corners[0][1], notice.corners[1][1]);

						// Geo coordinates can be empty string if unknown. parseFloat makes
						// these NaN, so that you do not get to see a notice in that case.
						if ( minlat < parseFloat( Geo.lat ) && parseFloat( Geo.lat ) < maxlat &&
							minlon < parseFloat( Geo.lon ) && parseFloat( Geo.lon ) < maxlon
						) {
							gn.displayGeonotice(notice);
						}
					}
				}
			}
		}
	}
	gn.expungeOldNotices( gn.notices );
};

// Attach to window
window.GeoNotice = $.extend( gn, window.GeoNotice );

if ( window.Geo !== undefined ) {
	$( gn.runGeonotice );
}

}( mediaWiki, jQuery ) );