//<pre>
// Analyze the chemical reactions on a page
//
// To use this script, add "importScript('User:Proteins/chemicalreactions.js');" to your monobook.js subpage
// under your user page, as you can see at User:Proteins/monobook.js
var isotope_names = {
"n" : "neutron",
"H" : "hydrogen",
"D" : "deuterium",
"T" : "tritium",
"He" : "helium",
"Li" : "lithium",
"Be" : "beryllium",
"B" : "boron",
"C" : "carbon",
"C13" : "carbon-13",
"N" : "nitrogen",
"N15" : "nitrogen-15",
"O" : "oxygen",
"F" : "fluorine",
"Ne" : "neon"
};
var isotope_abbreviations = {
"neutron" : "n",
"hydrogen" : "H",
"deuterium" : "D",
"tritium" : "T",
"helium" : "He",
"lithium" : "Li",
"beryllium" : "Be",
"boron" : "B",
"carbon" : "C",
"carbon-13" : "C13",
"nitrogen" : "N",
"nitrogen-15" : "N15",
"oxygen" : "O",
"fluorine" : "F",
"neon" : "Ne"
};
var isotope_atomic_numbers = {
"n" : "0",
"H" : "1",
"D" : "1",
"T" : "1",
"He" : "2",
"Li" : "3",
"Be" : "4",
"B" : "5",
"C" : "6",
"C13" : "6",
"N" : "7",
"N15" : "7",
"O" : "8",
"F" : "9",
"Ne" : "10"
};
var isotope_weights = {
"n" : "1.0",
"H" : "1.0",
"D" : "2.0",
"T" : "3.0",
"He" : "4.0",
"Li" : "7.0",
"Be" : "9.0",
"B" : "11.0",
"C" : "12.0",
"C13" : "13.0",
"N" : "14.0",
"N15" : "15.0",
"O" : "16.0",
"F" : "19.0",
"Ne" : "20.0"
};
var isotope_indices = {
"n" : "0",
"H" : "1",
"D" : "2",
"T" : "3",
"He" : "4",
"Li" : "5",
"Be" : "6",
"B" : "7",
"C" : "8",
"C13" : "9",
"N" : "10",
"N15" : "11",
"O" : "12",
"F" : "13",
"Ne" : "14"
};
var isotope_abbreviation_array = [
"n",
"H", "D", "T", "He",
"Li", "Be", "B", "C", "C13", "N", "N15", "O", "F", "Ne"
];
var atomic_element_abbreviation_array = [
"n", // 0 atomic number is also defined
"H", "He",
"Li", "Be", "B", "C", "N", "O", "F", "Ne"
];
var isotope_name_array = [
"neutron",
"hydrogen",
"deuterium",
"tritium",
"helium",
"lithium",
"beryllium",
"boron",
"carbon",
"carbon-13",
"nitrogen",
"nitrogen-15",
"oxygen",
"fluorine",
"neon"
];
//*******************
// The Main Function
//*******************
function analyzeChemicalReactions() {
var alert_string = "";
var error_string = "";
var diagnostic_string = "";
var products_string = "";
var reactants_string = "";
var products_Mw_string = "";
var reactants_Mw_string = "";
var body_content;
var span_nodes;
var temp_span_node;
var num_span_nodes = 0;
var span_node_index = 0;
var temp_chemical_reaction;
var chemical_reaction_name = "";
var chemical_reaction_list = new Array();
var num_reactions = 0;
var reaction_index = 0;
var reaction_symbol = "";
var reaction_symbol_node;
var reaction_products_node;
var reaction_reactants_node;
var num_product_molecules = 0;
var num_reactant_molecules = 0;
var num_product_molecule_types = 0;
var num_reactant_molecule_types = 0;
var child_nodes;
var temp_child_node;
var num_child_nodes = 0;
var child_node_index = 0;
var molecule_node;
var num_molecules = 0;
var molecule_index = 0;
var molecule_title = "";
var num_molecule_types = 0;
var molecule_type_index = 0;
var molecule_type_name = "";
var atom_node;
var num_atoms = 0;
var atom_index = 0;
var num_atom_types = 0;
var atom_type_index = 0;
var connecting_text = "";
var prefactor_num_molecules = 1;
var product_molecule_node;
var product_molecule_node_list = new Array();
var product_molecule_name_list = new Array();
var product_molecule_count_list = new Array();
var reactant_molecule_node;
var reactant_molecule_node_list = new Array();
var reactant_molecule_name_list = new Array();
var reactant_molecule_count_list = new Array();
var isotope_index = 0;
var max_num_isotopes = 0;
var isotope_name = "";
var isotope_abbreviation = "";
var atomic_number = 0;
var molecular_weight = 0.0;
var total_molecular_weight = 0.0;
var sum_products_molecular_weights = 0.0;
var sum_reactants_molecular_weights = 0.0;
var subscript_node;
var subscript_nodes;
var reaction_is_balanced = true;
var balanced_reaction_string = "";
var product_num_atoms = new Array();
var reactant_num_atoms = new Array();
// Initialize the reaction-balancing arrays
max_num_isotopes = isotope_name_array.length;
for (isotope_index=0; isotope_index<max_num_isotopes; isotope_index++) {
product_num_atoms[isotope_index] = 0;
reactant_num_atoms[isotope_index] = 0;
}
//****************************************
// Find the chemical reactions on the page
//****************************************
num_chemical_reactions = 0;
// 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;
}
span_nodes = body_content.getElementsByTagName("SPAN");
if (!span_nodes) {
error_string = "ERROR: This page has no SPAN nodes.\n";
window.alert(error_string);
return;
}
num_span_nodes = span_nodes.length;
if (num_span_nodes < 1) {
error_string = "ERROR: This page has no SPAN nodes.\n";
window.alert(error_string);
return;
}
for (span_node_index=0; span_node_index<num_span_nodes; span_node_index++) {
temp_span_node = span_nodes[span_node_index];
if (!temp_span_node) { continue; }
if (temp_span_node.className == "chemical-reaction") {
num_chemical_reactions++;
chemical_reaction_list.push(temp_span_node);
}
} // closes loop over the SPAN nodes in the main article
if (num_chemical_reactions < 1) {
error_string = "No chemical reactions were found on this page.";
window.alert(error_string);
return;
} else if (num_chemical_reactions == 1) {
alert_string = "This page has one chemical reaction.\n\n";
window.alert(alert_string);
} else {
alert_string = "This page has " + num_chemical_reactions + " chemical reactions.\n\n";
alert_string += "These will be analyzed in individual pop-up windows.\n";
window.alert(alert_string);
}
//*********************************************
// Loop over the chemical reactions on the page
//*********************************************
for (reaction_index=1; reaction_index<=num_chemical_reactions; reaction_index++) {
alert_string = ""; // reset the alert string
// Reset the reaction-balancing arrays
for (isotope_index=0; isotope_index<max_num_isotopes; isotope_index++) {
product_num_atoms[isotope_index] = 0;
reactant_num_atoms[isotope_index] = 0;
}
temp_chemical_reaction = chemical_reaction_list[reaction_index-1];
if (!temp_chemical_reaction) {
error_string = "ERROR: Chemical reaction " + reaction_index + " is undefined.\n";
window.alert(error_string);
continue;
}
chemical_reaction_name = temp_chemical_reaction.title;
if (!chemical_reaction_name) {
error_string = "ERROR: No name is defined for chemical reaction " + reaction_index + ".\n";
window.alert(error_string);
chemical_reaction_name = "UNNAMED REACTION";
}
alert_string += "Reaction " + reaction_index + " represents the " + chemical_reaction_name + "\n\n";
// window.alert(alert_string);
child_nodes = temp_chemical_reaction.childNodes;
if (!child_nodes) {
error_string = "ERROR: Chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has no child nodes.\n";
window.alert(error_string);
continue;
}
num_child_nodes = child_nodes.length;
if (num_child_nodes<3) {
error_string = "ERROR: Chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has " + num_child_nodes + " child nodes, fewer than the minimum number 3.\n";
window.alert(error_string);
continue;
}
reaction_symbol_node = null;
reaction_products_node = null;
reaction_reactants_node = null;
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.className) { continue; }
if (temp_child_node.className == "reaction-reactants") {
reaction_reactants_node = temp_child_node;
}
if (temp_child_node.className == "reaction-symbol") {
reaction_symbol_node = temp_child_node;
}
if (temp_child_node.className == "reaction-products") {
reaction_products_node = temp_child_node;
}
} // closes loop over the child nodes of the chemical reaction
if (reaction_reactants_node == null) {
error_string = "ERROR: The reactants element of chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") is missing.\n";
window.alert(error_string);
continue;
}
if (reaction_symbol_node == null) {
error_string = "ERROR: The symbol element of chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") is missing.\n";
window.alert(error_string);
continue;
}
if (reaction_products_node == null) {
error_string = "ERROR: The products element of chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") is missing.\n";
window.alert(error_string);
continue;
}
// alert_string += "Found the reaction reactants, symbol and products elements for chemical reaction " + reaction_index + " (" + chemical_reaction_name + ").\n";
// window.alert(alert_string);
//**********************
// Analyze the reactants
//**********************
child_nodes = reaction_reactants_node.childNodes;
if (!child_nodes) {
error_string = "ERROR: The reactants node of chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has no child nodes (molecules).\n";
window.alert(error_string);
continue;
}
num_child_nodes = child_nodes.length;
if (num_child_nodes<1) {
error_string = "ERROR: The reactants node of chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has zero child nodes (molecules).\n";
window.alert(error_string);
continue;
}
num_reactant_molecules = 0;
prefactor_num_molecules = 1;
num_reactant_molecule_types = 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) { // element node
if (!temp_child_node.className) { continue; }
if (temp_child_node.className == "molecule") {
num_reactant_molecules += prefactor_num_molecules;
reactant_molecule_count_list[num_reactant_molecule_types] = prefactor_num_molecules;
reactant_molecule_node_list[num_reactant_molecule_types] = temp_child_node;
molecule_type_name = temp_child_node.title;
if (!molecule_type_name) { molecule_type_name = "unknown molecule"; }
reactant_molecule_name_list[num_reactant_molecule_types] = molecule_type_name;
prefactor_num_molecules = 1;
num_reactant_molecule_types++;
}
} else if (temp_child_node.nodeType == 3) { // text node
connecting_text = temp_child_node.data;
connecting_text = connecting_text.replace(/[^0-9]/g, "");
if (!connecting_text) {
prefactor_num_molecules = 1;
} else {
prefactor_num_molecules = connecting_text - 0;
}
}
} // closes loop over the child nodes of the reaction_reactants_node
sum_reactants_molecular_weights = 0.0;
for (molecule_type_index=0; molecule_type_index<num_reactant_molecule_types; molecule_type_index++) {
num_molecules = reactant_molecule_count_list[molecule_type_index];
reactant_molecule_node = reactant_molecule_node_list[molecule_type_index];
if (!reactant_molecule_node) {
error_string = "ERROR: Reactant molecule type " + molecule_type_index + " in chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") is undefined.\n";
window.alert(error_string);
continue;
}
span_nodes = reactant_molecule_node.getElementsByTagName("SPAN");
if (!span_nodes) {
error_string = "ERROR: Reactant molecule type " + molecule_type_index + " in chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has no SPAN nodes (atoms).\n";
window.alert(error_string);
continue;
}
num_span_nodes = span_nodes.length;
if (num_span_nodes<1) {
error_string = "ERROR: Reactant molecule type " + molecule_type_index + " in chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has zero SPAN nodes (atoms).\n";
window.alert(error_string);
continue;
}
molecular_weight = 0.0;
for (span_node_index=0; span_node_index<num_span_nodes; span_node_index++) {
temp_span_node = span_nodes[span_node_index];
if (!temp_span_node) { continue; }
if (temp_span_node.className != "atom") { continue; }
isotope_name = temp_span_node.title;
if (!isotope_name) { isotope_name = "hydrogen"; }
isotope_abbreviation = isotope_abbreviations[isotope_name];
atomic_number = isotope_atomic_numbers[isotope_abbreviation];
isotope_index = isotope_indices[isotope_abbreviation] - 0;
subscript_nodes = temp_span_node.getElementsByTagName("SUB");
if (!subscript_nodes) {
num_atoms = 1;
} else {
subscript_node = subscript_nodes[0];
if (!subscript_node) {
num_atoms = 1;
} else {
num_atoms = subscript_nodes[0].innerHTML;
}
}
reactant_num_atoms[isotope_index] += num_molecules * num_atoms - 0;
molecular_weight += num_atoms*isotope_weights[isotope_abbreviation] - 0;
total_molecular_weight = num_molecules * molecular_weight;
} // closes loop over child nodes (atoms) in molecule
reactant_molecule_name_list[molecule_type_index] += " \t " + num_molecules + " x Mw " + molecular_weight + " = " + total_molecular_weight + " Da";
sum_reactants_molecular_weights += total_molecular_weight;
} // closes loop over reactant molecule types
reactants_string = "The " + num_reactant_molecules + " reactant molecules are:\n";
for (molecule_type_index=0; molecule_type_index<num_reactant_molecule_types; molecule_type_index++) {
num_molecules = reactant_molecule_count_list[molecule_type_index];
if (num_molecules != 1) {
reactants_string += "\t " + num_molecules + " molecules of ";
} else {
reactants_string += "\t 1 molecule of ";
}
reactants_string += reactant_molecule_name_list[molecule_type_index] + "\n";
}
reactants_Mw_string = "Molecular weight of reactants = " + sum_reactants_molecular_weights + " Da\n";
//*********************
// Analyze the products
//*********************
child_nodes = reaction_products_node.childNodes;
if (!child_nodes) {
error_string = "ERROR: The products node of chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has no child nodes (molecules).\n";
window.alert(error_string);
continue;
}
num_child_nodes = child_nodes.length;
if (num_child_nodes<1) {
error_string = "ERROR: The products node of chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has zero child nodes (molecules).\n";
window.alert(error_string);
continue;
}
num_product_molecules = 0;
prefactor_num_molecules = 1;
num_product_molecule_types = 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) { // element node
if (!temp_child_node.className) { continue; }
if (temp_child_node.className == "molecule") {
num_product_molecules += prefactor_num_molecules;
product_molecule_count_list[num_product_molecule_types] = prefactor_num_molecules;
product_molecule_node_list[num_product_molecule_types] = temp_child_node;
molecule_type_name = temp_child_node.title;
if (!molecule_type_name) { molecule_type_name = "unknown molecule"; }
product_molecule_name_list[num_product_molecule_types] = molecule_type_name;
prefactor_num_molecules = 1;
num_product_molecule_types++;
}
} else if (temp_child_node.nodeType == 3) { // text node
connecting_text = temp_child_node.data;
connecting_text = connecting_text.replace(/[^0-9]/g, "");
if (!connecting_text) {
prefactor_num_molecules = 1;
} else {
prefactor_num_molecules = connecting_text - 0;
}
}
} // closes loop over the child nodes of the reaction_products_node
sum_products_molecular_weights = 0.0;
for (molecule_type_index=0; molecule_type_index<num_product_molecule_types; molecule_type_index++) {
num_molecules = product_molecule_count_list[molecule_type_index];
product_molecule_node = product_molecule_node_list[molecule_type_index];
if (!product_molecule_node) {
error_string = "ERROR: Product molecule type " + molecule_type_index + " in chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") is undefined.\n";
window.alert(error_string);
continue;
}
span_nodes = product_molecule_node.getElementsByTagName("SPAN");
if (!span_nodes) {
error_string = "ERROR: Product molecule type " + molecule_type_index + " in chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has no SPAN nodes (atoms).\n";
window.alert(error_string);
continue;
}
num_span_nodes = span_nodes.length;
if (num_span_nodes<1) {
error_string = "ERROR: Product molecule type " + molecule_type_index + " in chemical reaction " + reaction_index + " (" + chemical_reaction_name + ") has zero SPAN nodes (atoms).\n";
window.alert(error_string);
continue;
}
molecular_weight = 0.0;
for (span_node_index=0; span_node_index<num_span_nodes; span_node_index++) {
temp_span_node = span_nodes[span_node_index];
if (!temp_span_node) { continue; }
if (temp_span_node.className != "atom") { continue; }
isotope_name = temp_span_node.title;
if (!isotope_name) { isotope_name = "hydrogen"; }
isotope_abbreviation = isotope_abbreviations[isotope_name];
atomic_number = isotope_atomic_numbers[isotope_abbreviation];
isotope_index = isotope_indices[isotope_abbreviation] - 0;
subscript_nodes = temp_span_node.getElementsByTagName("SUB");
if (!subscript_nodes) {
num_atoms = 1;
} else {
subscript_node = subscript_nodes[0];
if (!subscript_node) {
num_atoms = 1;
} else {
num_atoms = subscript_nodes[0].innerHTML;
}
}
product_num_atoms[isotope_index] += num_molecules * num_atoms - 0;
molecular_weight += num_atoms*isotope_weights[isotope_abbreviation] - 0;
total_molecular_weight = num_molecules * molecular_weight;
} // closes loop over child nodes (atoms) in molecule
product_molecule_name_list[molecule_type_index] += " \t " + num_molecules + " x Mw " + molecular_weight + " = " + total_molecular_weight + " Da";
sum_products_molecular_weights += total_molecular_weight;
} // closes loop over product molecule types
products_string = "The " + num_product_molecules + " product molecules are:\n";
for (molecule_type_index=0; molecule_type_index<num_product_molecule_types; molecule_type_index++) {
num_molecules = product_molecule_count_list[molecule_type_index];
if (num_molecules != 1) {
products_string += "\t " + num_molecules + " molecules of ";
} else {
products_string += "\t 1 molecule of ";
}
products_string += product_molecule_name_list[molecule_type_index] + "\n";
}
products_Mw_string = "Molecular weight of products = " + sum_products_molecular_weights + " Da\n";
//****************************
// Analyze the reaction symbol
//****************************
reaction_symbol = reaction_symbol_node.title;
if (!reaction_symbol) {
error_string = "ERROR: The reaction symbol is undefined.\n";
window.alert(error_string);
continue;
}
switch (reaction_symbol) {
case "equilibrium":
alert_string += "This reaction is an equilibrium between " + num_reactant_molecules + " reactant and " + num_product_molecules + " product molecules.\n\n";
break;
case "forward":
case "forwards":
case "forward_reaction":
alert_string += "This is the forward reaction from " + num_reactant_molecules + " reactant molecules to " + num_product_molecules + " product molecules.\n\n";
break;
case "backward":
case "backwards":
case "back_reaction":
case "backward_reaction":
alert_string += "This is the backward reaction from " + num_product_molecules + " product molecules to " + num_reactant_molecules + " reactant molecules.\n\n";
break;
case "forward_equilibrium":
alert_string += "This reaction is an equilibrium between " + num_reactant_molecules + " reactant and " + num_product_molecules + " product molecules that is strongly biased towards the products.\n\n";
break;
case "backward_equilibrium":
alert_string += "This reaction is an equilibrium between " + num_reactant_molecules + " reactant and " + num_product_molecules + " product molecules that is strongly biased towards the reactants.\n\n";
break;
default:
error_string = "ERROR: The reaction symbol \"" + reaction_symbol + "\" is not recognized.\n";
window.alert(error_string);
continue;
} // closes switch over the reaction_symbol
// ********************************
// Report analysis of this reaction
// ********************************
alert_string += reactants_string + "\n";
alert_string += products_string + "\n";
if (sum_reactants_molecular_weights == sum_products_molecular_weights) {
alert_string += "Mass is conserved in the reaction\n";
} else {
alert_string += "Mass is NOT conserved in the reaction\n";
}
alert_string += "\t" + reactants_Mw_string;
alert_string += "\t" + products_Mw_string;
alert_string += "\n";
reaction_is_balanced = true;
balanced_reaction_string = "";
for (isotope_index=1; isotope_index<max_num_isotopes; isotope_index++) {
if (product_num_atoms[isotope_index] != reactant_num_atoms[isotope_index]) {
reaction_is_balanced = false;
balanced_reaction_string += "\t Unbalanced " + isotope_name_array[isotope_index] + " atoms: Reactants " + reactant_num_atoms[isotope_index] + ", Products " + product_num_atoms[isotope_index] + "\n";
} else if (reactant_num_atoms[isotope_index]>0){
balanced_reaction_string += "\t Balanced " + isotope_name_array[isotope_index] + " atoms: Reactants " + reactant_num_atoms[isotope_index] + ", Products " + product_num_atoms[isotope_index] + "\n";
}
}
if (reaction_is_balanced == true) {
alert_string += "Reaction is balanced in all atoms:\n";
alert_string += balanced_reaction_string + "\n";
} else {
alert_string += "Reaction is UNBALANCED as follows:\n";
alert_string += balanced_reaction_string + "\n";
}
window.alert(alert_string);
} // closes loop over the chemical reactions
} // closes function analyzeChemicalReactions()
addOnloadHook(function () {
mw.util.addPortletLink('p-navigation', 'javascript:analyzeChemicalReactions()', 'Chemical reactions', 'ca-reactions', 'Analyze the chemical reactions on a page', '!', '');
});
//</pre>