Construction Calculator

 <!DOCTYPE html>

<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CONSTRUX-9000 | Ultimate Jobsite Calc</title> <style> :root { --primary: #1a2b3c; --secondary: #2c4d6e; --accent: #00ffaa; --accent-alt: #ff5588; --text: #e0e0e0; --panel: #0d1824; --warning: #ff5555; --display: #001a00; --success: #00cc77; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Courier New', monospace; background-color: #0a1018; color: var(--text); margin: 0; padding: 20px; display: flex; flex-direction: column; align-items: center; background-image: linear-gradient(rgba(0, 255, 170, 0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(0, 255, 170, 0.03) 1px, transparent 1px); background-size: 20px 20px; min-height: 100vh; } .calculator { width: 100%; max-width: 400px; border: 1px solid var(--secondary); border-radius: 8px; overflow: hidden; box-shadow: 0 0 20px rgba(0, 255, 170, 0.2); background-color: var(--primary); margin-bottom: 20px; position: relative; } .title-bar { background-color: var(--secondary); color: var(--accent); padding: 8px 15px; font-size: 1.2rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--accent); } .title-bar span { font-weight: bold; text-shadow: 0 0 5px rgba(0, 255, 170, 0.5); } .title-bar small { font-size: 0.7rem; opacity: 0.8; } .display { background-color: var(--display); padding: 20px; text-align: right; border-bottom: 1px solid var(--secondary); position: relative; overflow: hidden; } .display::after { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px; background: linear-gradient(90deg, transparent, var(--accent), transparent); animation: scanline 12s linear infinite; } @keyframes scanline { 0% { top: 0; } 100% { top: 100%; } } .display-main { font-size: 2.5rem; margin-bottom: 5px; color: var(--accent); text-shadow: 0 0 5px rgba(0, 255, 170, 0.5); min-height: 60px; word-wrap: break-word; word-break: break-all; } .display-secondary { font-size: 1rem; color: var(--text); opacity: 0.7; min-height: 20px; } .memory-indicator { position: absolute; top: 5px; left: 10px; font-size: 0.8rem; color: var(--accent-alt); } .mode-selector { display: flex; background-color: var(--panel); border-bottom: 1px solid var(--secondary); } .mode-btn { flex: 1; padding: 10px; text-align: center; border-right: 1px solid var(--secondary); font-size: 0.9rem; cursor: pointer; transition: all 0.2s; } .mode-btn:hover { background-color: rgba(0, 255, 170, 0.1); } .mode-btn.active { background-color: var(--secondary); color: var(--accent); } .mode-btn:last-child { border-right: none; } .keypad { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background-color: var(--secondary); } button { border: none; padding: 15px 10px; font-size: 1.2rem; background-color: var(--panel); color: var(--text); cursor: pointer; font-family: 'Courier New', monospace; transition: all 0.2s; position: relative; overflow: hidden; } button:hover { background-color: var(--secondary); color: var(--accent); } button:active { background-color: var(--accent); color: var(--primary); transform: scale(0.98); } /* Button ripple effect */ button::after { content: ''; position: absolute; top: 50%; left: 50%; width: 5px; height: 5px; background: rgba(0, 255, 170, 0.4); opacity: 0; border-radius: 100%; transform: scale(1, 1) translate(-50%, -50%); transform-origin: 50% 50%; } button:focus:not(:active)::after { animation: ripple 1s ease-out; } @keyframes ripple { 0% { transform: scale(0, 0) translate(-50%, -50%); opacity: 0.5; } 100% { transform: scale(20, 20) translate(-50%, -50%); opacity: 0; } } .function { background-color: #142838; } .operator { background-color: #1c3a4e; color: var(--accent); } .equals { background-color: var(--accent); color: var(--primary); } .memory-btn { background-color: #2a1f3d; color: var(--accent-alt); } .panel { display: none; background-color: var(--panel); } .panel.active { display: block; } .tabs { display: flex; border-bottom: 1px solid var(--secondary); overflow-x: auto; } .tab { padding: 10px 15px; cursor: pointer; border-bottom: 2px solid transparent; white-space: nowrap; } .tab.active { border-bottom: 2px solid var(--accent); color: var(--accent); } .tab-content { display: none; padding: 15px; } .tab-content.active { display: block; } .material-input { margin-bottom: 10px; } .material-input label { display: block; margin-bottom: 5px; font-size: 0.9rem; } .material-input input, .material-input select { width: 100%; padding: 8px; background-color: #1a2b3c; border: 1px solid var(--secondary); color: var(--text); border-radius: 4px; font-family: 'Courier New', monospace; } .material-input input:focus, .material-input select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px rgba(0, 255, 170, 0.2); } .material-result { margin-top: 15px; padding: 10px; background-color: var(--display); border-radius: 4px; border-left: 3px solid var(--accent); } .warning { color: var(--warning); } .success { color: var(--success); } .conversion-options { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; margin-bottom: 10px; } .conversion-btn { padding: 8px; font-size: 0.9rem; } .stair-formula { font-size: 0.8rem; opacity: 0.7; margin-top: 5px; margin-bottom: 10px; } /* History feature */ .history-panel { display: none; background-color: var(--panel); border-top: 1px solid var(--secondary); max-height: 200px; overflow-y: auto; } .history-panel.active { display: block; } .history-item { padding: 8px 15px; border-bottom: 1px solid rgba(0, 255, 170, 0.1); font-size: 0.9rem; cursor: pointer; } .history-item:hover { background-color: rgba(0, 255, 170, 0.05); } .history-result { color: var(--accent); float: right; } .history-empty { text-align: center; padding: 20px; color: var(--text); opacity: 0.5; } .toggle-history { position: absolute; bottom: 0; right: 0; font-size: 0.8rem; padding: 5px 10px; background-color: var(--panel); border-top-left-radius: 5px; border-top: 1px solid var(--secondary); border-left: 1px solid var(--secondary); cursor: pointer; transition: all 0.2s; z-index: 10; } .toggle-history:hover { background-color: var(--secondary); } /* Toast notification */ .toast { position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); background-color: var(--panel); color: var(--success); padding: 10px 20px; border-radius: 4px; border-left: 4px solid var(--success); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); z-index: 100; opacity: 0; transition: opacity 0.3s; } .toast.show { opacity: 1; } .toast.error { color: var(--warning); border-left-color: var(--warning); } /* Quick tool selector */ .quick-tools { display: flex; flex-wrap: wrap; gap: 5px; padding: 10px; background-color: #0d1420; border-top: 1px solid var(--secondary); } .quick-tool { padding: 5px 10px; font-size: 0.8rem; background-color: #1c3a4e; border-radius: 15px; cursor: pointer; transition: all 0.2s; } .quick-tool:hover { background-color: var(--secondary); color: var(--accent); } #version-info { position: absolute; bottom: 10px; right: 10px; font-size: 0.8rem; opacity: 0.5; } /* Footer with calculator info */ .footer { width: 100%; max-width: 600px; text-align: center; margin-top: 20px; margin-bottom: 40px; font-size: 0.9rem; color: var(--text); opacity: 0.7; } .footer a { color: var(--accent); text-decoration: none; } .footer a:hover { text-decoration: underline; } /* Save button for calculations */ .save-btn { position: absolute; top: 5px; right: 5px; font-size: 1rem; color: var(--accent); background: none; border: none; cursor: pointer; padding: 5px; z-index: 5; } .save-btn:hover { color: var(--text); } @media (max-width: 480px) { .conversion-options { grid-template-columns: repeat(2, 1fr); } .display-main { font-size: 2rem; } button { padding: 12px 8px; } .title-bar { font-size: 1rem; padding: 6px 10px; } } </style> </head> <body> <div class="calculator"> <div class="title-bar"> <span>CONSTRUX-9000</span> <small>PRO EDITION</small> </div> <div class="display"> <div class="memory-indicator" id="memory-indicator"></div> <div class="display-secondary" id="secondary-display"></div> <div class="display-main" id="main-display">0</div> <button class="save-btn" id="save-result" title="Save Result">💾</button> </div> <div class="mode-selector"> <div class="mode-btn active" data-mode="basic">BASIC</div> <div class="mode-btn" data-mode="conversion">CONVERT</div> <div class="mode-btn" data-mode="materials">MATERIALS</div> <div class="mode-btn" data-mode="geometry">GEOMETRY</div> </div> <!-- Basic Calculator --> <div class="panel active" id="basic-panel"> <div class="keypad"> <button class="memory-btn" onclick="memoryClear()">MC</button> <button class="memory-btn" onclick="memoryRecall()">MR</button> <button class="memory-btn" onclick="memoryAdd()">M+</button> <button class="memory-btn" onclick="memorySubtract()">M-</button> <button class="function" onclick="clearAll()">C</button> <button class="function" onclick="backspace()"></button> <button class="function" onclick="percentage()">%</button> <button class="operator" onclick="appendOperator('/')">÷</button> <button onclick="appendNumber('7')">7</button> <button onclick="appendNumber('8')">8</button> <button onclick="appendNumber('9')">9</button> <button class="operator" onclick="appendOperator('*')">×</button> <button onclick="appendNumber('4')">4</button> <button onclick="appendNumber('5')">5</button> <button onclick="appendNumber('6')">6</button> <button class="operator" onclick="appendOperator('-')">-</button> <button onclick="appendNumber('1')">1</button> <button onclick="appendNumber('2')">2</button> <button onclick="appendNumber('3')">3</button> <button class="operator" onclick="appendOperator('+')">+</button> <button onclick="toggleSign()">±</button> <button onclick="appendNumber('0')">0</button> <button onclick="appendDecimal()">.</button> <button class="operator equals" onclick="calculate()">=</button> </div> </div> <!-- Conversion Panel --> <div class="panel" id="conversion-panel"> <div class="tabs"> <div class="tab active" data-tab="length">Length</div> <div class="tab" data-tab="area">Area</div> <div class="tab" data-tab="volume">Volume</div> <div class="tab" data-tab="weight">Weight</div> </div> <div class="tab-content active" id="length-tab"> <div class="conversion-options"> <button class="conversion-btn" onclick="setConversion('in', 'ft')">in → ft</button> <button class="conversion-btn" onclick="setConversion('ft', 'in')">ft → in</button> <button class="conversion-btn" onclick="setConversion('ft', 'yd')">ft → yd</button> <button class="conversion-btn" onclick="setConversion('yd', 'ft')">yd → ft</button> <button class="conversion-btn" onclick="setConversion('ft', 'm')">ft → m</button> <button class="conversion-btn" onclick="setConversion('m', 'ft')">m → ft</button> <button class="conversion-btn" onclick="setConversion('in', 'cm')">in → cm</button> <button class="conversion-btn" onclick="setConversion('cm', 'in')">cm → in</button> <button class="conversion-btn" onclick="setConversion('ft', 'cm')">ft → cm</button> </div> <div class="material-result" id="roof-result"> Enter rise to calculate roof pitch </div> </div> </div> <!-- Quick access tools --> <div class="quick-tools"> <div class="quick-tool" onclick="quickTool('concrete')">Concrete</div> <div class="quick-tool" onclick="quickTool('lumber')">Lumber</div> <div class="quick-tool" onclick="quickTool('triangle')">Triangle</div> <div class="quick-tool" onclick="quickTool('stairs')">Stairs</div> <div class="quick-tool" onclick="quickTool('roof')">Roof</div> </div> <!-- Calculation History Panel --> <div class="history-panel" id="history-panel"> <div class="history-item" id="history-empty">No calculation history yet</div> </div> <div class="toggle-history" id="toggle-history">HISTORY</div> <div id="version-info">CONSTRUX-9000 v1.0</div> </div> <div class="footer"> CONSTRUX-9000 PRO EDITION | Built for the Modern Construction Professional </div> <!-- Toast Notification --> <div class="toast" id="toast">Result saved to memory</div> <script> // Calculator state let currentInput = '0'; let previousInput = ''; let operation = null; let resetScreen = false; let currentConversion = null; let memoryValue = 0; let calculationHistory = []; let historyVisible = false; // DOM elements const mainDisplay = document.getElementById('main-display'); const secondaryDisplay = document.getElementById('secondary-display'); const memoryIndicator = document.getElementById('memory-indicator'); const historyPanel = document.getElementById('history-panel'); const toggleHistoryBtn = document.getElementById('toggle-history'); const toast = document.getElementById('toast'); // Initialize updateDisplay(); setupEventListeners(); function setupEventListeners() { // Mode selector document.querySelectorAll('.mode-btn').forEach(btn => { btn.addEventListener('click', () => { document.querySelector('.mode-btn.active').classList.remove('active'); btn.classList.add('active'); // Hide all panels document.querySelectorAll('.panel').forEach(panel => { panel.classList.remove('active'); }); // Show selected panel document.getElementById(`${btn.dataset.mode}-panel`).classList.add('active'); }); }); // Tabs document.querySelectorAll('.tab').forEach(tab => { tab.addEventListener('click', () => { // Get all tabs in the same container const tabContainer = tab.closest('.tabs'); const tabId = tab.dataset.tab; // Deactivate all tabs in this container tabContainer.querySelectorAll('.tab').forEach(t => { t.classList.remove('active'); }); // Activate the clicked tab tab.classList.add('active'); // Find the parent panel const panel = tabContainer.closest('.panel'); // Hide all tab contents in this panel panel.querySelectorAll('.tab-content').forEach(content => { content.classList.remove('active'); }); // Show the selected tab content panel.querySelector(`#${tabId}-tab`).classList.add('active'); }); }); // Toggle history panel toggleHistoryBtn.addEventListener('click', () => { historyVisible = !historyVisible; if (historyVisible) { historyPanel.classList.add('active'); } else { historyPanel.classList.remove('active'); } }); // Save result button document.getElementById('save-result').addEventListener('click', () => { memoryValue = parseFloat(currentInput); updateMemoryIndicator(); showToast('Result saved to memory'); }); } // Toast notification function showToast(message, isError = false) { toast.textContent = message; toast.classList.remove('error'); if (isError) { toast.classList.add('error'); } toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 3000); } // Memory functions function memoryClear() { memoryValue = 0; updateMemoryIndicator(); showToast('Memory cleared'); } function memoryRecall() { if (memoryValue !== 0) { currentInput = memoryValue.toString(); updateDisplay(); showToast('Memory recalled'); } } function memoryAdd() { memoryValue += parseFloat(currentInput); updateMemoryIndicator(); showToast('Added to memory'); } function memorySubtract() { memoryValue -= parseFloat(currentInput); updateMemoryIndicator(); showToast('Subtracted from memory'); } function updateMemoryIndicator() { if (memoryValue !== 0) { memoryIndicator.textContent = 'M'; } else { memoryIndicator.textContent = ''; } } // Quick tools function function quickTool(tool) { switch(tool) { case 'concrete': activatePanel('materials'); activateTab('concrete'); break; case 'lumber': activatePanel('materials'); activateTab('lumber'); break; case 'triangle': activatePanel('geometry'); activateTab('right-triangle'); break; case 'stairs': activatePanel('geometry'); activateTab('stair'); break; case 'roof': activatePanel('geometry'); activateTab('roof'); break; } } function activatePanel(panelId) { // Update mode button document.querySelectorAll('.mode-btn').forEach(btn => { btn.classList.remove('active'); if (btn.dataset.mode === panelId) { btn.classList.add('active'); } }); // Hide all panels document.querySelectorAll('.panel').forEach(panel => { panel.classList.remove('active'); }); // Show selected panel document.getElementById(`${panelId}-panel`).classList.add('active'); } function activateTab(tabId) { // Find the tab in the currently active panel const activePanel = document.querySelector('.panel.active'); const tab = activePanel.querySelector(`.tab[data-tab="${tabId}"]`); if (tab) { // Deactivate all tabs in this container const tabContainer = tab.closest('.tabs'); tabContainer.querySelectorAll('.tab').forEach(t => { t.classList.remove('active'); }); // Activate the tab tab.classList.add('active'); // Hide all tab contents activePanel.querySelectorAll('.tab-content').forEach(content => { content.classList.remove('active'); }); // Show the selected tab content activePanel.querySelector(`#${tabId}-tab`).classList.add('active'); } } // Add calculation to history function addToHistory(calculation, result) { calculationHistory.unshift({ calculation, result }); // Keep only the last 10 calculations if (calculationHistory.length > 10) { calculationHistory.pop(); } updateHistoryPanel(); } function updateHistoryPanel() { historyPanel.innerHTML = ''; if (calculationHistory.length === 0) { historyPanel.innerHTML = '<div class="history-item" id="history-empty">No calculation history yet</div>'; return; } calculationHistory.forEach((item, index) => { const historyItem = document.createElement('div'); historyItem.className = 'history-item'; historyItem.innerHTML = ` ${item.calculation} <span class="history-result">${item.result}</span> `; historyItem.addEventListener('click', () => { currentInput = item.result.toString(); updateDisplay(); }); historyPanel.appendChild(historyItem); }); } // Basic calculator functions function appendNumber(number) { if (currentInput === '0' || resetScreen) { currentInput = number; resetScreen = false; } else { currentInput += number; } updateDisplay(); // Update conversion result if we're in conversion mode if (currentConversion) { updateConversionResult(); } } function appendDecimal() { if (resetScreen) { currentInput = '0.'; resetScreen = false; } else if (!currentInput.includes('.')) { currentInput += '.'; } updateDisplay(); // Update conversion result if we're in conversion mode if (currentConversion) { updateConversionResult(); } } function toggleSign() { currentInput = (parseFloat(currentInput) * -1).toString(); updateDisplay(); // Update conversion result if we're in conversion mode if (currentConversion) { updateConversionResult(); } } function percentage() { currentInput = (parseFloat(currentInput) / 100).toString(); updateDisplay(); } function appendOperator(op) { if (operation !== null) calculate(); previousInput = currentInput; operation = op; resetScreen = true; updateDisplay(); } function calculate() { if (operation === null || resetScreen) return; let result; const prev = parseFloat(previousInput); const current = parseFloat(currentInput); let calculationText = `${prev} ${getOperatorSymbol(operation)} ${current}`; switch (operation) { case '+': result = prev + current; break; case '-': result = prev - current; break; case '*': result = prev * current; break; case '/': result = prev / current; break; default: return; } // Add to history addToHistory(calculationText, result); currentInput = result.toString(); operation = null; resetScreen = true; updateDisplay(); } function clearAll() { currentInput = '0'; previousInput = ''; operation = null; updateDisplay(); } function backspace() { if (currentInput.length === 1 || (currentInput.length === 2 && currentInput.startsWith('-'))) { currentInput = '0'; } else { currentInput = currentInput.slice(0, -1); } updateDisplay(); // Update conversion result if we're in conversion mode if (currentConversion) { updateConversionResult(); } } function updateDisplay() { mainDisplay.textContent = currentInput; if (operation) { secondaryDisplay.textContent = `${previousInput} ${getOperatorSymbol(operation)}`; } else { secondaryDisplay.textContent = previousInput; } } function getOperatorSymbol(op) { switch (op) { case '+': return '+'; case '-': return '-'; case '*': return '×'; case '/': return '÷'; default: return op; } } // Conversion functions const conversionFactors = { // Length 'in-ft': 1/12, 'ft-in': 12, 'ft-yd': 1/3, 'yd-ft': 3, 'ft-m': 0.3048, 'm-ft': 3.28084, 'in-cm': 2.54, 'cm-in': 0.393701, 'ft-cm': 30.48, // Area 'sqin-sqft': 1/144, 'sqft-sqin': 144, 'sqft-sqyd': 1/9, 'sqyd-sqft': 9, 'sqft-sqm': 0.092903, 'sqm-sqft': 10.7639, 'acre-sqft': 43560, 'sqft-acre': 1/43560, // Volume 'cuin-cuft': 1/1728, 'cuft-cuin': 1728, 'cuft-cuyd': 1/27, 'cuyd-cuft': 27, 'cuft-gal': 7.48052, 'gal-cuft': 0.133681, 'liter-gal': 0.264172, 'gal-liter': 3.78541, // Weight 'lb-kg': 0.453592, 'kg-lb': 2.20462, 'oz-g': 28.3495, 'g-oz': 0.035274, 'ton-lb': 2000, 'lb-ton': 0.0005 }; function setConversion(from, to) { currentConversion = `${from}-${to}`; updateConversionResult(); // Update the display secondaryDisplay.textContent = `${from}${to}`; } function updateConversionResult() { if (!currentConversion) return; const parts = currentConversion.split('-'); const from = parts[0]; const to = parts[1]; // Find the appropriate result element based on the category let resultElement; if (['in', 'ft', 'yd', 'm', 'cm'].includes(from)) { resultElement = document.getElementById('conversion-result'); } else if (['sqin', 'sqft', 'sqyd', 'sqm', 'acre'].includes(from)) { resultElement = document.getElementById('area-result'); } else if (['cuin', 'cuft', 'cuyd', 'gal', 'liter'].includes(from)) { resultElement = document.getElementById('volume-result'); } else if (['lb', 'kg', 'oz', 'g', 'ton'].includes(from)) { resultElement = document.getElementById('weight-result'); } else { // Default fallback resultElement = document.getElementById('conversion-result'); } const inputValue = parseFloat(currentInput); if (isNaN(inputValue)) { resultElement.innerHTML = ` <span class="warning">Please enter a valid number</span> `; return; } const factor = conversionFactors[currentConversion]; if (!factor) { resultElement.innerHTML = ` <span class="warning">Conversion not available</span> `; return; } const convertedValue = inputValue * factor; // Add to history addToHistory(`${inputValue} ${from}${to}`, convertedValue); resultElement.innerHTML = ` <strong>${inputValue} ${from} =</strong><br> <span id="converted-value">${roundResult(convertedValue)} ${to}</span> `; } function roundResult(value, decimals = 4) { // Remove trailing zeros after decimal point return parseFloat(value.toFixed(decimals)); } // Materials calculations function calculateConcrete() { const length = parseFloat(document.getElementById('concrete-length').value); const width = parseFloat(document.getElementById('concrete-width').value); const depth = parseFloat(document.getElementById('concrete-depth').value); if (isNaN(length) || isNaN(width) || isNaN(depth)) { document.getElementById('concrete-result').innerHTML = '<span class="warning">Please enter valid dimensions</span>'; return; } // Calculate volume const cubicFeet = length * width * (depth / 12); const cubicYards = cubicFeet / 27; // Calculate bags needed (80lb bags) const bags80lb = Math.ceil(cubicYards * 45); // 45 bags per cubic yard // Calculate weight const weight = cubicYards * 4050; // 4050 lbs per cubic yard (150 lbs/cu ft) // Add to history addToHistory(`Concrete: ${length}×${width}×${depth/12}`, `${roundResult(cubicYards, 2)} yd³`); document.getElementById('concrete-result').innerHTML = ` <strong>Concrete Needed:</strong><br> ${roundResult(cubicFeet, 2)} cubic feet<br> ${roundResult(cubicYards, 2)} cubic yards<br> ${bags80lb} x 80lb bags (${roundResult(bags80lb * 80 / 2000, 2)} tons)<br> Weight: approximately ${roundResult(weight / 2000, 2)} tons `; // Show toast showToast('Concrete calculation complete!'); } function calculateLumber() { const count = parseFloat(document.getElementById('lumber-count').value); const width = parseFloat(document.getElementById('lumber-width').value); const thickness = parseFloat(document.getElementById('lumber-thickness').value); const length = parseFloat(document.getElementById('lumber-length').value); if (isNaN(count) || isNaN(width) || isNaN(thickness) || isNaN(length)) { document.getElementById('lumber-result').innerHTML = '<span class="warning">Please enter valid dimensions</span>'; return; } // Calculate board feet: (thickness × width × length) ÷ 12 const boardFeet = (thickness * width * length * count) / 12; // Calculate approximate cost ($5 per board foot - average rate) const cost = boardFeet * 5; // Add to history addToHistory(`Lumber: ${count} pieces ${thickness}×${width}×${length}`, `${roundResult(boardFeet, 2)} bd.ft`); document.getElementById('lumber-result').innerHTML = ` <strong>Lumber Total:</strong><br> ${roundResult(boardFeet, 2)} board feet<br> For ${count} pieces of ${thickness}" × ${width}" × ${length}' lumber<br> Approximate cost: ${roundResult(cost, 2)} (at $5/bd.ft.) `; // Show toast showToast('Lumber calculation complete!'); } function calculateDrywall() { const length = parseFloat(document.getElementById('drywall-length').value); const height = parseFloat(document.getElementById('drywall-height').value); const sheetSize = parseFloat(document.getElementById('drywall-sheets').value); if (isNaN(length) || isNaN(height)) { document.getElementById('drywall-result').innerHTML = '<span class="warning">Please enter valid dimensions</span>'; return; } // Calculate area const area = length * height; // Calculate sheets needed const sheets = Math.ceil(area / sheetSize); // Add 10% waste factor const sheetsWithWaste = Math.ceil(sheets * 1.1); // Calculate cost (estimate $15 per 4x8 sheet, $25 per 4x12 sheet) const sheetCost = sheetSize === 32 ? 15 : 25; const cost = sheetsWithWaste * sheetCost; // Add to history addToHistory(`Drywall: ${length}×${height} wall`, `${sheetsWithWaste} sheets`); document.getElementById('drywall-result').innerHTML = ` <strong>Drywall Needed:</strong><br> Wall area: ${roundResult(area, 2)} sq.ft.<br> ${sheets} sheets minimum (${sheetSize === 32 ? '4×8' : '4×12'})<br> Recommended: ${sheetsWithWaste} sheets (including 10% waste)<br> Estimated cost: ${roundResult(cost, 2)} `; // Show toast showToast('Drywall calculation complete!'); } function calculatePaint() { const length = parseFloat(document.getElementById('paint-length').value); const height = parseFloat(document.getElementById('paint-height').value); const coats = parseFloat(document.getElementById('paint-coats').value); const coverage = parseFloat(document.getElementById('paint-coverage').value); if (isNaN(length) || isNaN(height) || isNaN(coats) || isNaN(coverage)) { document.getElementById('paint-result').innerHTML = '<span class="warning">Please enter valid values</span>'; return; } // Calculate area const area = length * height; // Calculate paint needed const gallonsNeeded = (area * coats) / coverage; const gallonsRounded = Math.ceil(gallonsNeeded); // Calculate quarts for small jobs const quartsNeeded = gallonsNeeded * 4; // Add to history addToHistory(`Paint: ${length}×${height} wall, ${coats} coats`, `${roundResult(gallonsNeeded, 2)} gal`); document.getElementById('paint-result').innerHTML = ` <strong>Paint Needed:</strong><br> Wall area: ${roundResult(area, 2)} sq.ft.<br> ${roundResult(gallonsNeeded, 2)} gallons for ${coats} coat${coats > 1 ? 's' : ''}<br> Buy: ${gallonsRounded} gallon${gallonsRounded > 1 ? 's' : ''} or ${Math.ceil(quartsNeeded)} quart${Math.ceil(quartsNeeded) > 1 ? 's' : ''} `; // Show toast showToast('Paint calculation complete!'); } // Geometry calculations function calculateTriangle() { const a = parseFloat(document.getElementById('triangle-side-a').value); const b = parseFloat(document.getElementById('triangle-side-b').value); const c = parseFloat(document.getElementById('triangle-side-c').value); let result; // Case 1: Find hypotenuse (side c) when a and b are known if (!isNaN(a) && !isNaN(b) && isNaN(c)) { result = Math.sqrt(a*a + b*b); document.getElementById('triangle-side-c').value = roundResult(result, 2); const angle1 = Math.atan(a/b) * (180/Math.PI); const angle2 = Math.atan(b/a) * (180/Math.PI); // Add to history addToHistory(`Triangle: sides ${a}, ${b}`, `hyp=${roundResult(result, 2)}`); document.getElementById('triangle-result').innerHTML = ` <strong>Right Triangle Solution:</strong><br> Side A: ${a}<br> Side B: ${b}<br> Hypotenuse: ${roundResult(result, 2)}<br> Angle 1: ${roundResult(angle1, 1)}°<br> Angle 2: ${roundResult(angle2, 1)}° `; // Show toast showToast('Triangle calculation complete!'); } // Case 2: Find side B when A and C (hypotenuse) are known else if (!isNaN(a) && isNaN(b) && !isNaN(c)) { if (c <= a) { document.getElementById('triangle-result').innerHTML = '<span class="warning">Hypotenuse must be longer than side A</span>'; return; } result = Math.sqrt(c*c - a*a); document.getElementById('triangle-side-b').value = roundResult(result, 2); const angle1 = Math.asin(a/c) * (180/Math.PI); const angle2 = 90 - angle1; // Add to history addToHistory(`Triangle: side ${a}, hyp ${c}`, `side B=${roundResult(result, 2)}`); document.getElementById('triangle-result').innerHTML = ` <strong>Right Triangle Solution:</strong><br> Side A: ${a}<br> Hypotenuse: ${c}<br> Side B: ${roundResult(result, 2)}<br> Angle 1: ${roundResult(angle1, 1)}°<br> Angle 2: ${roundResult(angle2, 1)}° `; // Show toast showToast('Triangle calculation complete!'); } // Case 3: Find side A when B and C (hypotenuse) are known else if (isNaN(a) && !isNaN(b) && !isNaN(c)) { if (c <= b) { document.getElementById('triangle-result').innerHTML = '<span class="warning">Hypotenuse must be longer than side B</span>'; return; } result = Math.sqrt(c*c - b*b); document.getElementById('triangle-side-a').value = roundResult(result, 2); const angle1 = Math.asin(b/c) * (180/Math.PI); const angle2 = 90 - angle1; // Add to history addToHistory(`Triangle: side ${b}, hyp ${c}`, `side A=${roundResult(result, 2)}`); document.getElementById('triangle-result').innerHTML = ` <strong>Right Triangle Solution:</strong><br> Side B: ${b}<br> Hypotenuse: ${c}<br> Side A: ${roundResult(result, 2)}<br> Angle 1: ${roundResult(angle2, 1)}°<br> Angle 2: ${roundResult(angle1, 1)}° `; // Show toast showToast('Triangle calculation complete!'); } else { document.getElementById('triangle-result').innerHTML = '<span class="warning">Enter exactly two sides to calculate the third</span>'; } } function calculateCircle() { const radius = parseFloat(document.getElementById('circle-radius').value); if (isNaN(radius)) { document.getElementById('circle-result').innerHTML = '<span class="warning">Please enter a valid radius</span>'; return; } const diameter = radius * 2; const circumference = 2 * Math.PI * radius; const area = Math.PI * radius * radius; // Add to history addToHistory(`Circle: radius ${radius}`, `area=${roundResult(area, 2)}`); document.getElementById('circle-result').innerHTML = ` <strong>Circle Properties:</strong><br> Radius: ${radius} units<br> Diameter: ${roundResult(diameter, 2)} units<br> Circumference: ${roundResult(circumference, 2)} units<br> Area: ${roundResult(area, 2)} sq. units `; // Show toast showToast('Circle calculation complete!'); } function calculateStairs() { const totalRise = parseFloat(document.getElementById('stair-rise').value); const totalRun = parseFloat(document.getElementById('stair-run').value); let steps = parseFloat(document.getElementById('stair-steps').value); if (isNaN(totalRise) || isNaN(totalRun)) { document.getElementById('stair-result').innerHTML = '<span class="warning">Please enter rise and run values</span>'; return; } // If steps not provided, calculate optimal steps based on the standard 7-7.5" rise if (isNaN(steps)) { // Target rise per step: 7-7.5 inches steps = Math.round(totalRise / 7.25); document.getElementById('stair-steps').value = steps; } // Calculate rise and run per step const risePerStep = totalRise / steps; const runPerStep = totalRun / (steps - 1); // steps - 1 gives number of treads // Calculate stringer length using pythagorean theorem const stringerLength = Math.sqrt(totalRise * totalRise + totalRun * totalRun); // Check if rise/run are within recommended ranges const riseWarning = (risePerStep < 4 || risePerStep > 8) ? '<span class="warning">Warning: Rise per step should be 4-8 inches</span><br>' : ''; const runWarning = (runPerStep < 9 || runPerStep > 11) ? '<span class="warning">Warning: Run per step should be 9-11 inches</span><br>' : ''; // Add to history addToHistory(`Stairs: rise ${totalRise}", run ${totalRun}"`, `${steps} steps`); document.getElementById('stair-result').innerHTML = ` <strong>Stair Dimensions:</strong><br> ${riseWarning}${runWarning} Number of steps: ${steps}<br> Rise per step: ${roundResult(risePerStep, 2)}"<br> Run per step: ${roundResult(runPerStep, 2)}"<br> Total stringer length: ${roundResult(stringerLength, 2)}" `; // Show toast showToast('Stair calculation complete!'); } function calculateRoofPitch() { const rise = parseFloat(document.getElementById('roof-rise').value); if (isNaN(rise)) { document.getElementById('roof-result').innerHTML = '<span class="warning">Please enter a valid rise value</span>'; return; } const run = 12; // Standard run // Calculate pitch as rise/run (expressed as n:12) const pitch = rise / run; // Calculate angle in degrees const angle = Math.atan(pitch) * (180 / Math.PI); // Calculate slope as a percentage const slope = pitch * 100; // Calculate roof multiplier (factor to convert horizontal measurements to sloped) const multiplier = Math.sqrt(rise*rise + run*run) / run; // Add to history addToHistory(`Roof pitch: ${rise}:12`, `${roundResult(angle, 1)}°`); document.getElementById('roof-result').innerHTML = ` <strong>Roof Pitch Results:</strong><br> Pitch: ${rise}:12<br> Angle: ${roundResult(angle, 1)}°<br> Slope: ${roundResult(slope, 1)}%<br> Roof multiplier: ${roundResult(multiplier, 3)}<br> <small>(Multiply flat measurements by ${roundResult(multiplier, 3)} to get actual roof measurements)</small> `; // Show toast showToast('Roof pitch calculation complete!'); } </script> </body> </html>conversion-result"> Select a conversion above </div> </div> <div class="tab-content" id="area-tab"> <div class="conversion-options"> <button class="conversion-btn" onclick="setConversion('sqin', 'sqft')">in² → ft²</button> <button class="conversion-btn" onclick="setConversion('sqft', 'sqin')">ft² → in²</button> <button class="conversion-btn" onclick="setConversion('sqft', 'sqyd')">ft² → yd²</button> <button class="conversion-btn" onclick="setConversion('sqyd', 'sqft')">yd² → ft²</button> <button class="conversion-btn" onclick="setConversion('sqft', 'sqm')">ft² → m²</button> <button class="conversion-btn" onclick="setConversion('sqm', 'sqft')">m² → ft²</button> <button class="conversion-btn" onclick="setConversion('acre', 'sqft')">acre → ft²</button> <button class="conversion-btn" onclick="setConversion('sqft', 'acre')">ft² → acre</button> </div> <div class="material-result" id="area-result"> Select an area conversion </div> </div> <div class="tab-content" id="volume-tab"> <div class="conversion-options"> <button class="conversion-btn" onclick="setConversion('cuin', 'cuft')">in³ → ft³</button> <button class="conversion-btn" onclick="setConversion('cuft', 'cuin')">ft³ → in³</button> <button class="conversion-btn" onclick="setConversion('cuft', 'cuyd')">ft³ → yd³</button> <button class="conversion-btn" onclick="setConversion('cuyd', 'cuft')">yd³ → ft³</button> <button class="conversion-btn" onclick="setConversion('cuft', 'gal')">ft³ → gal</button> <button class="conversion-btn" onclick="setConversion('gal', 'cuft')">gal → ft³</button> <button class="conversion-btn" onclick="setConversion('liter', 'gal')">L → gal</button> <button class="conversion-btn" onclick="setConversion('gal', 'liter')">gal → L</button> </div> <div class="material-result" id="volume-result"> Select a volume conversion </div> </div> <div class="tab-content" id="weight-tab"> <div class="conversion-options"> <button class="conversion-btn" onclick="setConversion('lb', 'kg')">lb → kg</button> <button class="conversion-btn" onclick="setConversion('kg', 'lb')">kg → lb</button> <button class="conversion-btn" onclick="setConversion('oz', 'g')">oz → g</button> <button class="conversion-btn" onclick="setConversion('g', 'oz')">g → oz</button> <button class="conversion-btn" onclick="setConversion('ton', 'lb')">ton → lb</button> <button class="conversion-btn" onclick="setConversion('lb', 'ton')">lb → ton</button> </div> <div class="material-result" id="weight-result"> Select a weight conversion </div> </div> </div> <!-- Materials Calculator --> <div class="panel" id="materials-panel"> <div class="tabs"> <div class="tab active" data-tab="concrete">Concrete</div> <div class="tab" data-tab="lumber">Lumber</div> <div class="tab" data-tab="drywall">Drywall</div> <div class="tab" data-tab="paint">Paint</div> </div> <div class="tab-content active" id="concrete-tab"> <div class="material-input"> <label for="concrete-length">Length (ft)</label> <input type="number" id="concrete-length" placeholder="Enter length"> </div> <div class="material-input"> <label for="concrete-width">Width (ft)</label> <input type="number" id="concrete-width" placeholder="Enter width"> </div> <div class="material-input"> <label for="concrete-depth">Depth (in)</label> <input type="number" id="concrete-depth" placeholder="Enter depth"> </div> <button onclick="calculateConcrete()">Calculate</button> <div class="material-result" id="concrete-result"> Enter dimensions to calculate concrete needed </div> </div> <div class="tab-content" id="lumber-tab"> <div class="material-input"> <label for="lumber-count">Number of Pieces</label> <input type="number" id="lumber-count" placeholder="Enter quantity"> </div> <div class="material-input"> <label for="lumber-width">Width (in)</label> <input type="number" id="lumber-width" placeholder="Enter width"> </div> <div class="material-input"> <label for="lumber-thickness">Thickness (in)</label> <input type="number" id="lumber-thickness" placeholder="Enter thickness"> </div> <div class="material-input"> <label for="lumber-length">Length (ft)</label> <input type="number" id="lumber-length" placeholder="Enter length"> </div> <button onclick="calculateLumber()">Calculate</button> <div class="material-result" id="lumber-result"> Enter dimensions to calculate board feet </div> </div> <div class="tab-content" id="drywall-tab"> <div class="material-input"> <label for="drywall-length">Wall Length (ft)</label> <input type="number" id="drywall-length" placeholder="Enter length"> </div> <div class="material-input"> <label for="drywall-height">Wall Height (ft)</label> <input type="number" id="drywall-height" placeholder="Enter height"> </div> <div class="material-input"> <label for="drywall-sheets">Sheet Size</label> <select id="drywall-sheets"> <option value="32">4x8 ft (32 sqft)</option> <option value="48">4x12 ft (48 sqft)</option> </select> </div> <button onclick="calculateDrywall()">Calculate</button> <div class="material-result" id="drywall-result"> Enter dimensions to calculate drywall needed </div> </div> <div class="tab-content" id="paint-tab"> <div class="material-input"> <label for="paint-length">Wall Length (ft)</label> <input type="number" id="paint-length" placeholder="Enter length"> </div> <div class="material-input"> <label for="paint-height">Wall Height (ft)</label> <input type="number" id="paint-height" placeholder="Enter height"> </div> <div class="material-input"> <label for="paint-coats">Number of Coats</label> <input type="number" id="paint-coats" value="2" min="1"> </div> <div class="material-input"> <label for="paint-coverage">Paint Coverage (sqft/gal)</label> <input type="number" id="paint-coverage" value="350" min="100"> </div> <button onclick="calculatePaint()">Calculate</button> <div class="material-result" id="paint-result"> Enter dimensions to calculate paint needed </div> </div> </div> <!-- Geometry Calculator --> <div class="panel" id="geometry-panel"> <div class="tabs"> <div class="tab active" data-tab="right-triangle">Triangle</div> <div class="tab" data-tab="circle">Circle</div> <div class="tab" data-tab="stair">Stairs</div> <div class="tab" data-tab="roof">Roof Pitch</div> </div> <div class="tab-content active" id="right-triangle-tab"> <div class="material-input"> <label for="triangle-side-a">Side A</label> <input type="number" id="triangle-side-a" placeholder="Enter length"> </div> <div class="material-input"> <label for="triangle-side-b">Side B</label> <input type="number" id="triangle-side-b" placeholder="Enter length"> </div> <div class="material-input"> <label for="triangle-side-c">Side C (Hypotenuse)</label> <input type="number" id="triangle-side-c" placeholder="Leave blank to calculate"> </div> <button onclick="calculateTriangle()">Calculate</button> <div class="material-result" id="triangle-result"> Enter two sides to calculate the third </div> </div> <div class="tab-content" id="circle-tab"> <div class="material-input"> <label for="circle-radius">Radius</label> <input type="number" id="circle-radius" placeholder="Enter radius"> </div> <button onclick="calculateCircle()">Calculate</button> <div class="material-result" id="circle-result"> Enter radius to calculate circle properties </div> </div> <div class="tab-content" id="stair-tab"> <div class="material-input"> <label for="stair-rise">Total Rise (in)</label> <input type="number" id="stair-rise" placeholder="Floor to floor height"> </div> <div class="material-input"> <label for="stair-run">Total Run (in)</label> <input type="number" id="stair-run" placeholder="Total horizontal distance"> </div> <div class="material-input"> <label for="stair-steps">Number of Steps</label> <input type="number" id="stair-steps" placeholder="Leave blank to calculate"> </div> <div class="stair-formula"> Standard stairs: 7-7.5" rise, 10-11" run per step </div> <button onclick="calculateStairs()">Calculate</button> <div class="material-result" id="stair-result"> Enter rise and run to calculate stair dimensions </div> </div> <div class="tab-content" id="roof-tab"> <div class="material-input"> <label for="roof-rise">Rise (in)</label> <input type="number" id="roof-rise" placeholder="Vertical rise per 12in"> </div> <div class="material-input"> <label for="roof-run">Run (in)</label> <input type="number" id="roof-run" value="12" disabled> </div> <button onclick="calculateRoofPitch()">Calculate</button> <div class="material-result" id="

Comments

Popular posts from this blog

Articles for Calculator.ist

Calc.ist: List of all Calculators: Total of 592.

HP-65 Calculator Simulator (1974)