User:MastCell/el-search.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:MastCell/el-search. |
/*
* 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;
});
}
});