Memory Alpha
Advertisement
Memory Alpha

Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Chrome - Windows: Hold the Ctrl key and press the F5 key. OS X: Hold both the ⌘ Cmd and ⇧ Shift keys and press the R key.
  • Safari - Hold down the ⇧ Shift key and click the Reload toolbar button.
  • Firefox - Windows: Hold the Ctrl key, and press F5. OS X: Hold the ⌘ Cmd and ⇧ Shift keys, and then press R.
  • Internet Explorer - Hold the Ctrl key, and press F5 (or click the Refresh button).
/**
 * Adds a category intersection page using DynamicPageList and links to find pages in any two categories specified by the user.
 * 
 * Uses OOUI and MediaWiki core JS, see https://doc.wikimedia.org/oojs-ui/master/js/#!/api/OO.ui and https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw for details.
 */
$(function () {
	'use strict';

	if (mw.config.get('wgAction') === 'view') {
		const title = 'Category intersection';
		const intersectionPage = 'Special:BlankPage/CategoryIntersection';
		const searchParams = new URLSearchParams(location.search);
		const pageName = mw.config.get('wgPageName');
		const isCategoryPage = mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').category;
		const isResultsPage = pageName === intersectionPage && Array.from(searchParams.keys()).filter(function (param) {
			return param === 'category1' || param === 'category2';
		}).length === 2;
		const isFormPage = pageName === intersectionPage && !isResultsPage;
		
		// Add links to category pages
		if (isCategoryPage) {
			const category = mw.config.get('wgTitle').replaceAll(' ', '_');
			const baseUrl = '/wiki/' + intersectionPage + '?category1=' + category;
			var filters = '<li><a href="'+baseUrl+'">Category intersection</a></li>';
			$('#p-cactions .wds-list').append(filters);
		}
		
		// Results page
		if (isResultsPage) {
			const pageUrl = window.location.origin + window.location.pathname;
			const category1 = searchParams.get('category1').replaceAll(' ', '_');
			const category2 = searchParams.get('category2').replaceAll(' ', '_');

			document.title = title;
			$('#firstHeading').html(title);
			$('#firstHeading + .page-header__page-subtitle').append('<br />&lt; <a href="' + pageUrl + '">New category intersection query</a>');
			$('#mw-content-text').empty();

			// Style results like category page
			const importPromise = importArticles({
				type: "script",
				articles: [
					"jquery.spinner"
				]
			}, {
				type: "style",
				articles: [
					"ext.fandom.CategoryPage.category-page-mediawiki.css",
					"mediawiki.action.view.categoryPage.styles"
				]
			}).then(function () {
				$('#mw-content-text').append($.createSpinner({
					size: 'large',
					type: 'block'
				}));
				return Promise.resolve();
			});

			// Build DPL query
			const count = 200;
			var currentPage = Number.parseInt(searchParams.get('page')) || 1;
			if (!Number.isInteger(currentPage) || currentPage < 1) currentPage = 1;
			const offset = (currentPage - 1) * count;
			const headerTitle = '==Pages in categories "[[:Category:' + category1 + '|' + category1.replaceAll('_', ' ') + ']]" and "[[:Category:' + category2 + '|' + category2.replaceAll('_', ' ') + ']]"==';
			const basePaginationLink = pageUrl + '?category1=' + category1 + '&category2=' + category2;
			const previousLink = currentPage > 1 ? '[' + basePaginationLink + '&page=' + (currentPage - 1) + ' previous page]' : 'previous page';
			const nextLink = '[' + basePaginationLink + '&page=' + (currentPage + 1) + ' next page]';
			const headerLinks = '{{#ifeq:{{#expr:%TOTALPAGES%>' + count + '}}|1|(' + previousLink + ') ({{#ifeq:{{#expr:%TOTALPAGES%>' + (offset + count) + '}}|1|' + nextLink + '|next page}})|}}';
			var dpl = '<DPL>\n';
			dpl += '  category = ' + category1 + '\n';
			dpl += '  category = ' + category2 + '\n';
			dpl += '  count = ' + count + '\n';
			dpl += '  offset = ' + offset + '\n';
			dpl += '  mode = category\n';
			dpl += '  noresultsheader = \\n' + headerTitle + '\\n\'\'These categories currently contain no pages in common.\'\'\n';
			dpl += '  oneresultheader = \\n' + headerTitle + '\\nThese categories contain only the following page in common.\n';
			dpl += '  ordermethod = sortkey\n';
			dpl += '  resultsfooter = ' + headerLinks + '\n';
			dpl += '  resultsheader = \\n' + headerTitle + '\\nThe following %PAGES% pages are common to these categories, out of <span class="dpl-total-pages">%TOTALPAGES%</span> total.\\n\\n' + headerLinks + '\n';
			dpl += '</DPL>';

			// Get results from API
			const apiPromise = new mw.Api().post({
				action: 'parse',
				format: 'json',
				title: title,
				text: dpl,
				contentformat: 'text/x-wiki',
				contentmodel: 'wikitext'
			}).catch(function (code, result) {
				if (code === 'http') {
					$('#mw-content-text').html('<p>HTTP error fetching intersection results: ' + result.textStatus + '</p>');
				} else {
					$('#mw-content-text').html('<p>API error fetching intersection results: ' + result.error.info + '</p>');
				}
				return Promise.reject();
			});

			Promise.all([apiPromise, importPromise]).then(function (results) {
				$('#mw-content-text').html(results[0].parse.text['*']);
				$('#mw-content-text a[target="_blank"]').removeAttr('target');
				const totalPages = Number.parseInt($('#mw-content-text .dpl-total-pages').eq(0).html()) || 0;
				if (totalPages > count) {
					const pagesToShow = 21;
					const pagesLeft = Math.round(pagesToShow / 2) - 1;
					const pagesRight = pagesToShow % 2 === 0 ? Math.round(pagesToShow / 2) : Math.round(pagesToShow / 2) - 1;
					const maxPage = Math.ceil(totalPages / count);
					var startPage, endPage;
					if (maxPage >= pagesToShow) {
						if (currentPage <= pagesLeft) {
							startPage = 1;
							endPage = pagesToShow;
						} else if (currentPage >= maxPage - pagesLeft) {
							startPage = maxPage - pagesToShow + 1;
							endPage = maxPage;
						} else {
							startPage = currentPage - pagesLeft;
							endPage = currentPage + pagesRight;
						}
					} else {
						startPage = 1;
						endPage = maxPage;
					}
					const pageSeparator = ' <b>·</b> ';
					var pagination = '<div class="dpl-pagination">';
					pagination += '<b>Go to page:</b> ';
					if (currentPage > 2 && startPage > 1) {
						pagination += '<a href="' + basePaginationLink + '" aria-label="Page 1">1</a>';
						pagination += startPage > 2 ? pageSeparator : ' ';
					}
					for (var page = startPage; page <= endPage; page++) {
						pagination += '<a href="' + basePaginationLink + '&page=' + page + '" aria-label="Page ' + page + (page === currentPage ? ' (current)' : '') + '">' + (page === currentPage ? '<b>' + page + '</b>' : page) + '</a> ';
					}
					if (currentPage < maxPage - 1 && endPage < maxPage) {
						pagination += endPage < maxPage - 1 ? pageSeparator : ' ';
						pagination += '<a href="' + basePaginationLink + '&page=' + maxPage + '" aria-label="Page ' + maxPage + '">' + maxPage + '</a>';
					}
					pagination += '</div>';
					$('#mw-content-text').prepend(pagination);
				}
			});
		}
		
		// Intersect any category form
		if (isFormPage) {
			document.title = title;
			$('#firstHeading').html(title);
			const mwContentText = $('#mw-content-text');
			mwContentText.empty();
		
			importArticles({
				type: "script",
				articles: [
					"oojs-ui-core",
					"mediawiki.widgets"
				]
			}, {
				type: "style",
				articles: [
					"oojs-ui-core.styles"
				]
			}).then(function () {
				const form = new OO.ui.FormLayout({
					method: 'get'
				});
				for (var index = 1; index <= 2; index++) {
					form.addItems([
						new OO.ui.FieldLayout(new mw.widgets.TitleInputWidget({
							id: 'dpl-cat' + index,
							name: 'category' + index,
							namespace: 14,
							required: true,
							value: searchParams.has('category' + index) ? searchParams.get('category' + index).replaceAll('_', ' ') : undefined,
							$overlay: true
						}), {
							label: 'Category:',
							align: 'top'
						}),
					]);
				}
				form.addItems([
					new OO.ui.FieldLayout(new OO.ui.ButtonInputWidget({
						type: 'submit',
						label: 'Go',
						value: 'Go',
						flags: [
							'primary',
							'progressive'
						],
						classes: [
							'mw-htmlform-submit'
						]
					}))
				]);
				const panel = new OO.ui.PanelLayout({
					expanded: false,
					$content: form.$element
				});
				mwContentText.append(panel.$element);
			});
		}
	}
});
Advertisement