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

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

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

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

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

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

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

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

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

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', '!', '');

});

//