User:NguoiDungKhongDinhDanh/Dashboard.js

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)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// Inspired by [[User:DannyS712/GlobalUserDashboard.js]]
// TODO: //stackoverflow.com/q/4909167
// jshint esversion: 10

$(function() {
	var Dashboard = {};
	
	Dashboard.item = function(o) {
		var header = o.h || 'Unnamed item';
		var server = o.s || '';
		var content = '';
		
		if (Boolean(o.d)) {
			return '';
		}
		
		if (o.c) {
			for (let i of o.c) {
				let t = Dashboard.link(i);
				content += t ? (
					`<div class="dashboardItemItem">
						<span>
							${t || ''}
							${i.c ? i.c : ''}
						</span>
					</div>`
				) : '';
			}
		}
		
		return content ? (
			`<div class="dashboardItem">
				<div>
					<div class="dashboardItemHeaderWrapper">
						<h3 class="dashboardItemHeader">${header}</h3>
						<span class="dashboardItemSubtitle">
							${server ? `<a href="//${server}">${server}</a>` : '&nbsp;'}
						</span>
					</div>
					<div class="dashboardItemContentWrapper">
						<div class="dashboardItemContent">${content}</div>
					</div>
				</div>
			</div>`
		) : '';
	};
	Dashboard.link = function(o) {
		var link = o.l || '';
		var func = Boolean(o.f);
		var text = o.t || link.split('/').pop();
		var para = typeof o.p === 'object' ? $.param(o.p) : '';
		
		if (o.k) {
			let t = window.dashboardFunction.behaviour[o.k];
			if (t.check()) {
				link = `behaviour[${o.k}].fn`;
			}
		}
		
		if (!func) {
			return `<a class="dashboardLink" target="_blank" href="${link}${para}">${text}</a>`;
		} else if (link) {
			return `<a class="dashboardFunction" href="#" onclick="dashboardFunction.${link}(); return false;">${text}</a>`;
		}
	};
	Dashboard.locallink = function(t, p) {
		var link = t ? mw.config.get('wgArticlePath').replace('$1', t.replace(/ /g, '_')) : '';
		if (typeof p === 'object') {
			link += $.param(p);
		}
		return link;
	};
	
	// For attribution: [[:d:WD:TOOLS]]
	Dashboard.css = (`
		#dashboard {
			display: grid;
			gap: 10px;
			grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
			clear: both;
			margin: 1em;
		}
		@media only screen and (max-width: 1200px) {
			#dashboard {
				grid-template-columns: repeat(auto-fit, minmax(25%, 1fr));
			}
		}
		@media only screen and (max-width: 950px) {
			#dashboard {
				grid-template-columns: repeat(auto-fit, minmax(33.33%, 1fr));
			}
		}
		@media only screen and (max-width: 700px) {
			#dashboard {
				grid-template-columns: repeat(auto-fit, minmax(50%, 1fr));
			}
		}
		.dashboardItem {
			margin: 0.5em;
			box-sizing: border-box;
			box-shadow: 0 0 0.2em #999999;
			border-radius: 0.2em;
			background-color: white;
			word-break: break-word;
			white-space: nowrap;
			font-family: 'Roboto', 'Helvetica', sans-serif;
			transition: box-shadow 0.1s;
		}
		.dashboardItem:hover {
			box-shadow: 0 0 0.4em #999999;
		}
		.dashboardFade {
			opacity: 0.6;
			box-shadow: 0 0 0.1em #999999;
		}
		.dashboardItemHeaderWrapper {
			position: relative;
			border-radius: 0.2em;
			background-color: white;
			padding: 1.5em 2.5em;
		}
		.dashboardItem:hover .dashboardItemHeaderWrapper {
			z-index: 11;
		}
		.dashboardItemHeader {
			cursor: default;
			margin: 0;
			padding: 0;
			font-size: 1.5em;
		}
		.dashboardItemSubtitle {
			-webkit-user-select: none;
			-ms-user-select: none;
			user-select: none;
			margin-bottom: 1.5em;
			font-size: 0.8em;
		}
		.dashboardItemContentWrapper {
			position: relative;
		}
		.dashboardItemContent {
			display: grid;
			visibility: hidden;
			opacity: 0;
			position: absolute;
			top: -0.4em;
			gap: 5px 10px;
			grid-template-columns: repeat(auto-fit, minmax(33.33%, 1fr));
			box-sizing: border-box;
			box-shadow: 0 0 0.4em #999999;
			border-radius: 0.2em;
			width: 100%;
			background-color: white;
			padding: 0.6em 2.5em 1.5em;
			transition: opacity 0.4s, box-shadow 0.4s;
			z-index: 10;
		}
		.dashboardItem:hover .dashboardItemContent {
			visibility: visible;
			opacity: 1;
		}
		.dashboardItemItem {
			display: flex;
			justify-content: center;
			cursor: pointer;
			gap: 4px;
			align-items: center;
			margin: 0;
			line-height: 1.5em;
			padding: 0.5em;
		}
		.dashboardItemItem:hover {
			background-color: #999999;
		}
		.dashboardItemItem:hover a {
			color: #FFFFFF;
		}
		.dashboardItemItem a {
			color: #000000;
		}
		.dashboardItemItem a:hover,
 		.dashboardItemItem a:focus {
			text-decoration: none;
		}
	`);
	try {
		mw.util.addCSS(Dashboard.css);
	} catch (e) {
		mw.loader.addStyleTag(Dashboard.css);
	}
	
	mw.util.addPortletLink('p-tb', 'javascript:void(0)', 'Dashboard', 't-dashboard');
	Dashboard.toggle = false;
	
	$('#t-dashboard').click(function(e) {
		e.preventDefault();
		Dashboard.toggle = !Dashboard.toggle;
		
		if (!$('#dashboard').length) {
			$('#bodyContent').after(
				$('<div>').attr('id', 'dashboard').css('display', 'none')
			);
			$('#dashboard').append(function() {
				var r = '';
				if (window.dashboardContent) {
					for (let i of window.dashboardContent) {
						r += Dashboard.item(i);
					}
				}
				return r;
			});
			$('#dashboard').click(function(e) {
				if (!$(e.target).is('.dashboardItem *')) {
					$('#bodyContent, #dashboard').toggle();
				}
			});
			$('.dashboardItem').on('mouseenter mouseleave', function() {
				$('.dashboardItem').not(this).toggleClass('dashboardFade');
			});
			$('.dashboardItem').on('click', '.dashboardItemItem', function(e) {
				let $t = $(e.target).find('a');
				
				if ($t.is('.dashboardLink')) {
					window.open($t.attr('href'));
				} else if ($t.is('.dashboardFunction')) {
					(new Function($t.attr('onclick')))();
				}
			});
		}
		
		$('#content > header, #bodyContent, #dashboard').toggle();
	});
});