User:Evad37/timeless-newMessageHighlight.js

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.
/* timeless-newMessageHighlight
   A script to highlight the username in yellow when there are new messages on your user talk page
   (since the in Timeless skin, the talk page link is hidden in a dropdown). This script should
   only be used with the Timeless skin -- add it to your timeless.js, not your common.js!
   For details on why this is not done by the skin, nor by the Echo extension, see these tasks:
   https://phabricator.wikimedia.org/T215695 and https://phabricator.wikimedia.org/T216046
*/   
// Wait for page load
$( function($) {

	var MOBILE_BREAKPOINT = 850; // px
	
	var hasTalkpageAlert; // Boolean
	
	var recheckInterval;
	var recheckTimeout;
	var clearRecheckingIntervalAndTimeout = function() {
		if ( recheckInterval ) window.clearInterval(recheckInterval);
		if ( recheckTimeout ) window.clearTimeout(recheckTimeout);
		// Reset click handler. Seems to be needed, possibly from Echo mucking about
		// with the <a> elements?
		if ( onNotificationAlertClick ) {
			$('#pt-notifications-alert a').off("click.highlightingCheck");
			$('#pt-notifications-alert a').on("click.highlightingCheck", onNotificationAlertClick);
		}
	};

	// Desktop (and tablet) views
	var setDesktopStyles = function() {
		$('#personal').css({
			'background-color': '#fc3',
			'background-blend-mode': 'multiply',
			'background-clip': 'content-box'
		});
	};
	var removeDesktopStyles = function() {
		$('#personal').css({
			'background-color': 'initial',
			'background-blend-mode': 'initial',
			'background-clip': 'initial'
		});
	};
	var hasDesktopStylesSet = function() {
		return $('#personal').css('background-color') === "rgb(255, 204, 51)"; // #fc3;
	};
	
	// Mobile views (only needs styles when below breakpoint)
	var addStylesForMobileView = function() {
		$('#personal h2').css({
			'background-color': '#fc3',
			'background-blend-mode': 'multiply'
		});
	};
	var removeStylesForMobileView = function() {
		$('#personal h2').css({
			'background-color': 'initial',
			'background-blend-mode': 'initial'
		});
	};
	var hasMobileViewStylesSet = function() {
		return $('#personal h2').css('background-color') === "rgb(255, 204, 51)"; // #fc3;
	};
	var setMobileViewStyles = function() {
		var isStyled = hasMobileViewStylesSet();
		if ( window.innerWidth <= MOBILE_BREAKPOINT && !isStyled ) {
			setTimeout(addStylesForMobileView, 1);
		} else if ( window.innerWidth > MOBILE_BREAKPOINT && isStyled ) {
			setTimeout(removeStylesForMobileView, 1);
		}
	};
	
	// Set state of desktop / mobile view styles
	var setUpHighlighting = function() {
		hasTalkpageAlert = $('#user-tools').has('.mw-echo-alert').length > 0;
		if ( hasTalkpageAlert ) {
			if ( !hasDesktopStylesSet() ) {
				setDesktopStyles();
				clearRecheckingIntervalAndTimeout();
			}
			setMobileViewStyles();
		} else {
			if ( hasDesktopStylesSet() ) {
				removeDesktopStyles();
				clearRecheckingIntervalAndTimeout();
			}
			if ( hasMobileViewStylesSet() ) {
				removeStylesForMobileView();
			}
		}
	};
	// Set initial state
	setUpHighlighting();
	
	/* Respond when the window resizes, throttled to every 0.2 seconds.
	 * Derived from code by Mozilla Contributors, licensed under CC-BY-SA 2.5,
	 * at https://developer.mozilla.org/en-US/docs/Web/Events/resize#setTimeout
	 */
	window.addEventListener("resize", resizeThrottler, false);
	var resizeTimeout;
	var actualResizeHandler = function() {
		return hasTalkpageAlert && setTimeout(setMobileViewStyles, 1);
	};
	function resizeThrottler() {
		// ignore resize events as long as an actualResizeHandler execution is in the queue
		if ( !resizeTimeout ) {
			resizeTimeout = setTimeout(function() {
				resizeTimeout = null;
				actualResizeHandler();
			}, 200);
		}
	}
	
	/* Clicks on the notifications menu may add/remove the yellow background from the talkpage
	   link, so we do a check every 5 seconds to see if we need to reset the highlighting
	   (on or off).
	   For efficiency this is time-limited to period starting from when the notifications-alert
	   icon is clicked, and ending either when the highlighting state changes, or 60 seconds
	   have elapsed. 
	   Adding a callback to a hook would be prefereable, but Echo doesn't seem to provide
	   such hooks. And the mark as read/unread links aren't available till some time after the
	   user clicks on the bell icon, so click-event callbacks can't be used either. :(
	*/
	var onNotificationAlertClick = function() {
		recheckInterval = window.setInterval(setUpHighlighting, 5000);
		recheckTimeout = window.setTimeout(function() {
			clearRecheckingIntervalAndTimeout();
		}, 60000);
	};
	$('#pt-notifications-alert a').on("click.highlightingCheck", onNotificationAlertClick);
});