//<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>