User:Proteins/quickdiffs.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/quickdiffs. |
//<pre>
// Summarizes the differences between two page versions in pop-up windows
// Perhaps calculate fractional change in document?
//
// To use this script, add "importScript('User:Proteins/quickdiffs.js');" to your monobook.js subpage
// under your user page, as you can see at User:Proteins/monobook.js
function quickDiffs() {
var alert_string = "";
var num_alert_strings = 0;
var alert_string_index = 0;
var alert_string_list = new Array();
var body_content;
var article_tables;
var temp_article_table;
var num_article_tables = 0;
var article_table_index = 0;
var diff_table;
var num_diff_tables = 0;
var diff_table_body;
var diff_table_bodies;
var num_diff_table_bodies = 0;
var temp_table_row;
var diff_table_rows;
var table_row_index= 0;
var num_diff_table_rows = 0;
var table_row_data;
var temp_table_datum;
var table_datum_index = 0;
var num_table_row_data = 0;
var temp_table_datum_text = "";
var temp_table_datum_text_node;
var diff_old_version_info; //className = "diff-otitle"
var diff_new_version_info; //className = "diff-ntitle"
var mw_diff_otitle1;
var mw_diff_otitle1_child;
var mw_diff_otitle1_grandchild;
var mw_diff_otitle1_text = "";
var mw_diff_otitle2;
var mw_diff_otitle2_child;
var mw_diff_otitle2_grandchild;
var mw_diff_otitle2_text = "";
var mw_diff_otitle3;
var mw_diff_otitle3_child;
var mw_diff_otitle3_grandchild;
var mw_diff_otitle3_text = "";
var mw_diff_otitle4;
var mw_diff_otitle4_child;
var mw_diff_otitle4_grandchild;
var mw_diff_otitle4_text = "";
var mw_diff_ntitle1;
var mw_diff_ntitle1_child;
var mw_diff_ntitle1_grandchild;
var mw_diff_ntitle1_text = "";
var mw_diff_ntitle2;
var mw_diff_ntitle2_child;
var mw_diff_ntitle2_grandchild;
var mw_diff_ntitle2_text = "";
var mw_diff_ntitle3;
var mw_diff_ntitle3_child;
var mw_diff_ntitle3_grandchild;
var mw_diff_ntitle3_text = "";
var mw_diff_ntitle4;
var mw_diff_ntitle4_child;
var mw_diff_ntitle4_grandchild;
var mw_diff_ntitle4_text = "";
var revisions = "";
var num_revisions = 0;
var num_line_numbers = 0;
var current_old_line_number = 0;
var current_new_line_number = 0;
var old_line_numbers = new Array();
var new_line_numbers = new Array();
var line_number_flag = 0;
var num_diff_addedlines = 0;
var num_diff_deletedlines = 0;
var num_diff_context_lines = 0;
var num_diff_undefined_lines = 0;
var num_changes = 0;
var num_additions = 0;
var num_deletions = 0;
var num_replacements = 0;
var span_index = 0;
var num_potential_spans = 0;
var temp_added_span;
var added_span_nodes;
var num_added_spans = 0;
var added_span_text = "";
var temp_added_line = "";
var prev_added_line = "";
var temp_added_span_text = "";
var temp_deleted_span;
var deleted_span_nodes;
var num_deleted_spans = 0;
var deleted_span_text = "";
var temp_deleted_line = "";
var prev_deleted_line = "";
var temp_deleted_span_text = "";
var num_changed_lines = 0;
var diff_added_lines = new Array();
var diff_deleted_lines = new Array();
var num_changes_in_line = new Array();
var diff_changes = new Array();
var diff_change_line_numbers = new Array();
// Check that there is exactly one table on this page with the className "diff"
body_content = document.getElementById('bodyContent');
if (!body_content) {
alert_string = "ERROR: This article has no bodyContent element.";
window.alert(alert_string);
return;
}
article_tables = body_content.getElementsByTagName("TABLE");
if (!article_tables) {
alert_string = "ERROR: This article has no TABLE elements.";
window.alert(alert_string);
return;
}
num_article_tables = article_tables.length;
if (!num_article_tables) {
alert_string = "ERROR: This article has no TABLE elements.";
window.alert(alert_string);
return;
}
num_diff_tables = 0;
for (article_table_index=0; article_table_index<num_article_tables; article_table_index++) {
temp_article_table = article_tables[article_table_index];
if (!temp_article_table) { continue; }
if (temp_article_table.className == "diff") {
num_diff_tables++;
diff_table = temp_article_table;
}
} // closes loop searching for the diff table
if (num_diff_tables == 0) {
alert_string = "ERROR: This article has no TABLE elements belonging to the \"diff\" class.";
window.alert(alert_string);
return;
} else if (num_diff_tables != 1) {
alert_string = "ERROR: This article has " + num_diff_tables + " TABLE elements belonging to the \"diff\" class.";
alert_string += "An article should have at most one \"diff\" table.\n";
window.alert(alert_string);
return;
}
// Check that there is exactly one table body
diff_table_bodies = diff_table.getElementsByTagName("TBODY");
if (!diff_table_bodies) {
alert_string = "ERROR: This article has no TBODY element within its \"diff\" table.";
window.alert(alert_string);
return;
}
num_diff_table_bodies = diff_table_bodies.length;
if (!num_diff_table_bodies) {
alert_string = "ERROR: This article has no TBODY element within its \"diff\" table.";
window.alert(alert_string);
return;
} else if (num_diff_table_bodies != 1) {
alert_string = "ERROR: This article has " + num_diff_table_bodies + " TBODY elements within its \"diff\" table.";
alert_string += "A \"diff\" table should have at most one TBODY element.\n";
window.alert(alert_string);
return;
}
diff_table_body = diff_table_bodies[0];
if (!diff_table_body) {
alert_string = "ERROR: This article has a null TBODY element within its \"diff\" table.";
window.alert(alert_string);
return;
}
// Loop over the table rows in the table body
diff_table_rows = diff_table_body.getElementsByTagName("TR");
if (!diff_table_rows) {
alert_string = "ERROR: This article has no TR elements within its \"diff\" table body.";
window.alert(alert_string);
return;
}
num_diff_table_rows = diff_table_rows.length;
if (!num_diff_table_rows) {
alert_string = "ERROR: This article has no TR elements within its \"diff\" table body.";
window.alert(alert_string);
return;
} else if (num_diff_table_rows == 1) {
alert_string = "This article has only one row (TR element) within its \"diff\" table body.";
alert_string += "This shouldn't happen under ordinary circumstances; however, it suggests that the two versions are identical\n";
window.alert(alert_string);
return;
}
// Get header texts for older version
mw_diff_otitle1_text = "";
mw_diff_otitle1 = document.getElementById('mw-diff-otitle1');
if (!mw_diff_otitle1) {
window.alert("ERROR: This article has no element with id \"mw-diff-otitle1\".\n\n");
} else {
mw_diff_otitle1_child = mw_diff_otitle1.firstChild;
if (!mw_diff_otitle1_child) {
window.alert("ERROR: The \"mw-diff-otitle1\" element has no child node.\n\n");
} else {
mw_diff_otitle1_grandchild = mw_diff_otitle1_child.firstChild;
if (!mw_diff_otitle1_grandchild) {
window.alert("ERROR: The \"mw-diff-otitle1\" element has no grandchild node.\n\n");
} else {
mw_diff_otitle1_text = mw_diff_otitle1_grandchild.innerHTML;
} // closes check for grandchild node
} // closes check for child node
} // closes check for mw_diff_otitle1 node
// window.alert("The mw_diff_otitle1_text is " + mw_diff_otitle1_text + "\n");
mw_diff_otitle2_text = "";
mw_diff_otitle2 = document.getElementById('mw-diff-otitle2');
if (!mw_diff_otitle2) {
window.alert("ERROR: This article has no element with id \"mw-diff-otitle2\".\n\n");
} else {
mw_diff_otitle2_child = mw_diff_otitle2.firstChild;
if (!mw_diff_otitle2_child) {
window.alert("ERROR: The \"mw-diff-otitle2\" element has no child node.\n\n");
} else {
mw_diff_otitle2_text = mw_diff_otitle2_child.innerHTML;
} // closes check for child node
} // closes check for mw_diff_otitle2 node
// window.alert("The mw_diff_otitle2_text is " + mw_diff_otitle2_text + "\n");
mw_diff_otitle3_text = "";
mw_diff_otitle3 = document.getElementById('mw-diff-otitle3');
if (!mw_diff_otitle3) {
window.alert("ERROR: This article has no element with id \"mw-diff-otitle3\".\n\n");
} else {
mw_diff_otitle3_text = mw_diff_otitle3.innerHTML;
mw_diff_otitle3_text = mw_diff_otitle3_text.replace(/>/ig, ">");
mw_diff_otitle3_text = mw_diff_otitle3_text.replace(/</ig, "<");
mw_diff_otitle3_text = mw_diff_otitle3_text.replace(/(<([^>]+)>)/ig,"");
} // closes check for mw_diff_otitle3 node
// window.alert("The mw_diff_otitle3_text is " + mw_diff_otitle3_text + "\n");
// Possibly add code for mw_diff_otitle4 here, but seems unneeded
// Get header texts for newer version
mw_diff_ntitle1_text = "";
mw_diff_ntitle1 = document.getElementById('mw-diff-ntitle1');
if (!mw_diff_ntitle1) {
window.alert("ERROR: This article has no element with id \"mw-diff-ntitle1\".\n\n");
} else {
mw_diff_ntitle1_child = mw_diff_ntitle1.firstChild;
if (!mw_diff_ntitle1_child) {
window.alert("ERROR: The \"mw-diff-ntitle1\" element has no child node.\n\n");
} else {
mw_diff_ntitle1_grandchild = mw_diff_ntitle1_child.firstChild;
if (!mw_diff_ntitle1_grandchild) {
window.alert("ERROR: The \"mw-diff-ntitle1\" element has no grandchild node.\n\n");
} else {
mw_diff_ntitle1_text = mw_diff_ntitle1_grandchild.innerHTML;
} // closes check for grandchild node
} // closes check for child node
} // closes check for mw_diff_ntitle1 node
// window.alert("The mw_diff_ntitle1_text is " + mw_diff_ntitle1_text + "\n");
mw_diff_ntitle2_text = "";
mw_diff_ntitle2 = document.getElementById('mw-diff-ntitle2');
if (!mw_diff_ntitle2) {
window.alert("ERROR: This article has no element with id \"mw-diff-ntitle2\".\n\n");
} else {
mw_diff_ntitle2_child = mw_diff_ntitle2.firstChild;
if (!mw_diff_ntitle2_child) {
window.alert("ERROR: The \"mw-diff-ntitle2\" element has no child node.\n\n");
} else {
mw_diff_ntitle2_text = mw_diff_ntitle2_child.innerHTML;
} // closes check for child node
} // closes check for mw_diff_ntitle2 node
// window.alert("The mw_diff_ntitle2_text is " + mw_diff_ntitle2_text + "\n");
mw_diff_ntitle3_text = "";
mw_diff_ntitle3 = document.getElementById('mw-diff-ntitle3');
if (!mw_diff_ntitle3) {
window.alert("ERROR: This article has no element with id \"mw-diff-ntitle3\".\n\n");
} else {
mw_diff_ntitle3_text = mw_diff_ntitle3.innerHTML;
mw_diff_ntitle3_text = mw_diff_ntitle3_text.replace(/>/ig, ">");
mw_diff_ntitle3_text = mw_diff_ntitle3_text.replace(/</ig, "<");
mw_diff_ntitle3_text = mw_diff_ntitle3_text.replace(/(<([^>]+)>)/ig,"");
} // closes check for mw_diff_ntitle3 node
// window.alert("The mw_diff_ntitle3_text is " + mw_diff_ntitle3_text + "\n");
// Possibly add code for mw_diff_ntitle4 here, but seems unneeded
// Loop over the rows in the difference table
num_alert_strings = 0;
alert_string_list[0] = "NONE";
num_revisions = 1;
revisions = "The newer version is separated from the older version by one revision.";
for (table_row_index=0; table_row_index<num_diff_table_rows; table_row_index++) {
temp_table_row = diff_table_rows[table_row_index];
if (!temp_table_row) { continue; }
table_row_data = temp_table_row.getElementsByTagName("TD");
if (!table_row_data) { continue; }
num_table_row_data = table_row_data.length;
if (!num_table_row_data) { continue; }
temp_added_line = "";
temp_deleted_line = "";
line_number_flag = 0;
num_diff_addlines = 0;
num_diff_deletedlines = 0;
num_diff_context_lines = 0;
num_diff_undefined_lines = 0;
for (table_datum_index=0; table_datum_index<num_table_row_data; table_datum_index++) {
temp_table_datum = table_row_data[table_datum_index];
if (!temp_table_datum) { continue; }
if (temp_table_datum.className == "diff-lineno") {
temp_table_datum_text_node = temp_table_datum.firstChild;
if (!temp_table_datum_text_node) { continue; }
if (temp_table_datum_text_node.nodeType != 3) { continue; }
temp_table_datum_text = temp_table_datum_text_node.data;
temp_table_datum_text = temp_table_datum_text.replace(/[^0-9]*/ig, "");
if (line_number_flag == 0) {
current_old_line_number = temp_table_datum_text - 2;
line_number_flag = 1;
} else if (line_number_flag == 1) {
current_new_line_number = temp_table_datum_text - 2;
line_number_flag = 2;
} else if (line_number_flag == 2) {
// ignore this table_datum as anomalous
// there should be only two line numbers in any table row
} else {
alert_string = "ERROR: Line_number_flag = " + line_number_flag + " in datum " + table_datum_index + " of diff table row " + table_row_index + ".\n";
window.alert(alert_string);
return;
}
} else if (temp_table_datum.className == "diff-multi") {
temp_table_datum_text_node = temp_table_datum.firstChild;
if (!temp_table_datum_text_node) { continue; }
if (temp_table_datum_text_node.nodeType == 3) {
num_revisions = 0; // to flag for errors
temp_table_datum_text = temp_table_datum_text_node.data;
if (temp_table_datum_text.match(/^\(One/)) {
num_revisions = 2;
} else {
temp_table_datum_text = temp_table_datum_text.replace(/[^0-9]*/ig, "");
if (temp_table_datum_text) {
num_revisions = temp_table_datum_text;
num_revisions++;
}
}
if (num_revisions == 1) { // should never happen, but...
revisions = "The newer version is separated from the older version by one revision.";
} else {
revisions = "The newer version is separated from the older version by " + num_revisions + " revisions.";
}
} // closes check that the first child node is a text node
} else if (temp_table_datum.className == "diff-context") {
num_diff_context_lines++;
} else if (temp_table_datum.className == "diff-addedline") {
num_diff_addedlines = 1;
num_added_spans = 0;
added_span_text = "";
temp_added_line = temp_table_datum.innerHTML;
if (temp_added_line) {
// replace HTML tags
temp_added_line = temp_added_line.replace(/>/ig, ">");
temp_added_line = temp_added_line.replace(/</ig, "<");
temp_added_line = temp_added_line.replace(/(<([^>]+)>)/ig,"");
// replace renamed wiki links
temp_added_line = temp_added_line.replace(/\[\[([^\|\]]+?)\|([^\|]+?)\]\]/ig,"$2");
// replace renamed HTTP links, such as external links and diffs
temp_added_line = temp_added_line.replace(/\[http:([^\s]+)\s(.*?)\]/, "$2");
temp_added_line = temp_added_line.replace(/&/ig, "&");
temp_added_line = temp_added_line.replace(/ /ig, " ");
temp_added_line = temp_added_line.replace(/ /ig, " ");
temp_added_line = temp_added_line.replace(/\'\'\'/ig, "");
temp_added_line = temp_added_line.replace(/\'\'/ig, "");
temp_added_line = temp_added_line.replace(/\s+/ig, " ");
} else { temp_added_line = ""; }
if (temp_added_line.replace(/\s/ig, "").length < 1) { num_diff_addedlines = 0; continue; }
added_span_nodes = temp_table_datum.getElementsByTagName("SPAN");
if (!added_span_nodes) { num_added_spans = 0; continue; }
num_potential_spans = added_span_nodes.length;
for (span_index=0; span_index<num_potential_spans; span_index++) {
temp_added_span = added_span_nodes[span_index];
if (!temp_added_span) { continue; }
temp_added_span_text = temp_added_span.innerHTML;
if (!temp_added_span_text) { continue; }
temp_added_span_text = temp_added_span_text.replace(/(<([^>]+)>)/ig,"");
if (!temp_added_span_text) { continue; }
num_added_spans++;
added_span_text += "\t Addition " + num_added_spans + ": " + temp_added_span_text + "\n";
} // closes loop over the added spans
added_span_text = "The " + num_added_spans + " additions were:\n" + added_span_text;
} else if (temp_table_datum.className == "diff-deletedline") {
num_diff_deletedlines = 1;
num_deleted_spans = 0;
deleted_span_text = "";
temp_deleted_line = temp_table_datum.innerHTML;
if (temp_deleted_line) {
// replace HTML tags
temp_deleted_line = temp_deleted_line.replace(/>/ig, ">");
temp_deleted_line = temp_deleted_line.replace(/</ig, "<");
temp_deleted_line = temp_deleted_line.replace(/(<([^>]+)>)/ig,"");
// replace renamed wiki links
temp_deleted_line = temp_deleted_line.replace(/\[\[([^\|\]]+?)\|([^\|]+?)\]\]/ig,"$2");
// replace renamed HTTP links, such as external links and diffs
temp_deleted_line = temp_deleted_line.replace(/\[http:([^\s]+)\s(.*?)\]/, "$2");
temp_deleted_line = temp_deleted_line.replace(/&/ig, "&");
temp_deleted_line = temp_deleted_line.replace(/ /ig, " ");
temp_deleted_line = temp_deleted_line.replace(/ /ig, " ");
temp_deleted_line = temp_deleted_line.replace(/\'\'\'/ig, "");
temp_deleted_line = temp_deleted_line.replace(/\'\'/ig, "");
temp_deleted_line = temp_deleted_line.replace(/\s+/ig, " ");
} else { temp_deleted_line = ""; }
if (temp_deleted_line.replace(/\s/ig, "").length < 1) { num_diff_deletedlines = 0; continue; }
deleted_span_nodes = temp_table_datum.getElementsByTagName("SPAN");
if (!deleted_span_nodes) { num_deleted_spans = 0; continue; }
num_potential_spans = deleted_span_nodes.length;
for (span_index=0; span_index<num_potential_spans; span_index++) {
temp_deleted_span = deleted_span_nodes[span_index];
if (!temp_deleted_span) { continue; }
temp_deleted_span_text = temp_deleted_span.innerHTML;
if (!temp_deleted_span_text) { continue; }
temp_deleted_span_text = temp_deleted_span_text.replace(/(<([^>]+)>)/ig,"");
if (!temp_deleted_span_text) { continue; }
num_deleted_spans++;
deleted_span_text += "\t Deletion " + num_deleted_spans + ": " + temp_deleted_span_text + "\n";
} // closes loop over the deleted spans
deleted_span_text = "The " + num_deleted_spans + " deletions were:\n" + deleted_span_text;
} else if (temp_table_datum.className == "diff-marker") {
// do nothing
} else {
num_diff_undefined_lines++;
} // closes classification of the table datum
} // closes loop over the data within a table row
if ((num_diff_addedlines > 0) && (temp_added_line) && (num_diff_deletedlines > 0) && (temp_deleted_line)) {
current_new_line_number++;
current_old_line_number++;
num_replacements++;
alert_string = "Text replacement " + num_replacements + " in line number " + current_new_line_number + " of the newer version (line number " + current_old_line_number + " of the older version)\n\n";
alert_string += "There were " + num_added_spans + " additions and " + num_deleted_spans + " deletions to arrive at the current version of this line:\n\n";
alert_string += temp_added_line + "\n\n";
if ((num_added_spans>15) && (alert_string)) {
num_alert_strings++;
alert_string_list[num_alert_strings-1] = alert_string;
// window.alert(alert_string);
alert_string = "";
}
if (num_added_spans>0) {
alert_string += added_span_text;
}
if ((num_deleted_spans>15) && (alert_string)) {
num_alert_strings++;
alert_string_list[num_alert_strings-1] = alert_string;
// window.alert(alert_string);
alert_string = "";
}
if (num_deleted_spans>0) {
alert_string += deleted_span_text;
}
if (alert_string) {
num_alert_strings++;
alert_string_list[num_alert_strings-1] = alert_string;
// window.alert(alert_string);
}
} else if ((num_diff_addedlines > 0) && (temp_added_line)) {
num_additions++;
current_new_line_number++;
alert_string = "Text addition " + num_additions + " in line number " + current_new_line_number + " of the newer version (line number " + current_old_line_number + " of the older version)\n\n";
alert_string += "The following line was added to the article:\n\n";
alert_string += temp_added_line;
num_alert_strings++;
alert_string_list[num_alert_strings-1] = alert_string;
// window.alert(alert_string);
} else if ((num_diff_deletedlines > 0) && (temp_deleted_line)) {
num_deletions++;
current_old_line_number++;
alert_string = "Text deletion " + num_deletions + " in line number " + current_new_line_number + " of the newer version (line number " + current_old_line_number + " of the older version)\n\n";
alert_string += "The following line was deleted from the article:\n\n";
alert_string += temp_deleted_line;
num_alert_strings++;
alert_string_list[num_alert_strings-1] = alert_string;
// window.alert(alert_string);
} else if (num_diff_context_lines == 2) {
current_new_line_number++;
current_old_line_number++;
} // closes classification change as addition, deletion or replacement
} // closes loop over the table rows
// Report the results
alert_string = "";
if (revisions) {
alert_string += revisions + "\n\n";
}
num_changes = num_additions + num_deletions + num_replacements;
if (num_changes == 0) {
alert_string += "The two versions are identical.";
window.alert(alert_string);
} else {
alert_string += "The newer version differs by ";
if (num_additions == 1) {
alert_string += "one addition";
} else if (num_additions > 1) {
alert_string += num_additions + " additions";
}
if (num_additions>0) {
if (num_additions == num_changes) {
alert_string += ".\n\n";
} else if ((num_deletions == 0) || (num_replacements == 0)) {
alert_string += " and ";
} else {
alert_string += ", ";
}
}
if (num_deletions == 1) {
alert_string += "one deletion";
} else if (num_deletions > 1) {
alert_string += num_deletions + " deletions";
}
if (num_deletions>0) {
if (num_replacements > 0) {
alert_string += " and ";
} else {
alert_string += ".\n\n";
}
}
if (num_replacements == 1) {
alert_string += "one replacement.\n\n";
} else if (num_replacements > 1) {
alert_string += num_replacements + " replacements.\n\n";
}
if (num_alert_strings == 1) {
alert_string += "These changes will be described on the following alert window.\n";
} else if (num_alert_strings > 1) {
alert_string += "These changes will be described on the following " + num_alert_strings + " alert windows.\n";
}
window.alert(alert_string);
for (alert_string_index=0; alert_string_index<num_alert_strings; alert_string_index++) {
alert_string = alert_string_list[alert_string_index];
window.alert(alert_string);
}
} // closes check for zero changes
} // closes function quickDiffs()
addOnloadHook(function () {
mw.util.addPortletLink('p-cactions', 'javascript:quickDiffs()', 'qd', 'ca-quickdiff', 'Summarizes the differences between two page versions', 'b', '');
});
//</pre>