User:Proteins/sortunorderedlists.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:Proteins/sortunorderedlists. |
//<pre>
// Sorts an unordered list alphabetically
// Generally useful, but designed for Special:WhatLinksHere
// Uses specialized version of quicksort for unordered lists
//
// To use this script, add "importScript('User:Proteins/sortunorderedlists.js');" to your monobook.js subpage
// under your user page, as you can see at User:Proteins/monobook.js
//************************
// Swap list item function
//************************
function swapTwoListItems(arg_list_items_array, arg_list_index1, arg_list_index2) {
var error_string = "";
var parent_list1;
var parent_list2;
var next_sibling1;
var next_sibling2;
var arg_list_item1;
var arg_list_item2;
// Check for identity
if (arg_list_index1 == arg_list_index2) { return; }
arg_list_item1 = arg_list_items_array[arg_list_index1];
arg_list_item2 = arg_list_items_array[arg_list_index2];
if ((!arg_list_item1) && (!arg_list_item2)) {
error_string = "ERROR: Both list items " + arg_list_index1 + " & " + arg_list_index2 + " do not exist.";
window.alert(error_string);
return;
} else if (!arg_list_item1) {
error_string = "ERROR: List item 1 " + arg_list_index1 + " does not exist.";
window.alert(error_string);
return;
} else if (!arg_list_item2) {
error_string = "ERROR: List item 2 " + arg_list_index2 + " does not exist.";
window.alert(error_string);
return;
}
parent_list1 = arg_list_item1.parentNode;
if (!parent_list1) {
error_string = "ERROR: Parent node of list item 1 does not exist.";
window.alert(error_string);
return;
}
if (parent_list1.nodeType != 1) {
error_string = "ERROR: Parent node of list item 1 is not an Element.";
window.alert(error_string);
return;
}
if (parent_list1.tagName != "UL") {
error_string = "ERROR: Parent node of list item 1 is not a \"UL\" Element.";
window.alert(error_string);
return;
}
parent_list2 = arg_list_item2.parentNode;
if (!parent_list2) {
error_string = "ERROR: Parent node of list item 2 does not exist.";
window.alert(error_string);
return;
}
if (parent_list2.nodeType != 1) {
error_string = "ERROR: Parent node of list item 2 is not an Element.";
window.alert(error_string);
return;
}
if (parent_list2.tagName != "UL") {
error_string = "ERROR: Parent node of list item 2 is not a \"UL\" Element.";
window.alert(error_string);
return;
}
next_sibling1 = arg_list_item1.nextSibling;
next_sibling2 = arg_list_item2.nextSibling;
if ((!next_sibling1) && (!next_sibling2)) {
error_string = "ERROR: Next siblings of both list items are NULL.";
window.alert(error_string);
return;
} else if (!next_sibling1) {
parent_list1.appendChild(arg_list_item2);
parent_list2.insertBefore(arg_list_item1, next_sibling2);
} else if (!next_sibling2) {
parent_list2.appendChild(arg_list_item1);
parent_list1.insertBefore(arg_list_item2, next_sibling1);
} else {
parent_list1.insertBefore(arg_list_item2, next_sibling1);
parent_list2.insertBefore(arg_list_item1, next_sibling2);
}
arg_list_items_array[arg_list_index1] = arg_list_item2;
arg_list_items_array[arg_list_index2] = arg_list_item1;
return;
} // closes function swapTwoListItems()
//***************************
// Compare list item function
//***************************
function compareTwoListItems(arg_list_item1, arg_list_item2) {
var alert_string = "";
var inner_text1;
var inner_text2;
if ((!arg_list_item1) && (!arg_list_item2)) {
alert_string = "00: Both list items are undefined.";
window.alert(alert_string);
return 0;
} else if (!arg_list_item1) {
alert_string = "-1: List item 1 is undefined.";
window.alert(alert_string);
return -1;
} else if (!arg_list_item2) {
alert_string = "+1: List item 2 is undefined.";
window.alert(alert_string);
return 1;
}
inner_text1 = arg_list_item1.innerHTML;
inner_text2 = arg_list_item2.innerHTML;
if ((!inner_text1) && (!inner_text2)) {
alert_string = "00: No innerHTML in either list item.";
window.alert(alert_string);
return 0;
} else if (!inner_text1) {
alert_string = "-1: No innerHTML in list item 1.";
window.alert(alert_string);
return -1;
} else if (!inner_text2) {
alert_string = "+1: No innerHTML in list item 2.";
window.alert(alert_string);
return 1;
}
inner_text1 = inner_text1.replace(/<[^>]+>/ig, "");
inner_text2 = inner_text2.replace(/<[^>]+>/ig, "");
inner_text1 = inner_text1.replace(/>/ig, ">");
inner_text2 = inner_text2.replace(/>/ig, ">");
inner_text1 = inner_text1.replace(/</ig, "<");
inner_text2 = inner_text2.replace(/</ig, "<");
inner_text1 = inner_text1.replace(/&/ig, "&");
inner_text2 = inner_text2.replace(/&/ig, "&");
inner_text1 = inner_text1.replace(/ /ig, " ");
inner_text2 = inner_text2.replace(/ /ig, " ");
inner_text1 = inner_text1.replace(/ /ig, " ");
inner_text2 = inner_text2.replace(/ /ig, " ");
inner_text1 = inner_text1.replace(/\s+/ig, "");
inner_text2 = inner_text2.replace(/\s+/ig, "");
if (inner_text1>inner_text2) {
// alert_string = "+1: " + inner_text1.substr(0,20) + " " + inner_text2.substr(0,20);
// window.alert(alert_string);
return 1;
}
if (inner_text1<inner_text2) {
// alert_string = "-1: " + inner_text1.substr(0,20) + " " + inner_text2.substr(0,20);
// window.alert(alert_string);
return -1;
}
// alert_string = "00: " + inner_text1.substr(0,20) + " " + inner_text2.substr(0,20);
// window.alert(alert_string);
return 0;
} // closes function compareTwoListItems()
//************************
// Partition list function
//************************
function partitionAnUnorderedList(arg_list_items, first_index, last_index, pivot_index) {
var alert_string = "";
var error_string = "";
var temp_list_item;
var num_list_items = 0;
var list_item_index = 0;
var store_item_index = 0;
var pivot_list_item = arg_list_items[pivot_index];
swapTwoListItems(arg_list_items, pivot_index, last_index-1);
// alert_string = "Swapped pivot item " + pivot_index + " to " + (last_index-1) + " position.\n";
// window.alert(alert_string);
store_item_index = first_index;
for (list_item_index=first_index; list_item_index<last_index-1; list_item_index++) {
temp_list_item = arg_list_items[list_item_index];
if (!temp_list_item) {
error_string = "ERROR: Undefined list item " + list_item_index + " in partition of " + first_index + "–" + last_index + " about pivot " + pivot_index + ".\n";
window.alert(error_string);
}
if (!pivot_list_item) {
error_string = "ERROR: Pivot list item " + pivot_index + " in partition of " + first_index + "–" + last_index + " has become undefined.\n";
window.alert(error_string);
}
if (compareTwoListItems(temp_list_item, pivot_list_item) < 0) {
swapTwoListItems(arg_list_items, store_item_index, list_item_index);
store_item_index++;
}
}
swapTwoListItems(arg_list_items, last_index-1, store_item_index);
return store_item_index;
} // closes function partitionAnUnorderedList()
//******************************
// Quicksort for unordered lists
//******************************
function quicksortAnUnorderedList(arg_list_items, first_index, last_index) {
var alert_string = "";
var pivot_index = 0;
if(last_index>first_index) {
pivot_index=(first_index+last_index)/2;
pivot_index = Math.floor(pivot_index);
// alert_string = "For items " + first_index + "–" + last_index + ", the pivot index is " + pivot_index + "\n";
// window.alert(alert_string);
pivot_index=partitionAnUnorderedList(arg_list_items, first_index, last_index, pivot_index);
// alert_string = "Partitioned items " + first_index + "–" + last_index + " about the pivot index " + pivot_index + "\n";
// window.alert(alert_string);
quicksortAnUnorderedList(arg_list_items, first_index, pivot_index);
quicksortAnUnorderedList(arg_list_items, pivot_index+1, last_index);
}
} // closes function quicksortAnUnorderedList()
//**********************************************
// Callback function for individual list buttons
//**********************************************
function sortAnUnorderedList(arg_list) {
var alert_string = "";
var error_string = "";
var child_nodes;
var temp_child_node;
var num_child_nodes = 0;
var child_node_index = 0;
var num_list_items = 0;
var list_items = new Array();
alert_string = "List className = " + arg_list.className + ".";
// window.alert(alert_string);
child_nodes = arg_list.childNodes;
if (!child_nodes) {
alert_string = "This list has no child nodes; there's nothing to sort!";
window.alert(alert_string);
return;
}
num_child_nodes = child_nodes.length;
if (child_nodes<1) {
alert_string = "This list has zero child nodes; there's nothing to sort!";
window.alert(alert_string);
return;
}
num_list_items = 0;
for (child_node_index=0; child_node_index<num_child_nodes; child_node_index++) {
temp_child_node = child_nodes[child_node_index];
if (!temp_child_node) { continue; }
if (temp_child_node.nodeType != 1) { continue; }
if (temp_child_node.tagName != "LI") { continue; }
num_list_items++;
list_items.push(temp_child_node);
} // closes loop over the child nodes
// alert_string = "Found " + num_list_items + " list items of " + num_child_nodes + " child nodes.\n";
// window.alert(alert_string);
// Quicksort for efficiency; useful with 5000-item links
quicksortAnUnorderedList(list_items, 0, num_list_items);
alert_string = "Sorted table of " + num_list_items + " list items.";
window.alert(alert_string);
} // closes function sortAnUnorderedList()
//******************
// The Main Function
//******************
function addSortButtonsToAllUnorderedLists() {
var list_string = "";
var alert_string = "";
var error_string = "";
var body_content;
var temp_list;
var num_lists = 0;
var list_index = 0;
var unordered_lists;
var num_sortable_lists = 0;
var list_items;
var temp_list_item;
var num_list_items = 0;
var temp_hyperlink;
// Get the bodyContent node
body_content = document.getElementById('bodyContent');
if (!body_content) {
error_string = "ERROR: There is no bodyContent node in this article.";
window.alert(error_string);
return;
}
// Get unordered lists
unordered_lists = body_content.getElementsByTagName("UL");
if (!unordered_lists) {
alert_string = "This page has no unordered lists.\n\n";
window.alert(alert_string);
return;
}
num_lists = unordered_lists.length;
if (num_lists < 1) {
alert_string = "This page has zero unordered lists.\n\n";
window.alert(alert_string);
return;
}
// Loop over the unordered lists
list_string = "";
num_sortable_lists = 0;
for (list_index=1; list_index<=num_lists; list_index++) {
temp_list = unordered_lists[list_index-1];
if (!temp_list) {
error_string = "ERROR: Unordered list " + list_index + " is undefined.\n\n";
window.alert(error_string);
continue;
}
// Filter out unwanted lists, such as those of the Table of Contents
list_items = temp_list.getElementsByTagName("LI");
if (!list_items) { continue; }
num_list_items = list_items.length;
if (num_list_items < 1) { continue; }
temp_list_item = list_items[0];
if (!temp_list_item) { continue; }
if (temp_list_item.className.match(/^toclevel/)) { continue; }
// Calculate number of list items at the correct level
child_nodes = temp_list.childNodes;
if (!child_nodes) { continue; }
num_child_nodes = child_nodes.length;
if (child_nodes<1) { continue; }
num_list_items = 0;
for (child_node_index=0; child_node_index<num_child_nodes; child_node_index++) {
temp_child_node = child_nodes[child_node_index];
if (!temp_child_node) { continue; }
if (temp_child_node.nodeType != 1) { continue; }
if (temp_child_node.tagName != "LI") { continue; }
num_list_items++;
} // closes loop over the child nodes
if (num_list_items < 2) { continue; } // a list of one item doesn't need to be sorted
// Create the sorting button and add it at the top of the list
num_sortable_lists++;
list_string += "List " + num_sortable_lists + " has " + num_list_items + " list items.\n";
temp_hyperlink = document.createElement("A");
if (!temp_hyperlink) {
error_string = "ERROR: Unable to create hyperlink in unordered list " + list_index + ".\n";
window.alert(error_string);
continue;
}
temp_hyperlink.onclick = function() { sortAnUnorderedList(this.parentNode); }
temp_hyperlink.appendChild(document.createTextNode("CLICK TO SORT LIST " + num_sortable_lists + " (" + num_list_items + " items)"));
first_child = temp_list.firstChild;
if (first_child) {
temp_list.insertBefore(temp_hyperlink, first_child);
} else {
temp_list.appendChild(temp_hyperlink);
}
} // closes loop over the lists
// Print acknowledgment
alert_string = "Added sort buttons to " + num_sortable_lists + " unordered lists.\n\n";
alert_string += list_string;
window.alert(alert_string);
} // closes function addSortButtonsToAllUnorderedLists()
$(function () {
mw.util.addPortletLink('p-navigation', 'javascript:addSortButtonsToAllUnorderedLists()', 'Sort lists', 'ca-sortlists', 'Sort unordered lists', '', '');
});
//</pre>