User:Proteins/chemicalreactions.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/chemicalreactions. |
//<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>