User:Proteins/chemicalreactions.js

// // 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_index0){ 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', '!', ''); });

//