adv / index.html
Mustafa7assan's picture
Add 2 files
33cf488 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChemCalc Pro | Advanced Chemical Calculator</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #3a7bd5;
--secondary: #00d2ff;
--dark: #1a1a2e;
--light: #f5f7fa;
--success: #28a745;
--danger: #dc3545;
--warning: #fd7e14;
--info: #17a2b8;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #f5f7fa 0%, #e4e6e9 100%);
min-height: 100vh;
color: var(--dark);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
text-align: center;
margin-bottom: 30px;
padding: 20px;
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
color: white;
border-radius: 10px;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 2.5rem;
margin-bottom: 10px;
}
h1 i {
margin-right: 15px;
}
.subtitle {
font-size: 1.1rem;
opacity: 0.9;
}
.tabs {
display: flex;
flex-wrap: wrap;
background: white;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
overflow: hidden;
}
.tab-button {
flex: 1;
padding: 15px 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 600;
border-bottom: 3px solid transparent;
}
.tab-button:hover {
background: rgba(0, 0, 0, 0.05);
}
.tab-button.active {
background: rgba(58, 123, 213, 0.1);
border-bottom: 3px solid var(--primary);
color: var(--primary);
}
.tab-content {
display: none;
padding: 30px;
background: white;
border-radius: 0 0 10px 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.tab-content.active {
display: block;
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.calculator-form {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #555;
}
input, select {
width: 100%;
padding: 12px 15px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 16px;
transition: border 0.3s ease;
}
input:focus, select:focus {
border-color: var(--primary);
outline: none;
box-shadow: 0 0 0 3px rgba(58, 123, 213, 0.2);
}
.btn {
display: inline-block;
padding: 12px 24px;
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
}
.btn-calculate {
grid-column: 1 / -1;
justify-self: center;
margin-top: 20px;
min-width: 200px;
}
.result-container {
margin-top: 30px;
padding: 20px;
background: rgba(58, 123, 213, 0.1);
border-radius: 8px;
border-left: 4px solid var(--primary);
display: none;
}
.result-container.show {
display: block;
animation: fadeIn 0.5s ease;
}
.result-title {
font-weight: 700;
margin-bottom: 10px;
color: var(--primary);
}
.result-value {
font-size: 1.2rem;
font-weight: 600;
}
.periodic-table {
margin-top: 30px;
}
.periodic-table h3 {
margin-bottom: 15px;
color: var(--primary);
}
.elements-grid {
display: grid;
grid-template-columns: repeat(18, 1fr);
gap: 5px;
margin-bottom: 30px;
}
.element {
padding: 10px 5px;
background: white;
border-radius: 4px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.element:hover {
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
z-index: 1;
}
.element-symbol {
font-weight: 700;
font-size: 0.9rem;
}
.element-number {
font-size: 0.6rem;
opacity: 0.7;
}
.nonmetal { background-color: #ade8af; }
.alkali { background-color: #ffb7b3; }
.alkaline { background-color: #ffdfba; }
.transition { background-color: #ffc8dd; }
.post-transition { background-color: #b8d0eb; }
.metalloid { background-color: #c2e0c6; }
.halogen { background-color: #caffbf; }
.noble { background-color: #cddafd; }
.lanthanide { background-color: #eac4d5; }
.actinide { background-color: #f1c0e8; }
.history-container {
margin-top: 30px;
max-height: 300px;
overflow-y: auto;
}
.history-item {
padding: 10px 15px;
margin-bottom: 10px;
background: white;
border-radius: 6px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
font-size: 0.9rem;
}
.history-item .time {
font-size: 0.8rem;
color: #777;
}
footer {
text-align: center;
margin-top: 50px;
padding: 20px;
color: #777;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.elements-grid {
grid-template-columns: repeat(9, 1fr);
}
.tab-button {
flex: 0 0 50%;
}
}
@media (max-width: 480px) {
.tab-button {
flex: 0 0 100%;
}
.elements-grid {
grid-template-columns: repeat(6, 1fr);
}
}
/* Special styling for specific calculator types */
.concentration-controls, .reaction-controls {
display: flex;
gap: 15px;
align-items: center;
}
.reaction-arrow {
font-size: 1.5rem;
color: #777;
padding: 0 10px;
}
.formula-display {
font-size: 1.2rem;
font-family: 'Courier New', monospace;
padding: 10px;
background: #f5f5f5;
border-radius: 4px;
margin: 15px 0;
word-break: break-all;
}
.advanced-options {
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid #eee;
}
.toggle-advanced {
background: none;
border: none;
color: var(--primary);
cursor: pointer;
font-weight: 600;
display: flex;
align-items: center;
margin-bottom: 10px;
}
.toggle-advanced i {
margin-right: 5px;
transition: transform 0.3s ease;
}
.toggle-advanced.collapsed i {
transform: rotate(-90deg);
}
</style>
</head>
<body>
<div class="container">
<header>
<h1><i class="fas fa-atom"></i> ChemCalc Pro</h1>
<p class="subtitle">Advanced Chemical Calculations for Professionals</p>
</header>
<div class="tabs">
<div class="tab-button active" data-tab="molar-mass"><i class="fas fa-weight-hanging"></i> Molar Mass</div>
<div class="tab-button" data-tab="concentration"><i class="fas fa-flask"></i> Concentration</div>
<div class="tab-button" data-tab="stoichiometry"><i class="fas fa-balance-scale"></i> Stoichiometry</div>
<div class="tab-button" data-tab="gas-laws"><i class="fas fa-wind"></i> Gas Laws</div>
<div class="tab-button" data-tab="thermochemistry"><i class="fas fa-temperature-high"></i> Thermochemistry</div>
<div class="tab-button" data-tab="redox"><i class="fas fa-bolt"></i> Redox</div>
</div>
<!-- Molar Mass Calculator -->
<div id="molar-mass" class="tab-content active">
<h2><i class="fas fa-weight-hanging"></i> Molar Mass Calculator</h2>
<p>Calculate the molar mass of any chemical compound by entering its formula.</p>
<div class="calculator-form">
<div class="form-group">
<label for="compound-formula">Chemical Formula</label>
<input type="text" id="compound-formula" placeholder="e.g. H2O, C6H12O6, Ca(OH)2">
</div>
<div class="form-group">
<label for="compound-mass">Mass (optional)</label>
<div class="concentration-controls">
<input type="number" id="compound-mass" placeholder="e.g. 5">
<select id="mass-unit">
<option value="g">g</option>
<option value="mg">mg</option>
<option value="kg">kg</option>
</select>
</div>
</div>
<button id="calculate-mass" class="btn btn-calculate">Calculate Molar Mass</button>
</div>
<div id="mass-result" class="result-container">
<div class="result-title">Results</div>
<div id="mass-value" class="result-value"></div>
<div id="moles-value" class="result-value" style="margin-top: 10px;"></div>
<div id="composition" style="margin-top: 15px;"></div>
</div>
<div class="periodic-table">
<h3>Periodic Table</h3>
<p>Click on elements to add them to the formula</p>
<div class="elements-grid" id="periodic-elements"></div>
</div>
</div>
<!-- Concentration Calculator -->
<div id="concentration" class="tab-content">
<h2><i class="fas fa-flask"></i> Concentration Calculator</h2>
<p>Calculate concentration, mass, volume, or dilution of solutions.</p>
<div class="calculator-form">
<div class="form-group">
<label>Calculation Type</label>
<select id="concentration-type" class="form-control">
<option value="conc-from-mass">Concentration from Mass</option>
<option value="mass-from-conc">Mass from Concentration</option>
<option value="dilution">Dilution</option>
<option value="mole-fraction">Mole Fraction</option>
</select>
</div>
<div id="conc-inputs">
<div class="form-group">
<label for="solute-formula">Solute Formula</label>
<input type="text" id="solute-formula" placeholder="e.g. NaCl">
</div>
<div class="form-group">
<label for="solute-mass">Mass of Solute</label>
<input type="number" id="solute-mass" placeholder="in grams">
</div>
<div class="form-group">
<label for="solution-volume">Solution Volume</label>
<div class="concentration-controls">
<input type="number" id="solution-volume" placeholder="e.g. 250">
<select id="vol-unit">
<option value="L">L</option>
<option value="mL">mL</option>
</select>
</div>
</div>
</div>
<div id="dilution-inputs" style="display: none;">
<div class="form-group">
<label for="initial-conc">Initial Concentration</label>
<div class="concentration-controls">
<input type="number" id="initial-conc">
<select id="initial-conc-unit">
<option value="M">M</option>
<option value="mM">mM</option>
</select>
</div>
</div>
<div class="form-group">
<label for="initial-vol">Initial Volume</label>
<div class="concentration-controls">
<input type="number" id="initial-vol">
<select id="initial-vol-unit">
<option value="L">L</option>
<option value="mL">mL</option>
</select>
</div>
</div>
</div>
<div id="conc-advanced" class="advanced-options" style="display: none;">
<div class="form-group">
<label for="solution-density">Solution Density (g/mL)</label>
<input type="number" id="solution-density" placeholder="Optional">
</div>
<div class="form-group">
<label for="solvent-mass">Solvent Mass (g)</label>
<input type="number" id="solvent-mass" placeholder="Optional">
</div>
<div class="form-group">
<label for="solution-temp">Temperature (°C)</label>
<input type="number" id="solution-temp" placeholder="25">
</div>
</div>
<button type="button" class="toggle-advanced" id="toggle-conc-advanced">
<i class="fas fa-chevron-down"></i> Advanced Options
</button>
<button id="calculate-conc" class="btn btn-calculate">Calculate</button>
</div>
<div id="conc-result" class="result-container">
<div class="result-title">Results</div>
<div id="conc-value" class="result-value"></div>
<div id="conc-details" style="margin-top: 15px;"></div>
</div>
</div>
<!-- Stoichiometry Calculator -->
<div id="stoichiometry" class="tab-content">
<h2><i class="fas fa-balance-scale"></i> Stoichiometry Calculator</h2>
<p>Balance chemical equations and perform stoichiometric calculations.</p>
<div class="calculator-form">
<div class="form-group">
<label>Reaction Type</label>
<select id="reaction-type" class="form-control">
<option value="balance">Balance Equation</option>
<option value="limiting-reactant">Limiting Reactant</option>
<option value="product-yield">Product Yield</option>
</select>
</div>
<div id="reaction-inputs">
<div class="form-group balanced-equation">
<label>Enter Chemical Equation</label>
<div class="formula-display" id="equation-display"></div>
<div class="reaction-controls">
<input type="text" id="reactant1" placeholder="Reactant 1 (e.g. H2)">
<div class="reaction-arrow">+</div>
<input type="text" id="reactant2" placeholder="Reactant 2 (e.g. O2)">
<div class="reaction-arrow">
<select id="reaction-direction">
<option value="→"></option>
<option value="↔"></option>
</select>
</div>
<input type="text" id="product1" placeholder="Product 1 (e.g. H2O)">
<div class="reaction-arrow">+</div>
<input type="text" id="product2" placeholder="Product 2 (optional)">
</div>
</div>
<div id="stoich-inputs" style="display: none;">
<div class="form-group">
<label for="given-quantity">Given Quantity</label>
<input type="number" id="given-quantity" placeholder="Amount">
</div>
<div class="form-group">
<label for="given-compound">Given Compound</label>
<input type="text" id="given-compound" placeholder="Formula">
</div>
<div class="form-group">
<label for="desired-compound">Desired Compound</label>
<input type="text" id="desired-compound" placeholder="Formula">
</div>
</div>
</div>
<button id="balance-reaction" class="btn btn-calculate">Balance Equation</button>
<div id="stoich-result" class="result-container">
<div class="result-title">Results</div>
<div id="balanced-equation" class="result-value"></div>
<div id="stoich-details" style="margin-top: 15px;"></div>
</div>
</div>
</div>
<!-- Gas Laws Calculator -->
<div id="gas-laws" class="tab-content">
<h2><i class="fas fa-wind"></i> Gas Laws Calculator</h2>
<p>Perform calculations using the ideal gas law and other gas equations.</p>
<div class="calculator-form">
<div class="form-group">
<label>Gas Law</label>
<select id="gas-law" class="form-control">
<option value="ideal-gas">Ideal Gas Law (PV=nRT)</option>
<option value="boyles">Boyle's Law (P₁V₁=P₂V₂)</option>
<option value="charles">Charles's Law (V₁/T₁=V₂/T₂)</option>
<option value="gay-lussac">Gay-Lussac's Law (P₁/T₁=P₂/T₂)</option>
<option value="combined">Combined Gas Law (P₁V₁/T₁=P₂V₂/T₂)</option>
<option value="density">Gas Density (d=PM/RT)</option>
</select>
</div>
<div id="ideal-gas-inputs">
<div class="form-group">
<label for="gas-pressure">Pressure (P)</label>
<div class="concentration-controls">
<input type="number" id="gas-pressure" placeholder="e.g. 1">
<select id="pressure-unit">
<option value="atm">atm</option>
<option value="mmHg">mmHg</option>
<option value="kPa">kPa</option>
<option value="bar">bar</option>
</select>
</div>
</div>
<div class="form-group">
<label for="gas-volume">Volume (V)</label>
<div class="concentration-controls">
<input type="number" id="gas-volume" placeholder="e.g. 22.4">
<select id="volume-unit">
<option value="L">L</option>
<option value="mL">mL</option>
</select>
</div>
</div>
<div class="form-group">
<label for="gas-moles">Moles (n)</label>
<input type="number" id="gas-moles" placeholder="e.g. 1">
</div>
<div class="form-group">
<label for="gas-temp">Temperature (T)</label>
<div class="concentration-controls">
<input type="number" id="gas-temp" placeholder="e.g. 273">
<select id="temp-unit">
<option value="K">K</option>
<option value="°C">°C</option>
</select>
</div>
</div>
</div>
<button id="calculate-gas" class="btn btn-calculate">Calculate</button>
<div id="gas-result" class="result-container">
<div class="result-title">Results</div>
<div id="gas-value" class="result-value"></div>
<div id="gas-details" style="margin-top: 15px;"></div>
</div>
</div>
</div>
<!-- Thermochemistry Calculator -->
<div id="thermochemistry" class="tab-content">
<h2><i class="fas fa-temperature-high"></i> Thermochemistry Calculator</h2>
<p>Calculate enthalpy, heat transfer, and other thermochemical properties.</p>
<div class="calculator-form">
<div class="form-group">
<label>Calculation Type</label>
<select id="thermo-type" class="form-control">
<option value="enthalpy">Enthalpy Change</option>
<option value="heat">Heat Transfer (q=mcΔT)</option>
<option value="hess">Hess's Law</option>
<option value="calorimetry">Calorimetry</option>
</select>
</div>
<!-- Enthalpy inputs -->
<div id="enthalpy-inputs">
<div class="form-group">
<label for="reaction-enthalpy">Reaction Enthalpy (ΔH°)</label>
<div class="concentration-controls">
<input type="number" id="reaction-enthalpy" placeholder="kJ/mol">
</div>
</div>
<div class="form-group">
<label for="moles-reacted">Moles Reacted</label>
<input type="number" id="moles-reacted" placeholder="mol">
</div>
</div>
<!-- Heat inputs -->
<div id="heat-inputs" style="display: none;">
<div class="form-group">
<label for="thermo-mass">Mass</label>
<div class="concentration-controls">
<input type="number" id="thermo-mass" placeholder="g">
</div>
</div>
<div class="form-group">
<label for="specific-heat">Specific Heat Capacity (c)</label>
<div class="concentration-controls">
<input type="number" id="specific-heat" placeholder="J/g°C (4.18 for water)">
</div>
</div>
<div class="form-group">
<label for="temp-change">Temperature Change (ΔT)</label>
<div class="concentration-controls">
<input type="number" id="temp-change" placeholder="°C">
</div>
</div>
</div>
<button id="calculate-thermo" class="btn btn-calculate">Calculate</button>
<div id="thermo-result" class="result-container">
<div class="result-title">Results</div>
<div id="thermo-value" class="result-value"></div>
<div id="thermo-details" style="margin-top: 15px;"></div>
</div>
</div>
</div>
<!-- Redox Calculator -->
<div id="redox" class="tab-content">
<h2><i class="fas fa-bolt"></i> Redox Reaction Calculator</h2>
<p>Balance redox reactions and calculate electrochemical properties.</p>
<div class="calculator-form">
<div class="form-group">
<label>Calculation Type</label>
<select id="redox-type" class="form-control">
<option value="balance-redox">Balance Redox Reaction</option>
<option value="cell-potential">Cell Potential</option>
<option value="nernst">Nernst Equation</option>
</select>
</div>
<div id="redox-reaction-inputs">
<div class="form-group">
<label>Redox Reaction (Half-Reactions)</label>
<div class="reaction-controls">
<input type="text" id="redox-reactant1" placeholder="Oxidation (e.g. Fe → Fe²⁺)">
<div class="reaction-arrow">+</div>
<input type="text" id="redox-reactant2" placeholder="Reduction (e.g. O2 + 4e⁻ → 2O²⁻)">
</div>
</div>
</div>
<div id="redox-advanced" class="advanced-options" style="display: none;">
<div class="form-group">
<label for="redox-medium">Medium</label>
<select id="redox-medium">
<option value="acidic">Acidic</option>
<option value="basic">Basic</option>
<option value="neutral">Neutral</option>
</select>
</div>
<div class="form-group">
<label for="redox-temp">Temperature (°C)</label>
<input type="number" id="redox-temp" value="25">
</div>
</div>
<button type="button" class="toggle-advanced" id="toggle-redox-advanced">
<i class="fas fa-chevron-down"></i> Advanced Options
</button>
<button id="calculate-redox" class="btn btn-calculate">Balance Reaction</button>
<div id="redox-result" class="result-container">
<div class="result-title">Results</div>
<div id="redox-value" class="result-value"></div>
<div id="redox-details" style="margin-top: 15px;"></div>
</div>
</div>
</div>
<div class="history-container">
<h3>Calculation History</h3>
<div id="history-list"></div>
</div>
<footer>
<p>ChemCalc Pro &copy; 2023 | Advanced Chemical Calculator for Professionals</p>
<p>Disclaimer: Results should be verified with experimental data.</p>
</footer>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Tab functionality
const tabButtons = document.querySelectorAll('.tab-button');
const tabContents = document.querySelectorAll('.tab-content');
tabButtons.forEach(button => {
button.addEventListener('click', () => {
const tabId = button.getAttribute('data-tab');
// Update active tab button
tabButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
// Show corresponding content
tabContents.forEach(content => {
content.classList.remove('active');
if(content.id === tabId) {
content.classList.add('active');
}
});
});
});
// Advanced options toggle
const toggleConcAdvanced = document.getElementById('toggle-conc-advanced');
const concAdvanced = document.getElementById('conc-advanced');
toggleConcAdvanced.addEventListener('click', () => {
concAdvanced.style.display = concAdvanced.style.display === 'none' ? 'block' : 'none';
toggleConcAdvanced.classList.toggle('collapsed');
});
const toggleRedoxAdvanced = document.getElementById('toggle-redox-advanced');
const redoxAdvanced = document.getElementById('redox-advanced');
toggleRedoxAdvanced.addEventListener('click', () => {
redoxAdvanced.style.display = redoxAdvanced.style.display === 'none' ? 'block' : 'none';
toggleRedoxAdvanced.classList.toggle('collapsed');
});
// Periodic table elements
const periodicElements = document.getElementById('periodic-elements');
const compoundFormula = document.getElementById('compound-formula');
const elements = [
{ symbol: 'H', name: 'Hydrogen', number: 1, group: 'nonmetal' },
{ symbol: 'He', name: 'Helium', number: 2, group: 'noble' },
{ symbol: 'Li', name: 'Lithium', number: 3, group: 'alkali' },
{ symbol: 'Be', name: 'Beryllium', number: 4, group: 'alkaline' },
{ symbol: 'B', name: 'Boron', number: 5, group: 'metalloid' },
{ symbol: 'C', name: 'Carbon', number: 6, group: 'nonmetal' },
{ symbol: 'N', name: 'Nitrogen', number: 7, group: 'nonmetal' },
{ symbol: 'O', name: 'Oxygen', number: 8, group: 'nonmetal' },
{ symbol: 'F', name: 'Fluorine', number: 9, group: 'halogen' },
{ symbol: 'Ne', name: 'Neon', number: 10, group: 'noble' },
{ symbol: 'Na', name: 'Sodium', number: 11, group: 'alkali' },
{ symbol: 'Mg', name: 'Magnesium', number: 12, group: 'alkaline' },
{ symbol: 'Al', name: 'Aluminum', number: 13, group: 'post-transition' },
{ symbol: 'Si', name: 'Silicon', number: 14, group: 'metalloid' },
{ symbol: 'P', name: 'Phosphorus', number: 15, group: 'nonmetal' },
{ symbol: 'S', name: 'Sulfur', number: 16, group: 'nonmetal' },
{ symbol: 'Cl', name: 'Chlorine', number: 17, group: 'halogen' },
{ symbol: 'Ar', name: 'Argon', number: 18, group: 'noble' },
{ symbol: 'K', name: 'Potassium', number: 19, group: 'alkali' },
{ symbol: 'Ca', name: 'Calcium', number: 20, group: 'alkaline' },
{ symbol: 'Sc', name: 'Scandium', number: 21, group: 'transition' },
{ symbol: 'Ti', name: 'Titanium', number: 22, group: 'transition' },
{ symbol: 'V', name: 'Vanadium', number: 23, group: 'transition' },
{ symbol: 'Cr', name: 'Chromium', number: 24, group: 'transition' },
{ symbol: 'Mn', name: 'Manganese', number: 25, group: 'transition' },
{ symbol: 'Fe', name: 'Iron', number: 26, group: 'transition' },
{ symbol: 'Co', name: 'Cobalt', number: 27, group: 'transition' },
{ symbol: 'Ni', name: 'Nickel', number: 28, group: 'transition' },
{ symbol: 'Cu', name: 'Copper', number: 29, group: 'transition' },
{ symbol: 'Zn', name: 'Zinc', number: 30, group: 'transition' },
{ symbol: 'Ga', name: 'Gallium', number: 31, group: 'post-transition' },
{ symbol: 'Ge', name: 'Germanium', number: 32, group: 'metalloid' },
{ symbol: 'As', name: 'Arsenic', number: 33, group: 'metalloid' },
{ symbol: 'Se', name: 'Selenium', number: 34, group: 'nonmetal' },
{ symbol: 'Br', name: 'Bromine', number: 35, group: 'halogen' },
{ symbol: 'Kr', name: 'Krypton', number: 36, group: 'noble' },
{ symbol: 'Rb', name: 'Rubidium', number: 37, group: 'alkali' },
{ symbol: 'Sr', name: 'Strontium', number: 38, group: 'alkaline' },
{ symbol: 'Y', name: 'Yttrium', number: 39, group: 'transition' },
{ symbol: 'Zr', name: 'Zirconium', number: 40, group: 'transition' },
{ symbol: 'Nb', name: 'Niobium', number: 41, group: 'transition' },
{ symbol: 'Mo', name: 'Molybdenum', number: 42, group: 'transition' },
{ symbol: 'Tc', name: 'Technetium', number: 43, group: 'transition' },
{ symbol: 'Ru', name: 'Ruthenium', number: 44, group: 'transition' },
{ symbol: 'Rh', name: 'Rhodium', number: 45, group: 'transition' },
{ symbol: 'Pd', name: 'Palladium', number: 46, group: 'transition' },
{ symbol: 'Ag', name: 'Silver', number: 47, group: 'transition' },
{ symbol: 'Cd', name: 'Cadmium', number: 48, group: 'transition' },
{ symbol: 'In', name: 'Indium', number: 49, group: 'post-transition' },
{ symbol: 'Sn', name: 'Tin', number: 50, group: 'post-transition' },
{ symbol: 'Sb', name: 'Antimony', number: 51, group: 'metalloid' },
{ symbol: 'Te', name: 'Tellurium', number: 52, group: 'metalloid' },
{ symbol: 'I', name: 'Iodine', number: 53, group: 'halogen' },
{ symbol: 'Xe', name: 'Xenon', number: 54, group: 'noble' },
{ symbol: 'Cs', name: 'Cesium', number: 55, group: 'alkali' },
{ symbol: 'Ba', name: 'Barium', number: 56, group: 'alkaline' },
{ symbol: 'La', name: 'Lanthanum', number: 57, group: 'lanthanide' },
{ symbol: 'Ce', name: 'Cerium', number: 58, group: 'lanthanide' },
{ symbol: 'Pr', name: 'Praseodymium', number: 59, group: 'lanthanide' },
{ symbol: 'Nd', name: 'Neodymium', number: 60, group: 'lanthanide' },
{ symbol: 'Pm', name: 'Promethium', number: 61, group: 'lanthanide' },
{ symbol: 'Sm', name: 'Samarium', number: 62, group: 'lanthanide' },
{ symbol: 'Eu', name: 'Europium', number: 63, group: 'lanthanide' },
{ symbol: 'Gd', name: 'Gadolinium', number: 64, group: 'lanthanide' },
{ symbol: 'Tb', name: 'Terbium', number: 65, group: 'lanthanide' },
{ symbol: 'Dy', name: 'Dysprosium', number: 66, group: 'lanthanide' },
{ symbol: 'Ho', name: 'Holmium', number: 67, group: 'lanthanide' },
{ symbol: 'Er', name: 'Erbium', number: 68, group: 'lanthanide' },
{ symbol: 'Tm', name: 'Thulium', number: 69, group: 'lanthanide' },
{ symbol: 'Yb', name: 'Ytterbium', number: 70, group: 'lanthanide' },
{ symbol: 'Lu', name: 'Lutetium', number: 71, group: 'lanthanide' },
{ symbol: 'Hf', name: 'Hafnium', number: 72, group: 'transition' },
{ symbol: 'Ta', name: 'Tantalum', number: 73, group: 'transition' },
{ symbol: 'W', name: 'Tungsten', number: 74, group: 'transition' },
{ symbol: 'Re', name: 'Rhenium', number: 75, group: 'transition' },
{ symbol: 'Os', name: 'Osmium', number: 76, group: 'transition' },
{ symbol: 'Ir', name: 'Iridium', number: 77, group: 'transition' },
{ symbol: 'Pt', name: 'Platinum', number: 78, group: 'transition' },
{ symbol: 'Au', name: 'Gold', number: 79, group: 'transition' },
{ symbol: 'Hg', name: 'Mercury', number: 80, group: 'transition' },
{ symbol: 'Tl', name: 'Thallium', number: 81, group: 'post-transition' },
{ symbol: 'Pb', name: 'Lead', number: 82, group: 'post-transition' },
{ symbol: 'Bi', name: 'Bismuth', number: 83, group: 'post-transition' },
{ symbol: 'Po', name: 'Polonium', number: 84, group: 'metalloid' },
{ symbol: 'At', name: 'Astatine', number: 85, group: 'halogen' },
{ symbol: 'Rn', name: 'Radon', number: 86, group: 'noble' },
{ symbol: 'Fr', name: 'Francium', number: 87, group: 'alkali' },
{ symbol: 'Ra', name: 'Radium', number: 88, group: 'alkaline' },
{ symbol: 'Ac', name: 'Actinium', number: 89, group: 'actinide' },
{ symbol: 'Th', name: 'Thorium', number: 90, group: 'actinide' },
{ symbol: 'Pa', name: 'Protactinium', number: 91, group: 'actinide' },
{ symbol: 'U', name: 'Uranium', number: 92, group: 'actinide' },
{ symbol: 'Np', name: 'Neptunium', number: 93, group: 'actinide' },
{ symbol: 'Pu', name: 'Plutonium', number: 94, group: 'actinide' },
// ... more elements if needed
];
// Create periodic table
elements.forEach(element => {
const elementDiv = document.createElement('div');
elementDiv.className = `element ${element.group}`;
elementDiv.innerHTML = `
<div class="element-symbol">${element.symbol}</div>
<div class="element-number">${element.number}</div>
`;
elementDiv.title = element.name;
elementDiv.addEventListener('click', () => {
if (compoundFormula) {
compoundFormula.value += element.symbol;
compoundFormula.focus();
}
});
periodicElements.appendChild(elementDiv);
});
// Molar mass calculation
const molarMasses = {
'H': 1.008, 'He': 4.0026, 'Li': 6.94, 'Be': 9.0122, 'B': 10.81,
'C': 12.011, 'N': 14.007, 'O': 15.999, 'F': 18.998, 'Ne': 20.180,
'Na': 22.990, 'Mg': 24.305, 'Al': 26.982, 'Si': 28.085, 'P': 30.974,
'S': 32.06, 'Cl': 35.45, 'Ar': 39.948, 'K': 39.098, 'Ca': 40.078,
'Sc': 44.956, 'Ti': 47.867, 'V': 50.942, 'Cr': 51.996, 'Mn': 54.938,
'Fe': 55.845, 'Co': 58.933, 'Ni': 58.693, 'Cu': 63.546, 'Zn': 65.38,
'Ga': 69.723, 'Ge': 72.630, 'As': 74.922, 'Se': 78.971, 'Br': 79.904,
'Kr': 83.798, 'Rb': 85.468, 'Sr': 87.62, 'Y': 88.906, 'Zr': 91.224,
'Nb': 92.906, 'Mo': 95.95, 'Tc': 98, 'Ru': 101.07, 'Rh': 102.91,
'Pd': 106.42, 'Ag': 107.87, 'Cd': 112.41, 'In': 114.82, 'Sn': 118.71,
'Sb': 121.76, 'Te': 127.60, 'I': 126.90, 'Xe': 131.29, 'Cs': 132.91,
'Ba': 137.33, 'La': 138.91, 'Ce': 140.12, 'Pr': 140.91, 'Nd': 144.24,
'Pm': 145, 'Sm': 150.36, 'Eu': 151.96, 'Gd': 157.25, 'Tb': 158.93,
'Dy': 162.50, 'Ho': 164.93, 'Er': 167.26, 'Tm': 168.93, 'Yb': 173.05,
'Lu': 174.97, 'Hf': 178.49, 'Ta': 180.95, 'W': 183.84, 'Re': 186.21,
'Os': 190.23, 'Ir': 192.22, 'Pt': 195.08, 'Au': 196.97, 'Hg': 200.59,
'Tl': 204.38, 'Pb': 207.2, 'Bi': 208.98, 'Po': 209, 'At': 210, 'Rn': 222,
'Fr': 223, 'Ra': 226, 'Ac': 227, 'Th': 232.04, 'Pa': 231.04, 'U': 238.03,
'Np': 237, 'Pu': 244
};
document.getElementById('calculate-mass').addEventListener('click', calculateMolarMass);
function calculateMolarMass() {
const formula = document.getElementById('compound-formula').value.trim();
const massStr = document.getElementById('compound-mass').value;
const massUnit = document.getElementById('mass-unit').value;
if (!formula) {
alert('Please enter a chemical formula');
return;
}
try {
// Parse the chemical formula
const parsedFormula = parseFormula(formula);
let totalMass = 0;
let compositionHTML = '<div>Elemental Composition:</div><ul>';
// Calculate molar mass
for (const element in parsedFormula) {
const count = parsedFormula[element];
const elementMass = molarMasses[element] || 0;
totalMass += elementMass * count;
// Add to composition list
const elementObj = elements.find(e => e.symbol === element);
const percent = ((elementMass * count) / totalMass * 100).toFixed(2);
compositionHTML += `<li>${element} (${elementObj?.name || 'Unknown'}): ${count} atom${count > 1 ? 's' : ''} (${percent}%)</li>`;
}
compositionHTML += '</ul>';
// Display results
const resultDiv = document.getElementById('mass-result');
document.getElementById('mass-value').textContent = `Molar Mass: ${totalMass.toFixed(4)} g/mol`;
// Calculate moles if mass was provided
if (massStr) {
const mass = parseFloat(massStr);
let convertedMass = mass;
// Convert units if needed
switch(massUnit) {
case 'mg': convertedMass = mass / 1000; break;
case 'kg': convertedMass = mass * 1000; break;
}
const moles = convertedMass / totalMass;
document.getElementById('moles-value').textContent = `Moles: ${moles.toFixed(6)} mol`;
} else {
document.getElementById('moles-value').textContent = '';
}
document.getElementById('composition').innerHTML = compositionHTML;
resultDiv.classList.add('show');
// Add to history
addToHistory(`Calculated molar mass for ${formula}: ${totalMass.toFixed(4)} g/mol`);
} catch (error) {
alert('Error parsing formula: ' + error.message);
}
}
// Helper function to parse chemical formulas
function parseFormula(formula) {
const elements = {};
let currentElement = '';
let currentCount = 0;
let i = 0;
while (i < formula.length) {
const c = formula[i];
// Check for uppercase letter (new element)
if (c === c.toUpperCase() && c !== c.toLowerCase()) {
// If we have a current element, add it to the result
if (currentElement) {
elements[currentElement] = (elements[currentElement] || 0) + (currentCount || 1);
}
// Start new element
currentElement = c;
i++;
// Check for lowercase letters (element symbol with 2 letters)
while (i < formula.length && formula[i] === formula[i].toLowerCase() && formula[i] !== formula[i].toUpperCase()) {
currentElement += formula[i];
i++;
}
currentCount = 0;
}
// Check for digits (count of atoms)
else if (c >= '0' && c <= '9') {
currentCount = currentCount * 10 + parseInt(c);
i++;
}
// Check for parentheses (grouping)
else if (c === '(') {
// If we have a current element, add it to the result
if (currentElement) {
elements[currentElement] = (elements[currentElement] || 0) + (currentCount || 1);
}
// Parse the group inside parentheses
const groupEnd = findMatchingClosingParenthesis(formula, i);
const groupContent = formula.substring(i + 1, groupEnd);
const parsedGroup = parseFormula(groupContent);
// Parse the count after the group
let groupCount = 0;
let j = groupEnd + 1;
while (j < formula.length && formula[j] >= '0' && formula[j] <= '9') {
groupCount = groupCount * 10 + parseInt(formula[j]);
j++;
}
groupCount = groupCount || 1;
// Add all elements from the group to the result
for (const element in parsedGroup) {
elements[element] = (elements[element] || 0) + parsedGroup[element] * groupCount;
}
i = j;
currentElement = '';
currentCount = 0;
}
else {
throw new Error(`Invalid character in formula: ${c}`);
}
}
// Add the last element if it exists
if (currentElement) {
elements[currentElement] = (elements[currentElement] || 0) + (currentCount || 1);
}
return elements;
}
function findMatchingClosingParenthesis(str, pos) {
let depth = 1;
for (let i = pos + 1; i < str.length; i++) {
if (str[i] === '(') depth++;
else if (str[i] === ')') depth--;
if (depth === 0) return i;
}
throw new Error('No matching closing parenthesis found');
}
// Concentration calculator
const concTypeSelect = document.getElementById('concentration-type');
concTypeSelect.addEventListener('change', updateConcInputs);
function updateConcInputs() {
const type = concTypeSelect.value;
const concInputs = document.getElementById('conc-inputs');
const dilutionInputs = document.getElementById('dilution-inputs');
if (type === 'dilution') {
concInputs.style.display = 'none';
dilutionInputs.style.display = 'block';
} else {
concInputs.style.display = 'block';
dilutionInputs.style.display = 'none';
}
}
document.getElementById('calculate-conc').addEventListener('click', calculateConcentration);
function calculateConcentration() {
const type = concTypeSelect.value;
const resultDiv = document.getElementById('conc-result');
try {
if (type === 'dilution') {
const initialConc = parseFloat(document.getElementById('initial-conc').value);
const initialConcUnit = document.getElementById('initial-conc-unit').value;
const initialVol = parseFloat(document.getElementById('initial-vol').value);
const initialVolUnit = document.getElementById('initial-vol-unit').value;
if (!initialConc || !initialVol) {
alert('Please enter both initial concentration and volume');
return;
}
// Convert units if needed
let conc = initialConc;
if (initialConcUnit === 'mM') conc = conc / 1000;
let vol = initialVol;
if (initialVolUnit === 'mL') vol = vol / 1000;
// Calculate dilution (M1V1 = M2V2) assuming final volume is known
// For simplicity, we'll calculate final concentration based on assuming final volume is known from dilution
// In a real app, you'd want more detailed inputs
const finalConc = (conc * vol) / (vol + vol); // Assuming doubling volume
document.getElementById('conc-value').innerHTML = `
<div>Initial Concentration: ${initialConc} ${initialConcUnit}</div>
<div>Final Concentration: ${finalConc.toFixed(6)} M</div
</html>