Jump to content

User:MastCell/el-search.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.
/*
 * File: el-search.js
 * Author: MastCell
 * Language: Javascript
 * Dependencies:
 *	jQuery (bundled with MediaWiki)
 *	api.js (by Conrad Irwin; original at http://en.wiktionary.org/wiki/User:Conrad.Irwin/Api.js)
 * Other credits:
 *	Leverages code from a variety of sources, including ^demon's old CSD-rationale script
 * =================================================================================================
 * Purpose: 	This script adds a drop-down selection box to restrict external-link searches to
 *		a specific namespace. Often, one is only interested in external links in
 *		articlespace, so it's useful to be able to filter these. The MediaWiki API
 *		has a handy option to restrict external-link queries by namespace, but
 *		for whatever reason, it doesn't have an associated UI gadget at
 *		Special:LinkSearch. This script is intended to fill that gap.
 * =================================================================================================
 * Under the hood:
 *	Pretty straightforward. The script:
 *		1. Adds a namespace selection box to Special:LinkSearch.
 *		2. Intercepts the "Search" button
 *		3. Reroutes it to the API via AJAX
 *		4. Throws the results into human-readable form.
 *	Note that the script runs on the client side, so you won't be able to bookmark results.
 * =================================================================================================
 * Usage:
 *	To use this gadget, go to your vector.js file (or, if you use a skin besides vector, go to
 *	the appropriate .js file). For me, it's at User:MastCell/vector.js.
 *		
 *	Once you're in your vector.js file, simply add the following line:
 *		importScript('User:MastCell/el-search.js');
 
 *	... then save and reload. After that, it should just work. You can go to
 *	Special:LinkSearch and try it out. You should see a drop-down box next to the
 *	"Search" button, with a list of namespaces.
 */
 
 
// Include local copy of api.js, which facilitates AJAX queries to the MediaWiki API
// The original library is at http://en.wiktionary.org/wiki/User:Conrad.Irwin/Api.js
importScript('User:MastCell/api.js');
 
 
/*
 * Function: fillSelect()
 * Parameters: None
 * Return value: 	Returns a Select object filled in with Wikipedia's namespaces
 *			and corresponding numerical values
 * ==================================================================================
 * This is a helper function to fill in a drop-down box. The function creates a "select"
 * input, fills it with the relevant namespaces and corresponding numerical values,
 * and then returns the drop-down box, which can then be inserted into the DOM.
 *
 * The drop-down box is assigned the id "nsoptions", so that it can be
 * located easily later on.
 */
 
function fillSelect() {
	var namespaceList = [ {
		"value" : "-99",
		"display" : "All namespaces"
	}, {
		"value" : "0",
		"display" : "Article"
	}, {
		"value" : "1",
		"display" : "Talk"
	}, {
		"value" : "2",
		"display" : "User"
	}, {
		"value" : "3",
		"display" : "User Talk"
	}, {
		"value" : "4",
		"display" : "Wikipedia"
	}, {
		"value" : "5",
		"display" : "Wikipedia Talk"
	}, {
		"value" : "6",
		"display" : "Image"
	}, {
		"value" : "7",
		"display" : "Image Talk"
	}, {
		"value" : "8",
		"display" : "MediaWiki"
	}, {
		"value" : "9",
		"display" : "MediaWiki Talk"
	}, {
		"value" : "10",
		"display" : "Template"
	}, {
		"value" : "11",
		"display" : "Template Talk"
	}, {
		"value" : "12",
		"display" : "Help"
	}, {
		"value" : "13",
		"display" : "Help Talk"
	}, {
		"value" : "14",
		"display" : "Category"
	}, {
		"value" : "15",
		"display" : "Category Talk"
	} ];
	var sel = document.createElement("select");
	sel.disabled = false;
	for (var i = 0; i < namespaceList.length; i++) {
		var opt = new Option(namespaceList[i].display, namespaceList[i].value);
		// catches stupid IE error
		if (opt.innerHTML != namespaceList[i].display) {
			opt.innerHTML = namespaceList[i].display;
		}
		sel.appendChild(opt);
	}
	sel.name = "nsoptions";
	sel.id = "nsoptions";
	sel.style.marginLeft = "10px";
        return sel;
}
 
 
/*
 * Function: 	handleFormSubmission()
 * Params:	None.
 * Returns:	Nothing.
 * ================================================================================================
 * This function is called when the user clicks on the "Search" button on the HTML form. It calls the
 * MediaWiki API, using api.js, and then returns. The result is sent back asynchronously and dispatched
 * to processELresults() for handling.
 *
 * This function sets the UI to a "busy" state; it disables the Search button (to prevent multiple
 * simultaneous queries) and shows a spinner while waiting for the results. Note that the AJAX
 * callback function (in this case, processELresults()) is responsible for restoring the UI
 * to its functional state once the query is complete.
 */
 
function handleFormSubmission() {
	// Set the "busy" UI...	
	$("#mw-linksearch-form :submit").attr("value", "Searching...");
	$("#mw-linksearch-form :submit").attr("disabled", "true");
	if ($("#progress-spinner").length > 0) {
		// Show spinner
		$("#progress-spinner").show();
	} else {
		// Create and show spinner
		$("#mw-linksearch-form :submit").after('<span id="progress-spinner"><img src="http://upload.wikimedia.org/wikipedia/commons/4/42/Loading.gif" alt="Loading..."></span>');
	}
 
	// AJAX call to retrieve results...
	var targetLink = $("#target").val();
  	var localAPI = JsMwApi();
	var namespaceOpt = $("#nsoptions").val();
	if (namespaceOpt == -99) {
		// Search all namespaces
		localAPI({action: "query", list: "exturlusage", euquery: targetLink, eulimit: "1000"}, processELresults);
	} else {
		// Search only the restricted namespace
		localAPI({action: "query", list: "exturlusage", euquery: targetLink, eulimit: "1000", eunamespace: namespaceOpt}, processELresults);
	}
}
 
 
/*
 * Function: 	processELresults()
 * Params:	result (a query object returned by api.js, containing the results of the user request)
 * Returns:	Nothing
 * ====================================================================================================================================
 * This function is called when the AJAX query returns with results from the MediaWiki database. It processes the results and
 * puts them in a user-friendly list, patterned after the result view from Special:LinkSearch.
 *
 * Note that this function is responsible for restoring the functional UI (from the "busy" state) once it is completed.
 */
 
function processELresults(result) {
	// Remove old list, if any
	if ($("#el-result-list").length > 0) {
		$("#el-result-list").remove();
	}
 
	if (result.query.exturlusage.length == 0) {
		// No links were found
		var noneFound = '<div id="el-result-list">No links to ';
		noneFound += $("#target").val();
		noneFound += " were found in the given namespace.</div>";
		$("#mw-linksearch-form").after(noneFound);
	} else {
		// Create a result list
		$("#mw-linksearch-form").after('<ol id="el-result-list"></ol>');
 
		// Populate the result list
		for (var i = 0; i < result.query.exturlusage.length; i++) {
			var listItem = '<li><a href="';
      			listItem += result.query.exturlusage[i].url;
      			listItem += '" class="external">';
      			listItem += result.query.exturlusage[i].url;
      			listItem += '</a> is linked from <a href="';
			// Make sure the wikilinks work from the secure server
			if (document.domain == "secure.wikimedia.org") {
				listItem += '/wikipedia/en/wiki/';
			} else {
				listItem += '/wiki/';
			}
      			listItem += encodeURI(result.query.exturlusage[i].title);
      			listItem += '" title="';
      			listItem += result.query.exturlusage[i].title;
      			listItem += '">';
      			listItem += result.query.exturlusage[i].title;
      			listItem += "</a></li>";
			$("#el-result-list").append(listItem);
		}
	}
 
	// Clear the "busy" UI...
	$("#mw-linksearch-form :submit").attr("value", "Search");
	$("#mw-linksearch-form :submit").removeAttr("disabled");
	$("#progress-spinner").hide();
}
 
 
// Adds a hook to check if we're on Special:LinkSearch. If so,
// we create and place the drop-down box. Then we intercept clicks
// on the "Search" button and re-route them to our handler.
addOnloadHook(function() {
	if (mw.config.get('wgPageName') == "Special:LinkSearch") {
		var sel = fillSelect();
		$("#target").after(sel);
		$("#mw-linksearch-form").submit(function(event) {
			event.preventDefault();
			handleFormSubmission();
			return false;
		});
	}
});