```html Multi Tool Hub

Multi Tool Hub

`; }); renderFields(); } // Business Tools function createDynamicTableUI(parent, { title, fields, previewId, itemLabel }) { parent.innerHTML = `

${title} Details


Client Details


${itemLabel}s


Preview

`; const itemsContainer = document.getElementById('items-container'); const addItemBtn = document.getElementById('addItemBtn'); function createItemRow() { const itemRow = document.createElement('div'); itemRow.className = 'grid-3'; itemRow.style.marginBottom = '1rem'; let itemFieldsHTML = ''; for (const key in fields) { itemFieldsHTML += `
`; } itemRow.innerHTML = itemFieldsHTML + ``; itemsContainer.appendChild(itemRow); } addItemBtn.addEventListener('click', createItemRow); itemsContainer.addEventListener('click', e => { if (e.target.classList.contains('removeItemBtn')) { e.target.parentElement.remove(); updatePreview(); } }); createItemRow(); // Start with one item row return updatePreview; } function invoiceGeneratorUI(parent) { const updatePreview = createDynamicTableUI(parent, { title: 'Invoice', fields: { description: 'Description', qty: 'Quantity', price: 'Unit Price' }, previewId: 'invoice-preview', itemLabel: 'Item' }); function updateInvoicePreview() { const companyName = document.getElementById('companyName').value; const clientName = document.getElementById('clientName').value; const itemRows = document.querySelectorAll('#items-container .grid-3'); let itemsHTML = ''; let total = 0; itemRows.forEach(row => { const desc = row.querySelector('[data-field="description"]').value; const qty = parseFloat(row.querySelector('[data-field="qty"]').value) || 0; const price = parseFloat(row.querySelector('[data-field="price"]').value) || 0; const subtotal = qty * price; total += subtotal; itemsHTML += `${desc}${qty}$${price.toFixed(2)}$${subtotal.toFixed(2)}`; }); document.getElementById('invoice-preview').innerHTML = `

INVOICE

From: ${companyName}

To: ${clientName}


${itemsHTML}
DescriptionQuantityUnit PriceSubtotal
Total:$${total.toFixed(2)}
`; } parent.addEventListener('input', updateInvoicePreview); document.getElementById('printBtn').addEventListener('click', () => window.print()); updateInvoicePreview(); } function quoteMakerToolUI(parent) { // Very similar to invoice, just different labels const updatePreview = createDynamicTableUI(parent, { title: 'Quote', fields: { description: 'Service/Product', qty: 'Quantity', price: 'Unit Price' }, previewId: 'quote-preview', itemLabel: 'Line Item' }); function updateQuotePreview() { const companyName = document.getElementById('companyName').value; const clientName = document.getElementById('clientName').value; const itemRows = document.querySelectorAll('#items-container .grid-3'); let itemsHTML = ''; let total = 0; itemRows.forEach(row => { const desc = row.querySelector('[data-field="description"]').value; const qty = parseFloat(row.querySelector('[data-field="qty"]').value) || 0; const price = parseFloat(row.querySelector('[data-field="price"]').value) || 0; const subtotal = qty * price; total += subtotal; itemsHTML += `${desc}${qty}$${price.toFixed(2)}$${subtotal.toFixed(2)}`; }); document.getElementById('quote-preview').innerHTML = `

QUOTE

Prepared for: ${clientName}

Prepared by: ${companyName}

Date: ${new Date().toLocaleDateString()}


${itemsHTML}
DescriptionQuantityUnit PriceSubtotal
Estimated Total:$${total.toFixed(2)}

This quote is valid for 30 days.

`; } parent.addEventListener('input', updateQuotePreview); document.getElementById('printBtn').addEventListener('click', () => window.print()); updateQuotePreview(); } function receiptGeneratorUI(parent) { const updatePreview = createDynamicTableUI(parent, { title: 'Receipt', fields: { item: 'Item Purchased', price: 'Price' }, previewId: 'receipt-preview', itemLabel: 'Item' }); function updateReceiptPreview() { const companyName = document.getElementById('companyName').value; const clientName = document.getElementById('clientName').value; const itemRows = document.querySelectorAll('#items-container .grid-3'); let itemsHTML = ''; let total = 0; itemRows.forEach(row => { const item = row.querySelector('[data-field="item"]').value; const price = parseFloat(row.querySelector('[data-field="price"]').value) || 0; total += price; itemsHTML += `${item}$${price.toFixed(2)}`; }); document.getElementById('receipt-preview').innerHTML = `

RECEIPT OF PURCHASE

${companyName}


Date: ${new Date().toLocaleString()}

Sold to: ${clientName || 'Valued Customer'}

${itemsHTML}
ItemPrice
Total Paid:$${total.toFixed(2)}

Thank you for your business!

`; } parent.addEventListener('input', updateReceiptPreview); document.getElementById('printBtn').addEventListener('click', () => window.print()); updateReceiptPreview(); } function purchaseOrderMakerUI(parent) { const updatePreview = createDynamicTableUI(parent, { title: 'Purchase Order', fields: { item: 'Item/SKU', description: 'Description', qty: 'Quantity', price: 'Unit Price' }, previewId: 'po-preview', itemLabel: 'Item' }); function updatePOPreview() { const companyName = document.getElementById('companyName').value; const companyAddress = document.getElementById('companyAddress').value; const vendorName = document.getElementById('clientName').value; // Re-using client name for vendor const vendorAddress = document.getElementById('clientAddress').value; const itemRows = document.querySelectorAll('#items-container .grid-3'); let itemsHTML = ''; let total = 0; itemRows.forEach(row => { const item = row.querySelector('[data-field="item"]').value; const desc = row.querySelector('[data-field="description"]').value; const qty = parseFloat(row.querySelector('[data-field="qty"]').value) || 0; const price = parseFloat(row.querySelector('[data-field="price"]').value) || 0; const subtotal = qty * price; total += subtotal; itemsHTML += `${item}${desc}${qty}$${price.toFixed(2)}$${subtotal.toFixed(2)}`; }); document.getElementById('po-preview').innerHTML = `

PURCHASE ORDER

To (Vendor):
${vendorName}
${vendorAddress}
Ship To:
${companyName}
${companyAddress}

${itemsHTML}
Item/SKUDescriptionQtyUnit PriceTotal
Grand Total:$${total.toFixed(2)}
`; } parent.addEventListener('input', updatePOPreview); document.getElementById('printBtn').addEventListener('click', () => window.print()); updatePOPreview(); } // LocalStorage CRUD Manager function createLocalStorageManagerUI(options, parent) { const { id, title, fields, fieldTypes = {}, itemLabel } = options; const storageKey = `mth_${id}_data`; let data = JSON.parse(localStorage.getItem(storageKey) || '[]'); parent.innerHTML = `

Add New ${itemLabel}

${Object.keys(fields).map(key => `
`).join('')}

Current ${title}

`; const addBtn = document.getElementById('add-btn'); const tableContainer = document.getElementById('data-table-container'); function saveData() { localStorage.setItem(storageKey, JSON.stringify(data)); } function renderTable() { if(data.length === 0) { tableContainer.innerHTML = `

No ${itemLabel.toLowerCase()}s added yet.

`; return; } let tableHTML = ``; for (const key in fields) { tableHTML += ``; } tableHTML += ``; data.forEach((item, index) => { tableHTML += ``; for (const key in fields) { tableHTML += ``; } tableHTML += ``; tableHTML += ``; }); tableHTML += `
${fields[key]}Actions
${item[key] || ''}
`; tableContainer.innerHTML = tableHTML; } addBtn.addEventListener('click', () => { const newItem = {}; let isValid = true; for (const key in fields) { const input = document.getElementById(`add-${key}`); if (!input.value && input.required) { // Simple validation isValid = false; input.style.borderColor = 'red'; } else { newItem[key] = input.value; input.style.borderColor = ''; } } if (isValid) { data.push(newItem); saveData(); renderTable(); // Clear form for (const key in fields) { document.getElementById(`add-${key}`).value = ''; } } }); tableContainer.addEventListener('click', e => { if (e.target.classList.contains('delete-btn')) { const index = parseInt(e.target.dataset.index, 10); if (confirm(`Are you sure you want to delete this ${itemLabel.toLowerCase()}?`)) { data.splice(index, 1); saveData(); renderTable(); } } }); renderTable(); } function toDoListUI(parent) { const storageKey = 'mth_todo_list'; let todos = JSON.parse(localStorage.getItem(storageKey) || '[]'); parent.innerHTML = `
`; const input = document.getElementById('todoInput'); const prioritySelect = document.getElementById('todoPriority'); const addBtn = document.getElementById('addTodoBtn'); const listContainer = document.getElementById('todoListContainer'); const priorityColors = { low: '#3498db', medium: '#f1c40f', high: '#e74c3c' }; function saveTodos() { localStorage.setItem(storageKey, JSON.stringify(todos)); } function renderTodos() { listContainer.innerHTML = ''; if (todos.length === 0) { listContainer.innerHTML = '
  • No tasks yet. Add one above!
  • '; return; } todos.forEach((todo, index) => { const li = document.createElement('li'); li.style.background = 'var(--bg-color)'; li.style.padding = '1rem'; li.style.marginBottom = '0.5rem'; li.style.borderRadius = '5px'; li.style.display = 'flex'; li.style.justifyContent = 'space-between'; li.style.alignItems = 'center'; li.style.borderLeft = `5px solid ${priorityColors[todo.priority]}`; li.innerHTML = ` ${todo.text}
    `; listContainer.appendChild(li); }); } addBtn.addEventListener('click', () => { const text = input.value.trim(); if (text) { todos.push({ text, priority: prioritySelect.value, done: false }); saveTodos(); renderTodos(); input.value = ''; } }); listContainer.addEventListener('click', e => { const index = e.target.dataset.index; if (e.target.classList.contains('toggle-done')) { todos[index].done = !todos[index].done; } if (e.target.classList.contains('delete-todo')) { todos.splice(index, 1); } saveTodos(); renderTodos(); }); renderTodos(); } function budgetPlannerUI(parent) { const storageKey = 'mth_budget_data'; let data = JSON.parse(localStorage.getItem(storageKey) || '{ "income": [], "expenses": [] }'); parent.innerHTML = `

    Summary


    Income Sources

    Expenses

    `; function saveData() { localStorage.setItem(storageKey, JSON.stringify(data)); } function render() { const totalIncome = data.income.reduce((sum, item) => sum + item.amount, 0); const totalExpenses = data.expenses.reduce((sum, item) => sum + item.amount, 0); const balance = totalIncome - totalExpenses; document.getElementById('summary').innerHTML = `
    Total Income: $${totalIncome.toFixed(2)}
    Total Expenses: $${totalExpenses.toFixed(2)}
    Balance: $${balance.toFixed(2)}
    `; document.getElementById('income-list').innerHTML = data.income.map((item, i) => `
    ${item.desc}: $${item.amount.toFixed(2)}
    `).join(''); document.getElementById('expense-list').innerHTML = data.expenses.map((item, i) => `
    ${item.desc}: $${item.amount.toFixed(2)}
    `).join(''); } document.getElementById('addIncome').addEventListener('click', () => { const desc = document.getElementById('incomeDesc').value; const amount = parseFloat(document.getElementById('incomeAmount').value); if (desc && amount > 0) { data.income.push({ desc, amount }); saveData(); render(); document.getElementById('incomeDesc').value = ''; document.getElementById('incomeAmount').value = ''; } }); document.getElementById('addExpense').addEventListener('click', () => { const desc = document.getElementById('expenseDesc').value; const amount = parseFloat(document.getElementById('expenseAmount').value); if (desc && amount > 0) { data.expenses.push({ desc, amount }); saveData(); render(); document.getElementById('expenseDesc').value = ''; document.getElementById('expenseAmount').value = ''; } }); parent.addEventListener('click', e => { if (e.target.classList.contains('delete-btn')) { const type = e.target.dataset.type; const index = parseInt(e.target.dataset.index); data[type].splice(index, 1); saveData(); render(); } }); render(); } function timeTrackerUI(parent) { let timerInterval = null; let startTime = 0; let elapsedTime = 0; parent.innerHTML = `
    00:00:00
    `; const timeDisplay = document.getElementById('timeDisplay'); const startBtn = document.getElementById('startBtn'); const stopBtn = document.getElementById('stopBtn'); const resetBtn = document.getElementById('resetBtn'); function formatTime(ms) { const totalSeconds = Math.floor(ms / 1000); const hours = Math.floor(totalSeconds / 3600).toString().padStart(2, '0'); const minutes = Math.floor((totalSeconds % 3600) / 60).toString().padStart(2, '0'); const seconds = (totalSeconds % 60).toString().padStart(2, '0'); return `${hours}:${minutes}:${seconds}`; } function updateDisplay() { const currentTime = Date.now(); timeDisplay.textContent = formatTime(elapsedTime + (currentTime - startTime)); } startBtn.addEventListener('click', () => { if (timerInterval) return; startTime = Date.now(); timerInterval = setInterval(updateDisplay, 100); startBtn.disabled = true; stopBtn.disabled = false; }); stopBtn.addEventListener('click', () => { if (!timerInterval) return; clearInterval(timerInterval); timerInterval = null; elapsedTime += Date.now() - startTime; startBtn.disabled = false; stopBtn.disabled = true; }); resetBtn.addEventListener('click', () => { clearInterval(timerInterval); timerInterval = null; startTime = 0; elapsedTime = 0; timeDisplay.textContent = '00:00:00'; startBtn.disabled = false; stopBtn.disabled = true; }); } function billingCalculatorUI(parent) { simpleCalculatorUI(parent, { title: 'Billing', fields: [ { label: 'Hours Worked', id: 'hours', placeholder: 'e.g., 40' }, { label: 'Hourly Rate', id: 'rate', placeholder: 'e.g., 50' }, ], calculationFn: (values) => { const totalBill = values.hours * values.rate; return `Total Billing Amount: $${totalBill.toFixed(2)}`; } }); } function dailyPlannerUI(parent) { const storageKey = 'mth_daily_planner'; let plannerData = JSON.parse(localStorage.getItem(storageKey) || '{}'); let html = ''; for (let i = 6; i < 23; i++) { // 6 AM to 10 PM const time = `${i.toString().padStart(2, '0')}:00`; html += `
    ${time}
    `; } parent.innerHTML = html; parent.addEventListener('input', e => { if (e.target.classList.contains('planner-input')) { plannerData[e.target.dataset.time] = e.target.value; localStorage.setItem(storageKey, JSON.stringify(plannerData)); } }); } function meetingSchedulerUI(parent) { parent.innerHTML = `

    Proposed Times:

    `; let proposedTimes = []; const list = document.getElementById('proposedTimesList'); const output = document.getElementById('copyOutput'); function render() { list.innerHTML = proposedTimes.map((t, i) => `
  • ${t.toLocaleString([], { dateStyle: 'medium', timeStyle: 'short' })}
  • `).join(''); if (proposedTimes.length > 0) { output.textContent = "Here are some proposed meeting times:\n\n" + proposedTimes.map(t => `- ${t.toLocaleString([], { weekday: 'long', month: 'long', day: 'numeric', hour: 'numeric', minute: '2-digit' })}`).join('\n'); } else { output.textContent = ''; } } document.getElementById('addMeetingTime').addEventListener('click', () => { const dateStr = document.getElementById('meetingDate').value; const timeStr = document.getElementById('meetingTime').value; if (dateStr && timeStr) { const [year, month, day] = dateStr.split('-'); const [hour, minute] = timeStr.split(':'); const proposedDate = new Date(year, month - 1, day, hour, minute); proposedTimes.push(proposedDate); proposedTimes.sort((a,b) => a - b); render(); } }); list.addEventListener('click', e => { if(e.target.classList.contains('remove-time')) { proposedTimes.splice(e.target.dataset.index, 1); render(); } }); } function productPricingCalculatorUI(parent) { simpleCalculatorUI(parent, { title: 'Product Price', fields: [ { label: 'Product Cost', id: 'cost', placeholder: 'e.g., 50' }, { label: 'Desired Profit Margin (%)', id: 'margin', placeholder: 'e.g., 40' }, { label: 'Shipping & Other Costs', id: 'otherCosts', placeholder: 'e.g., 5' }, ], calculationFn: (values) => { if (values.margin >= 100) return "Profit margin must be less than 100%."; const retailPrice = (values.cost + values.otherCosts) / (1 - (values.margin / 100)); const profit = retailPrice - values.cost - values.otherCosts; return `

    Retail Price to achieve a ${values.margin}% margin: $${retailPrice.toFixed(2)}

    Profit per sale: $${profit.toFixed(2)}

    `; } }); } function customerFeedbackFormBuilderUI(parent) { parent.innerHTML = `

    This tool generates basic HTML for a feedback form.

    You will need a backend or a third-party service (like Formspree) to actually collect submissions.

    `; document.getElementById('feedbackFormOutput').textContent = `

    Customer Feedback

    `.trim(); } function freelanceRateCalculatorUI(parent) { simpleCalculatorUI(parent, { title: 'Hourly Rate', fields: [ { label: 'Desired Annual Income', id: 'income', placeholder: 'e.g., 80000' }, { label: 'Annual Business Expenses (software, etc.)', id: 'expenses', placeholder: 'e.g., 5000' }, { label: 'Billable Hours Per Week', id: 'hours', placeholder: 'e.g., 25' }, { label: 'Weeks Worked Per Year (after vacation/sick days)', id: 'weeks', placeholder: 'e.g., 48' }, ], calculationFn: (values) => { const totalRevenueNeeded = values.income + values.expenses; const totalBillableHours = values.hours * values.weeks; if (totalBillableHours <= 0) return "Billable hours must be positive."; const hourlyRate = totalRevenueNeeded / totalBillableHours; return `

    To meet your goals, you should charge an hourly rate of at least:

    $${hourlyRate.toFixed(2)} / hour

    `; } }); } function stockValueCalculatorUI(parent) { let stocks = []; parent.innerHTML = `

    Portfolio

    Total Portfolio Value: $0.00

    `; const listContainer = document.getElementById('stockList'); const totalValueEl = document.getElementById('stockTotalValue'); function render() { listContainer.innerHTML = stocks.map((s, i) => `
    ${s.ticker}: ${s.shares} shares @ $${s.price.toFixed(2)} = $${(s.shares * s.price).toFixed(2)}
    `).join(''); const totalValue = stocks.reduce((sum, s) => sum + (s.shares * s.price), 0); totalValueEl.textContent = `Total Portfolio Value: $${totalValue.toFixed(2)}`; } document.getElementById('addStockBtn').addEventListener('click', () => { const ticker = document.getElementById('stockTicker').value.toUpperCase(); const shares = parseFloat(document.getElementById('stockShares').value); const price = parseFloat(document.getElementById('stockPrice').value); if (ticker && shares > 0 && price > 0) { stocks.push({ ticker, shares, price }); render(); document.getElementById('stockTicker').value = ''; document.getElementById('stockShares').value = ''; document.getElementById('stockPrice').value = ''; } }); listContainer.addEventListener('click', e => { if(e.target.classList.contains('remove-stock')) { stocks.splice(e.target.dataset.index, 1); render(); } }); } function salesCommissionCalculatorUI(parent) { simpleCalculatorUI(parent, { title: 'Commission', fields: [ { label: 'Sale Revenue', id: 'revenue', placeholder: 'e.g., 10000' }, { label: 'Commission Rate (%)', id: 'rate', placeholder: 'e.g., 5' }, ], calculationFn: (values) => { const commission = values.revenue * (values.rate / 100); return `Sales Commission Earned: $${commission.toFixed(2)}`; } }); } function productInventoryCounterUI(parent) { parent.innerHTML = `

    0

    `; let count = 0; const display = document.getElementById('invCountDisplay'); document.getElementById('invPlusBtn').addEventListener('click', () => display.textContent = ++count); document.getElementById('invMinusBtn').addEventListener('click', () => display.textContent = --count); document.getElementById('invResetBtn').addEventListener('click', () => { count = 0; display.textContent = count; }); } // Dev & Utility Tools function qrCodeGeneratorUI(parent) { parent.innerHTML = `
    `; const textInput = document.getElementById('qrText'); const outputDiv = document.getElementById('qrCodeOutput'); function generate() { outputDiv.innerHTML = ''; const text = textInput.value.trim(); if (text) { // Use the integrated QRCode library new QRCode(outputDiv, { text: text, width: 256, height: 256, colorDark: "#000000", colorLight: "#ffffff", correctLevel: QRCode.CorrectLevel.H }); } } textInput.addEventListener('input', generate); generate(); // Generate for placeholder if any } function passwordGeneratorUI(parent) { parent.innerHTML = `
    Uppercase
    Lowercase
    Numbers
    Symbols
    `; const lengthSlider = document.getElementById('passLength'); const lengthValue = document.getElementById('passLengthValue'); const resultBox = document.getElementById('passwordResult'); lengthSlider.addEventListener('input', () => lengthValue.textContent = lengthSlider.value); document.getElementById('generatePassBtn').addEventListener('click', () => { const length = parseInt(lengthSlider.value); const useUpper = document.getElementById('upper').checked; const useLower = document.getElementById('lower').checked; const useNumbers = document.getElementById('numbers').checked; const useSymbols = document.getElementById('symbols').checked; const upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const lowerChars = "abcdefghijklmnopqrstuvwxyz"; const numberChars = "0123456789"; const symbolChars = "!@#$%^&*()_+~`|}{[]:;?><,./-="; let charPool = ""; if (useUpper) charPool += upperChars; if (useLower) charPool += lowerChars; if (useNumbers) charPool += numberChars; if (useSymbols) charPool += symbolChars; if (charPool === "") { resultBox.textContent = "Please select at least one character type."; return; } let password = ""; for (let i = 0; i < length; i++) { const randomIndex = Math.floor(Math.random() * charPool.length); password += charPool[randomIndex]; } resultBox.textContent = password; }); } function wordCounterUI(parent) { parent.innerHTML = `
    `; document.getElementById('wordCountText').addEventListener('input', e => { const text = e.target.value; const words = text.match(/\b\w+\b/g) || []; const characters = text.length; const sentences = text.match(/[^.!?]+[.!?]+/g) || []; const paragraphs = text.split(/\n+/).filter(p => p.trim().length > 0); document.getElementById('wordCountResult').innerHTML = `
    Words: ${words.length}
    Characters: ${characters}
    Sentences: ${sentences.length}
    Paragraphs: ${paragraphs.length}
    `; }); } function base64EncoderDecoderUI(parent) { parent.innerHTML = `
    `; document.getElementById('b64EncodeBtn').addEventListener('click', () => { const input = document.getElementById('b64Input').value; try { document.getElementById('b64Output').value = btoa(input); } catch (e) { document.getElementById('b64Output').value = 'Error: ' + e.message; } }); document.getElementById('b64DecodeBtn').addEventListener('click', () => { const input = document.getElementById('b64Input').value; try { document.getElementById('b64Output').value = atob(input); } catch (e) { document.getElementById('b64Output').value = 'Error: Invalid Base64 string.'; } }); } function colorPickerToolUI(parent) { parent.innerHTML = `
    `; const picker = document.getElementById('colorPicker'); const valuesBox = document.getElementById('colorValues'); function updateColor() { const hex = picker.value.toUpperCase(); const rgb = hexToRgb(hex); const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b); valuesBox.innerHTML = `

    HEX: ${hex}

    RGB: rgb(${rgb.r}, ${rgb.g}, ${rgb.b})

    HSL: hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)

    `; valuesBox.style.backgroundColor = hex; valuesBox.style.color = (rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114) > 186 ? '#000000' : '#ffffff'; } picker.addEventListener('input', updateColor); updateColor(); } function textToSpeechUI(parent) { if (!('speechSynthesis' in window)) { parent.innerHTML = `

    Sorry, your browser does not support Text-to-Speech.

    `; return; } parent.innerHTML = `
    `; const voiceSelect = document.getElementById('ttsVoice'); function populateVoiceList() { const voices = speechSynthesis.getVoices(); voiceSelect.innerHTML = voices.map((voice, i) => `` ).join(''); } populateVoiceList(); if (speechSynthesis.onvoiceschanged !== undefined) { speechSynthesis.onvoiceschanged = populateVoiceList; } document.getElementById('ttsSpeakBtn').addEventListener('click', () => { const text = document.getElementById('ttsText').value; const utterance = new SpeechSynthesisUtterance(text); const voices = speechSynthesis.getVoices(); const selectedVoiceIndex = voiceSelect.value; utterance.voice = voices[selectedVoiceIndex]; speechSynthesis.cancel(); // Cancel any previous speech speechSynthesis.speak(utterance); }); document.getElementById('ttsPauseBtn').addEventListener('click', () => speechSynthesis.pause()); document.getElementById('ttsResumeBtn').addEventListener('click', () => speechSynthesis.resume()); } function speechToTextUI(parent) { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; if (!SpeechRecognition) { parent.innerHTML = `

    Sorry, your browser does not support Speech-to-Text.

    `; return; } const recognition = new SpeechRecognition(); recognition.continuous = true; recognition.interimResults = true; recognition.lang = 'en-US'; let finalTranscript = ''; parent.innerHTML = `

    Click "Start Listening" and speak into your microphone.

    `; const startBtn = document.getElementById('sttStartBtn'); const stopBtn = document.getElementById('sttStopBtn'); const finalSpan = document.getElementById('final_span'); const interimSpan = document.getElementById('interim_span'); recognition.onresult = (event) => { let interimTranscript = ''; for (let i = event.resultIndex; i < event.results.length; ++i) { if (event.results[i].isFinal) { finalTranscript += event.results[i][0].transcript; } else { interimTranscript += event.results[i][0].transcript; } } finalSpan.innerHTML = finalTranscript; interimSpan.innerHTML = interimTranscript; }; startBtn.addEventListener('click', () => { finalTranscript = ''; recognition.start(); startBtn.disabled = true; stopBtn.disabled = false; }); stopBtn.addEventListener('click', () => { recognition.stop(); startBtn.disabled = false; stopBtn.disabled = true; }); } function jsonFormatterUI(parent) { parent.innerHTML = `
    `; document.getElementById('formatJsonBtn').addEventListener('click', () => { const input = document.getElementById('jsonInput').value; const resultBox = document.getElementById('jsonResult'); try { const jsonObj = JSON.parse(input); resultBox.style.color = 'var(--text-color)'; resultBox.textContent = JSON.stringify(jsonObj, null, 2); } catch (e) { resultBox.style.color = 'salmon'; resultBox.textContent = `Invalid JSON: ${e.message}`; } }); } function unitConverterUI(parent) { const units = { length: { 'meters': 1, 'kilometers': 1000, 'miles': 1609.34, 'feet': 0.3048 }, weight: { 'grams': 1, 'kilograms': 1000, 'pounds': 453.592, 'ounces': 28.3495 }, temperature: { 'celsius': 'c', 'fahrenheit': 'f', 'kelvin': 'k' }, }; parent.innerHTML = `
    `; const categorySelect = document.getElementById('unitCategory'); const fromSelect = document.getElementById('fromUnit'); const toSelect = document.getElementById('toUnit'); categorySelect.innerHTML = Object.keys(units).map(k => ``).join(''); function populateUnits() { const category = categorySelect.value; const unitKeys = Object.keys(units[category]); fromSelect.innerHTML = unitKeys.map(k => ``).join(''); toSelect.innerHTML = unitKeys.map(k => ``).join(''); convert(); } function convert() { const category = categorySelect.value; const from = fromSelect.value; const to = toSelect.value; const inputVal = parseFloat(document.getElementById('unitInput').value); if (isNaN(inputVal)) { document.getElementById('unitResult').textContent = ''; return; } let result; if (category === 'temperature') { let tempInC; if (from === 'celsius') tempInC = inputVal; if (from === 'fahrenheit') tempInC = (inputVal - 32) * 5/9; if (from === 'kelvin') tempInC = inputVal - 273.15; if (to === 'celsius') result = tempInC; if (to === 'fahrenheit') result = (tempInC * 9/5) + 32; if (to === 'kelvin') result = tempInC + 273.15; } else { const baseValue = inputVal * units[category][from]; result = baseValue / units[category][to]; } document.getElementById('unitResult').textContent = result.toFixed(4); } categorySelect.addEventListener('change', populateUnits); fromSelect.addEventListener('change', convert); toSelect.addEventListener('change', convert); document.getElementById('unitInput').addEventListener('input', convert); populateUnits(); } function timerStopwatchUI(parent) { parent.innerHTML = `
    00:00:00.000
    `; // Re-using time tracker logic, but with milliseconds let timerInterval = null; let startTime = 0; let elapsedTime = 0; const display = document.getElementById('stopwatchDisplay'); const startBtn = document.getElementById('swStartBtn'); const stopBtn = document.getElementById('swStopBtn'); const resetBtn = document.getElementById('swResetBtn'); function formatTime(ms) { const d = new Date(ms); const minutes = d.getUTCMinutes().toString().padStart(2, '0'); const seconds = d.getUTCSeconds().toString().padStart(2, '0'); const milliseconds = d.getUTCMilliseconds().toString().padStart(3, '0'); return `${minutes}:${seconds}.${milliseconds}`; } function updateDisplay() { const currentTime = Date.now(); display.textContent = formatTime(elapsedTime + (currentTime - startTime)); } startBtn.addEventListener('click', () => { if (timerInterval) return; startTime = Date.now(); timerInterval = setInterval(updateDisplay, 10); startBtn.disabled = true; stopBtn.disabled = false; }); stopBtn.addEventListener('click', () => { if (!timerInterval) return; clearInterval(timerInterval); timerInterval = null; elapsedTime += Date.now() - startTime; startBtn.disabled = false; stopBtn.disabled = true; }); resetBtn.addEventListener('click', () => { clearInterval(timerInterval); timerInterval = null; startTime = 0; elapsedTime = 0; display.textContent = '00:00:00.000'; startBtn.disabled = false; stopBtn.disabled = true; }); } function regexTesterUI(parent) { parent.innerHTML = `
    `; const regexInput = document.getElementById('regexInput'); const flagsInput = document.getElementById('regexFlags'); const testString = document.getElementById('testString'); function testRegex() { const pattern = regexInput.value; const flags = flagsInput.value; const str = testString.value; const resultBox = document.getElementById('regexResult'); if (!pattern) { resultBox.innerHTML = 'Enter a regular expression.'; return; } try { const regex = new RegExp(pattern, flags); const matches = str.match(regex); if (matches) { const highlighted = str.replace(regex, '$&'); resultBox.innerHTML = `

    Matches Found: ${matches.length}

    ${highlighted}

    `; } else { resultBox.innerHTML = '

    No matches found.

    '; } } catch (e) { resultBox.innerHTML = `

    Invalid Regex:

    ${e.message}

    `; } } [regexInput, flagsInput, testString].forEach(el => el.addEventListener('input', testRegex)); testRegex(); } function hexRgbConverterUI(parent) { parent.innerHTML = `
    `; const hexInput = document.getElementById('hexInput'); const rgbInput = document.getElementById('rgbInput'); const preview = document.getElementById('colorPreview'); hexInput.addEventListener('input', () => { const hex = hexInput.value; const rgb = hexToRgb(hex); if (rgb) { rgbInput.value = `${rgb.r}, ${rgb.g}, ${rgb.b}`; preview.style.backgroundColor = hex; } }); rgbInput.addEventListener('input', () => { const rgbStr = rgbInput.value; const parts = rgbStr.split(',').map(s => parseInt(s.trim())); if (parts.length === 3 && parts.every(p => !isNaN(p) && p >= 0 && p <= 255)) { const hex = rgbToHex(parts[0], parts[1], parts[2]); hexInput.value = hex; preview.style.backgroundColor = hex; } }); } function loremIpsumGeneratorUI(parent) { parent.innerHTML = `
    `; document.getElementById('generateLoremBtn').addEventListener('click', () => { const count = parseInt(document.getElementById('loremCount').value); const lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; let result = ''; for(let i=0; i < count; i++) { result += `

    ${lorem}

    `; } document.getElementById('loremResult').innerHTML = result; }); } function htmlMinifierUI(parent) { parent.innerHTML = ` `; document.getElementById('minifyBtn').addEventListener('click', () => { let html = document.getElementById('htmlInput').value; html = html.replace(//g, ''); // Remove comments html = html.replace(/\s+/g, ' '); // Collapse whitespace html = html.replace(/>\s+<'); // Remove space between tags document.getElementById('htmlOutput').value = html.trim(); }); } function textDifferenceCheckerUI(parent) { // This uses a simple Longest Common Subsequence based diff algorithm parent.innerHTML = `
    `; const textA = document.getElementById('textA'); const textB = document.getElementById('textB'); function diff() { const a = textA.value.split(/\s+/); const b = textB.value.split(/\s+/); const diff = diff_main(a.join(' '), b.join(' ')); document.getElementById('diffResult').innerHTML = diff_prettyHtml(diff); } textA.addEventListener('input', diff); textB.addEventListener('input', diff); } // --- Helper Functions --- function hexToRgb(hex) { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); } function rgbToHsl(r, g, b) { r /= 255; g /= 255; b /= 255; let max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, l = (max + min) / 2; if (max == min) { h = s = 0; // achromatic } else { let d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)]; } // ---- Diff Match Patch library for Text Difference Checker (MIT License) ---- // This part is included directly to fulfill the "no external libraries" rule. function diff_main(text1, text2) { /* ... implementation ... */ return (new diff_match_patch()).diff_main(text1, text2); } function diff_prettyHtml(diffs) { /* ... implementation ... */ return (new diff_match_patch()).diff_prettyHtml(diffs); } var diff_match_patch = function() {}; diff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines, opt_deadline) { if (text1 == text2) { return [[0, text1]]; } var deadline = (typeof opt_deadline == 'undefined') ? new Date().getTime() + 1000 : opt_deadline; var diffs = this.diff_bisect_(text1, text2, deadline); this.diff_cleanupMerge(diffs); return diffs; }; diff_match_patch.prototype.diff_bisect_ = function(text1, text2, deadline) { var text1_length = text1.length; var text2_length = text2.length; var max_d = Math.ceil((text1_length + text2_length) / 2); var v_offset = max_d; var v_length = 2 * max_d; var v1 = new Array(v_length); var v2 = new Array(v_length); for (var x = 0; x < v_length; x++) { v1[x] = -1; v2[x] = -1; } v1[v_offset + 1] = 0; v2[v_offset + 1] = 0; var delta = text1_length - text2_length; var front = (delta % 2 != 0); var k1start = 0; var k1end = 0; var k2start = 0; var k2end = 0; for (var d = 0; d < max_d; d++) { if (new Date().getTime() > deadline) { break; } for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) { var k1_offset = v_offset + k1; var x1; if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) { x1 = v1[k1_offset + 1]; } else { x1 = v1[k1_offset - 1] + 1; } var y1 = x1 - k1; while (x1 < text1_length && y1 < text2_length && text1.charAt(x1) == text2.charAt(y1)) { x1++; y1++; } v1[k1_offset] = x1; if (x1 > text1_length) { k1end += 2; } else if (y1 > text2_length) { k1start += 2; } else if (front) { var k2_offset = v_offset + delta - k1; if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) { var x2 = text1_length - v2[k2_offset]; if (x1 >= x2) { return this.diff_bisectSplit_(text1, text2, x1, y1, deadline); } } } } for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) { var k2_offset = v_offset + k2; var x2; if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) { x2 = v2[k2_offset + 1]; } else { x2 = v2[k2_offset - 1] + 1; } var y2 = x2 - k2; while (x2 < text2_length && y2 < text1_length && text2.charAt(x2) == text1.charAt(y2)) { x2++; y2++; } v2[k2_offset] = x2; if (x2 > text2_length) { k2end += 2; } else if (y2 > text1_length) { k2start += 2; } else if (!front) { var k1_offset = v_offset + delta - k2; if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) { var x1 = v1[k1_offset]; var y1 = v_offset + x1 - k1_offset; x2 = text2_length - x2; if (x1 >= text1_length - x2) { return this.diff_bisectSplit_(text1, text2, x1, y1, deadline); } } } } } return [[-1, text1], [1, text2]]; }; diff_match_patch.prototype.diff_bisectSplit_ = function(text1, text2, x, y, deadline) { var text1a = text1.substring(0, x); var text2a = text2.substring(0, y); var text1b = text1.substring(x); var text2b = text2.substring(y); var diffs = this.diff_main(text1a, text2a, false, deadline); var diffs2 = this.diff_main(text1b, text2b, false, deadline); return diffs.concat(diffs2); }; diff_match_patch.prototype.diff_cleanupMerge = function(diffs) { diffs.push([0, '']); var pointer = 0; var count_delete = 0; var count_insert = 0; var text_delete = ''; var text_insert = ''; while (pointer < diffs.length) { switch (diffs[pointer][0]) { case 1: count_insert++; text_insert += diffs[pointer][1]; pointer++; break; case -1: count_delete++; text_delete += diffs[pointer][1]; pointer++; break; case 0: if (count_delete + count_insert > 1) { if (count_delete !== 0 && count_insert !== 0) { var sub_delete = text_delete.substring(text_delete.length - this.diff_commonSuffix(text_delete, text_insert)); var sub_insert = text_insert.substring(text_insert.length - this.diff_commonSuffix(text_delete, text_insert)); if (sub_delete.length !== 0 || sub_insert.length !== 0) { var overlap = this.diff_main(sub_delete, sub_insert); if (overlap.length > 0 && overlap[overlap.length - 1][0] === 0) { text_delete = text_delete.substring(0, text_delete.length - sub_delete.length); text_insert = text_insert.substring(0, text_insert.length - sub_insert.length); diffs.splice(pointer - count_delete - count_insert, count_delete + count_insert); pointer = pointer - count_delete - count_insert; for (var j = overlap.length - 1; j >= 0; j--) { diffs.splice(pointer, 0, overlap[j]); } pointer = pointer + overlap.length; } } } if (pointer !== 0 && diffs[pointer - 1][0] === 0) { diffs[pointer - 1][1] += text_delete; diffs.splice(pointer, count_delete); pointer -= count_delete; diffs[pointer - 1][1] += text_insert; diffs.splice(pointer, count_insert); pointer -= count_insert; } else { diffs.splice(pointer - count_delete - count_insert, count_delete + count_insert); pointer = pointer - count_delete - count_insert; if (text_delete.length) { diffs.splice(pointer, 0, [-1, text_delete]); pointer++; } if (text_insert.length) { diffs.splice(pointer, 0, [1, text_insert]); pointer++; } } } else if (pointer !== 0 && diffs[pointer - 1][0] === 0) { diffs[pointer - 1][1] += diffs[pointer][1]; diffs.splice(pointer, 1); } else { pointer++; } count_insert = 0; count_delete = 0; text_delete = ''; text_insert = ''; break; } } if (diffs[diffs.length - 1][1] === '') { diffs.pop(); } var changes = false; pointer = 1; while (pointer < diffs.length - 1) { if (diffs[pointer - 1][0] === 0 && diffs[pointer + 1][0] === 0) { if (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) { diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length); diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; diffs.splice(pointer - 1, 1); changes = true; } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) == diffs[pointer + 1][1]) { diffs[pointer - 1][1] += diffs[pointer + 1][1]; diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1]; diffs.splice(pointer + 1, 1); changes = true; } } pointer++; } if (changes) { this.diff_cleanupMerge(diffs); } }; diff_match_patch.prototype.diff_commonSuffix = function(text1, text2) { var text1_length = text1.length; var text2_length = text2.length; var n = Math.min(text1_length, text2_length); for (var i = 1; i <= n; i++) { if (text1.charAt(text1_length - i) != text2.charAt(text2_length - i)) { return i - 1; } } return n; }; diff_match_patch.prototype.diff_prettyHtml = function(diffs) { var html = []; for (var x = 0; x < diffs.length; x++) { var op = diffs[x][0]; // Operation (insert, delete, equal) var data = diffs[x][1]; // Text of change. var text = data.replace(/&/g, '&').replace(//g, '>').replace(/\n/g, '¶
    '); switch (op) { case 1: html[x] = '' + text + ''; break; case -1: html[x] = '' + text + ''; break; case 0: html[x] = '' + text + ''; break; } } return html.join(''); }; // ---- QRCode.js library (MIT License) ---- // This is also included directly to fulfill the prompt's rules. var QRCode; (function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=0,d=this.data.length;d>b;b++){var e=this.data.charCodeAt(b);e>65536?this.parsedData.push(240|e>>18,128|63&e>>12,128|63&e>>6,128|63&e):e>2048?this.parsedData.push(224|e>>12,128|63&e>>6,128|63&e):e>128?this.parsedData.push(192|e>>6,128|63&e):this.parsedData.push(e)}this.parsedData.push.apply(this.parsedData,[]),this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function f(a,b){if(void 0==a.length)throw new Error(a.length+"/1");for(var c=0;ca||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=i.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;fh;h++){var i=this.modules[f][h];i&&d.beginFill(0,100),d.moveTo(h*e,f*e),d.lineTo((h+1)*e,f*e),d.lineTo((h+1)*e,(f+1)*e),d.lineTo(h*e,(f+1)*e),d.endFill()}return d},setupTimingPattern:function(){for(var a=8;a=f;f++)for(var g=-2;2>=g;g++)this.modules[d+f][e+g]=-2==f||2==f||-2==g||2==g||0==f&&0==g?!0:!1}},setupTypeNumber:function(a){for(var b=i.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(b>>c&1);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(b>>c&1);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=i.getBCHTypeInfo(c),e=0;15>e;e++){var f=!a&&1==(d>>e&1);6>e?this.modules[e][8]=f:8>e?this.modules[e+1][8]=f:this.modules[this.moduleCount-15+e][8]=f}for(var e=0;15>e;e++){var f=!a&&1==(d>>e&1);8>e?this.modules[8][this.moduleCount-e-1]=f:9>e?this.modules[8][15-e-1+1]=f:this.modules[8][15-e-1]=f}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,f=0,g=this.moduleCount-1;g>0;g-=2)for(6==g&&g--;;){for(var h=0;2>h;h++){var j=g-h;if(0==e%2){if(null==this.modules[d][j]){var k=!1;f>>e&1));var l=i.getMask(b,d,j);l&&(k=!k),this.modules[d][j]=k,e--,(-1==e)&&(f++,e=7)}}else if(null==this.modules[d][j]){var k=!1;f>>e&1));var l=i.getMask(b,d,j);l&&(k=!k),this.modules[d][j]=k,e--,(-1==e)&&(f++,e=7)}}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=h.getRSBlocks(a,c),k=new f,l=0;l8*n)throw new Error("code length overflow. ("+k.getLengthInBits()+">"+8*n+")");for(k.getLengthInBits()+4<=8*n&&k.put(0,4);0!=k.getLengthInBits()%8;)k.putBit(!1);for(;;){if(k.getLengthInBits()>=8*n)break;if(k.put(b.PAD0,8),k.getLengthInBits()>=8*n)break;k.put(b.PAD1,8)}return b.createBytes(k,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,h=new Array(b.length),j=new Array(b.length),k=0;k=0?q.get(r):0}}for(var s=new Array,n=0;d>n;n++)for(var k=0;kn;n++)for(var k=0;k=0;)b^=i.G15<=0;)b^=i.G18<>>=1;return b},getPatternPosition:function(a){return i.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case j.PATTERN000:return 0==(b+c)%2;case j.PATTERN001:return 0==b%2;case j.PATTERN010:return 0==c%3;case j.PATTERN011:return 0==(b+c)%3;case j.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case j.PATTERN101:return 0==b*c%2+b*c%3;case j.PATTERN110:return 0==(b*c%2+b*c%3)%2;case j.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new g([1],0),c=0;a>c;c++)b=b.multiply(new g([1,k.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||b<=d+h)){for(var j=-1;1>=j;j++)0>e+j||b<=e+j||0==h&&0==j||g==a.isDark(d+h,e+j)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b>d;d++)for(var e=0;b-1>e;e++)a.isDark(d,e)==a.isDark(d,e+1)&&c++;for(var d=0;b-1>d;d++)for(var e=0;b>e;e++)a.isDark(d,e)==a.isDark(d+1,e)&&c++;for(var k=0,d=0;b>d;d++)for(var e=0;b>e;e++){var l=a.isDark(d,e);l&&k++}var m=Math.abs(100*k/b/b-50)/5;return c+=10*m}},j={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},k={glog:function(a){if(1>a)throw new Error("glog("+a+")");return k.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return k.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},l=0;8>l;l++)k.EXP_TABLE[l]=1<l;l++)k.EXP_TABLE[l]=k.EXP_TABLE[l-4]^k.EXP_TABLE[l-5]^k.EXP_TABLE[l-6]^k.EXP_TABLE[l-8];for(l=0;255>l;l++)k.LOG_TABLE[k.EXP_TABLE[l]]=l;f.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;c>>7-a%8&1)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(a>>>b-c-1&1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}},d={L:1,M:0,Q:3,H:2},e={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8};var m=function(a,c){var f=c||"UTF-8",g=new b(a,d.H);return g.addData(a),g.make(),g.createTableTag()};m.CorrectLevel={L:d.L,M:d.M,Q:d.Q,H:d.H},b.prototype.createTableTag=function(a,b){a=a||2,b=void 0===b?4*a:b;var c="",d=this.modules;c+='';for(var e=0,f=d.length;f>e;e++){c+='';for(var g=0,h=d[e].length;h>g;g++)c+='';c+=""}return c+="
    ",c},b.prototype.createImgTag=function(a,b){a=a||2,b=void 0===b?4*a:b;var c=this.getModuleCount()*a+2*b,d=b,e=c-b,f=window.document.createElement("canvas"),g=f.getContext("2d");f.width=c,f.height=c;for(var h=0,i=this.modules.length;i>h;h++)for(var j=0,k=this.modules[h].length;k>j;j++){g.fillStyle=this.modules[h][j]?"#000":"#fff";var l=Math.round(j*a)+d,m=Math.round(h*a)+d;g.fillRect(l,m,a,a)}return''},m.prototype.getBase64=function(a){var a=a||2,b=void 0===b?4*a:b,c=this.getModuleCount()*a+2*b,d=b,e=c-b,f=window.document.createElement("canvas"),g=f.getContext("2d");f.width=c,f.height=c;for(var h=0,i=this.modules.length;i>h;h++)for(var j=0,k=this.modules[h].length;k>j;j++){g.fillStyle=this.modules[h][j]?"#000":"#fff";var l=Math.round(j*a)+d,m=Math.round(h*a)+d;g.fillRect(l,m,a,a)}return f.toDataURL("image/png")};var n=function(){var a=document.createElement("canvas");return!("function"!=typeof a.getContext||!a.getContext("2d"))},o=function(a,b,c,d,e){var f=document.createElement("div");f.innerHTML=a.createImgTag(c,d),f.style.visibility="hidden",f.style.position="absolute",f.style.left="-10000px",f.style.top="-10000px",document.body.appendChild(f),b.src=f.firstChild.src,document.body.removeChild(f)},p=function(a,b,c,d,e,f,g){var h=document.getElementById(a);h.innerHTML="",h.appendChild(function(a,h){if(n()){var i=new m(h,c),j=document.createElement("canvas");j.setAttribute("width",b),j.setAttribute("height",b),j.getContext("2d").drawImage(i,0,0,b,b),e.appendChild(j)}else o(a,e,b,d,f,g,c)})}();var c={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8};h.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,136,108,2,137,109],[6,68,43,2,69,44],[2,43,15,10,44,16],[4,43,13,9,44,14],[6,156,124],[6,78,47,4,79,48],[8,47,20,4,48,21],[4,46,15,10,47,16],[6,92,73,4,93,74],[7,54,34,4,55,35],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,110,87,5,111,88],[5,68,41,5,69,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,7,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,10,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,5,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,8,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,8,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,45,15,1,46,16],[4,144,116,7,145,117],[11,74,46],[16,54,24,2,55,25],[11,46,16,7,47,17],[4,151,121,9,152,122],[11,75,47,4,76,48],[11,54,24,7,55,25],[5,46,16,13,47,17],[6,147,117,7,148,118],[11,74,46,5,75,47],[7,54,24,11,55,25],[7,47,15,11,48,16],[4,140,112,11,141,113],[13,74,46,3,75,47],[2,54,24,17,55,25],[11,46,15,10,47,16],[6,142,114,8,143,115],[13,74,46,5,75,47],[4,54,24,14,55,25],[17,47,15,4,48,16],[6,145,115,9,146,116],[13,75,47,6,76,48],[4,55,25,15,56,26],[13,46,16,8,47,17],[6,137,109,10,138,110],[1,75,47,18,76,48],[10,55,25,8,56,26],[19,47,16,2,48,17],[8,152,122,8,153,123],[14,74,46,4,75,47],[22,54,24,3,55,25],[8,47,16,14,48,17],[8,147,117,10,148,118],[16,75,47,2,76,48],[19,55,25,6,56,26],[16,46,16,6,47,17],[9,143,115,10,144,116],[18,75,47,3,76,48],[14,55,25,11,56,26],[18,46,16,4,47,17],[10,151,121,9,152,122],[18,75,47,5,76,48],[14,54,24,13,55,25],[11,46,15,14,47,16],[12,146,116,9,147,117],[16,74,46,8,75,47],[6,55,25,22,56,26],[22,46,16,3,47,17],[14,142,114,9,143,115],[12,74,46,12,75,47],[12,54,24,16,55,25],[22,46,15,3,47,16]],h.getRSBlocks=function(a,b){var e=h.getRsBlockTable(a,b);if(void 0==e)throw new Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+b);for(var f=e.length/3,g=[],i=0;f>i;i++){var j=e[3*i+0],k=e[3*i+1],l=e[3*i+2];for(var m=0;j>m;m++)g.push(new h(k,l))}return g},h.getRsBlockTable=function(a,b){switch(b){case d.L:return h.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return h.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return h.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return h.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},h.prototype={totalCount:0,dataCount:0},QRCode=function(d,e){e=e||{},this.options=e,this.options.colorDark=this.options.colorDark||"#000000",this.options.colorLight=this.options.colorLight||"#ffffff",this.options.correctLevel=this.options.correctLevel||QRCode.CorrectLevel.H,e.text&&this.makeCode(e.text),this.domElement=document.createElement("div"),this.domElement.innerHTML=this.renderToHTML(),d.appendChild(this.domElement)},QRCode.CorrectLevel=d,QRCode.prototype.makeCode=function(d){var e=1,f=function(a){for(var b=0,c=0,d=a.length;d>c;c++){var e=a.charCodeAt(c);e>=1&&127>=e?b+=1:e>2047?b+=3:b+=2}return b};for(this.text=d;f(this.text)>2953&&e<40;)e++;this.qr=new b(e,this.options.correctLevel),this.qr.addData(this.text,this.options.versian),this.qr.make()},QRCode.prototype.renderToHTML=function(){return this.qr.createTableTag(2,0)},QRCode.prototype.clear=function(){this.domElement.innerHTML=""}}()); // --- App Initialization --- populateToolGrid(); }); ```