User:Proteins/sortunorderedlists.js

// // 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(/&gt;/ig, ">"); inner_text2 = inner_text2.replace(/&gt;/ig, ">");

inner_text1 = inner_text1.replace(/&lt;/ig, "<"); inner_text2 = inner_text2.replace(/&lt;/ig, "<");

inner_text1 = inner_text1.replace(/&amp;/ig, "&"); inner_text2 = inner_text2.replace(/&amp;/ig, "&");

inner_text1 = inner_text1.replace(/ /ig, " "); inner_text2 = inner_text2.replace(/ /ig, " ");

inner_text1 = inner_text1.replace(/&#160;/ig, " "); inner_text2 = inner_text2.replace(/&#160;/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', , ); }); //