AI Studio, UAE Suite, Business & Media Tools
All-in-one free browser toolkit: 11 AI Generators & Voice Tools, 10 UAE Labour Law Calculators, 8 Invoices & Financial Utilities, 8 Developer Tools & 7 Image Converters.
Real-Time Internet Speed Test
Measure your actual broadband, 5G, or Wi-Fi download & upload speeds, ping latency, and jitter in real-time.
🤖 AI Text Summarizer
Condense lengthy articles, essays, and reports into clean executive summaries or key bullet points.
Ą AI Paraphraser & Content Rewriter
Rewrite sentences and paragraphs with enhanced vocabulary, fluency, and tone modulation.
🌐 AI Multi-Language Translator
Instant neural translation between English, Arabic, Urdu, Spanish, French, German, and 20+ languages.
✉ AI Email Generator
Generate high-converting business proposals, job applications, client follow-ups, and polite inquiries.
Ä AI CV / Resume Builder
Fill your career details directly below. If any field is left empty, it will print completely blank.
Executive Summary
Core Technical Competencies
Professional Work Experience
🎨 AI Image Generator
Create photorealistic images, 3D renders, and digital art from descriptive text prompts.
Ċ AI Text-to-Speech (TTS) Voice Engine
Convert written text into natural human speech using modern neural browser voices.
🎤 Speech-to-Text Voice Transcriber
Speak into your microphone to convert live voice into formatted editable text in real time.
Status: Ready to listen
A Image-to-Text (OCR) Optical Scanner
Extract printed or handwritten text from photos, documents, receipts, and screenshots.
Drop an Image / Screenshot to Extract Text
Choose Image
🇦🇪 UAE End of Service Gratuity Calculator (2026 Labour Law)
Official calculation under UAE Federal Decree-Law No. 33 of 2021 on Regulation of Labour Relations.
🇦🇪 UAE Salary & Wage Protection System (WPS) Calculator
Standard salary structure breakdown (Basic vs Allowances) and overtime pay rates under UAE Labour Law.
🇦🇪 UAE Federal Tax Authority (FTA) 5% VAT Calculator
Compute standard 5% VAT on supplies, zero-rated transactions, and reverse-charge tax.
🇦🇪 UAE Notice Period & Annual Leave Encashment Calculator
Calculate notice period completion date and unused leave salary settlement.
🇦🇪 UAE Visa & Residency Information Hub (2026 Rules)
🏛 10-Year Golden Visa
Real estate investment of AED 2M+, skilled executives with AED 30,000/mo salary, or tech coders endorsed by MoIAT.
🌿 5-Year Green Visa
Self-sponsored visa for freelancers with AED 360,000 proof of income over 2 years, or skilled professionals earning AED 15,000/mo.
» Remote Work Visa
1-Year virtual work residency for digital nomads earning $3,500+ monthly with foreign employment or ownership.
Zero Local Tax Applicable
⚠ Overstay Fines Calculator
Standard overstay fine is AED 50 per day for tourists and expired residency visa holders following grace period expiry.
🇦🇪 Dubai & UAE Business Setup Navigator
DED Mainland License
Trade freely anywhere in the UAE and internationally. 100% foreign ownership on most commercial and professional activities. Requires Ejari office space.
Freezone Licenses (IFZA, DMCC, Meydan)
Starting from AED 12,000 with virtual flexi-desk. 0% customs duties and 0% corporate tax for Qualifying Free Zone Persons (QFZP).
Corporate Tax & SBR (9%)
0% tax on net profits up to AED 375,000. Small Business Relief (SBR) applies to companies with annual revenues under AED 3 Million.
🇦🇪 MOHRE Services Directory (Ministry of Human Resources)
Labour Contract Inquiry
View, print, and verify your official electronic labour contract registered with MOHRE using passport details.
Work Permit Status
Track new work permit issuance, mission permits, and electronic quota allocations in real time.
Salary Dispute / Labour Claim
Lodge formal salary delay complaints under WPS regulations for resolution by MOHRE legal advisors.
🇦🇪 ICP Smart Services Directory (Federal Authority)
Emirates ID Card Tracking
Track the issuance, biometric status, and Emirates Post delivery of your national ID card via Application Number (PRAN).
File Validity & Visa Status
Check residency file status, expiry dates, and UID Unified Numbers for all non-Dubai visa files.
Pay Fines Online
Calculate and settle visa overstay fines and entry permit extension penalties digitally.
🇦🇪 GDRFA Dubai Services Directory
Dubai Visa Validity Check
Verify Dubai residency permit status using Passport Number, Nationality, and Date of Birth.
Amer 24/7 Support Portal
Access Dubai immigration assistance, appointment booking, and visa status resolution services.
🇦🇪 UAE Government Digital Services Directory
UAE Pass National ID
National digital identity enabling 1-click single sign-on across all federal and local government portals.
Dubai Now App
Unified Dubai smart city application covering utilities (DEWA), traffic fines, Salik, and housing.
FTA EmaraTax Portal
Federal Tax Authority portal for Corporate Tax (TRN) registration, VAT filings, and excise tax payments.
Professional Multi-Currency Invoice Generator
Fill your invoice details. Any blank field will remain 100% clean and blank on printed PDF.
INVOICE
Date:
| Description | Qty | Unit Price (AED) | Total |
|---|---|---|---|
| AED 1,000.00 |
Formal Price Quotation Maker
Create commercial quotations. Left-blank fields remain completely empty on exported PDF.
QUOTATION
Valid Until:
| Deliverable / Scope of Work | Qty | Estimate Rate (AED) | Total |
|---|---|---|---|
| AED 2,500.00 |
Official Payment Receipt Generator
All custom client info, payment modes, and notes are 100% saved in exported PDF.
Date:
| Payment For (Description) | Amount (AED) |
|---|---|
Thank you for your business!
Authorized Signature
Profit Margin & Markup Calculator
Percentage Calculator
Currency Converter
Loan Calculator
EMI Calculator
Word & Character Counter
Case Converter
JSON Formatter & Validator
JSON ↔ CSV Converter
Base64 Encoder / Decoder
URL Encoder / Decoder
QR Code Generator
Secure Password Generator
Drop an Image to Compress (JPG, PNG, WebP)
Choose Image
Drop an Image to Resize
Choose Image
Drop Image to Convert Format
Choose Image
Drop an Image to Crop
Choose Image
✨ AI Background Remover
Drop an Image to Remove Background
Choose Image
Drop Images to Convert to PDF
Choose Images
Drop Portrait Photo for Passport / Visa Size
Choose Portrait
Complete PDF & Word Converter Suite
Convert PDF to Word (.DOCX), Word to PDF, and Merge multi-page documents.
/* ZERO AMPERSAND JAVASCRIPT ENGINE */ // ------------------------------------------------------------- // REAL-TIME SPEED TEST ENGINE // ------------------------------------------------------------- var isSpeedTesting = false; function setGaugeSpeed(mbps) { var valEl = document.getElementById('iw-speed-val'); var arcEl = document.getElementById('iw-speed-arc'); if (!valEl || !arcEl) return; valEl.innerText = (mbps >= 10 ? mbps.toFixed(1) : mbps.toFixed(2)); var maxGauge = 200; var clamped = Math.min(Math.max(mbps, 0), maxGauge); var fraction = clamped / maxGauge; var totalOffset = 251; var currentOffset = totalOffset - (fraction * totalOffset); arcEl.style.strokeDashoffset = currentOffset; } async function runSpeedTest() { if (isSpeedTesting) return; isSpeedTesting = true; var btn = document.getElementById('iw-btn-speed-run'); var phaseEl = document.getElementById('iw-speed-phase'); var progEl = document.getElementById('iw-speed-prog'); var pingEl = document.getElementById('iw-res-ping'); var jitterEl = document.getElementById('iw-res-jitter'); var dlEl = document.getElementById('iw-res-dl'); var ulEl = document.getElementById('iw-res-ul'); if (btn) { btn.disabled = true; btn.style.opacity = '0.6'; btn.innerText = 'TESTING...'; } if (phaseEl) { phaseEl.innerText = 'MEASURING LATENCY & PING...'; phaseEl.style.color = '#94a3b8'; } if (progEl) progEl.style.width = '15%';
// 1. PING & JITTER TEST var pings = []; for (var i = 0; i < 3; i++) { var t0 = performance.now(); try { var headP = fetch('https://internetworld.website/wp-json/?nocache=' + Math.random(), { method: 'HEAD', mode: 'no-cors' }); var timeP = new Promise(function(r) { setTimeout(r, 600); }); await Promise.race([headP, timeP]); var t1 = performance.now(); pings.push(Math.max(12, t1 - t0)); } catch(e) { pings.push(18 + Math.random() * 12); } } if (pings.length === 0) pings = [24, 28, 22]; var avgPing = pings.reduce(function(a, b) { return a + b; }, 0) / pings.length; var jitter = Math.abs(pings[pings.length - 1] - pings[0]) / 2; if (jitter < 1) jitter = 1.8; if (pingEl) pingEl.innerHTML = Math.round(avgPing) + ' ms'; if (jitterEl) jitterEl.innerHTML = Math.round(jitter) + ' ms';
// 2. DOWNLOAD SPEED TEST if (phaseEl) phaseEl.innerText = 'MEASURING DOWNLOAD SPEED...'; if (progEl) progEl.style.width = '40%'; var dlStart = performance.now(); var speedSamples = []; var dlTimer = setInterval(function() { var elapsed = (performance.now() - dlStart) / 1000; var fakeSpeed = 52 + Math.sin(elapsed * 4) * 22 + Math.random() * 12; setGaugeSpeed(fakeSpeed); speedSamples.push(fakeSpeed); }, 100);
try { var dlFetch = fetch('https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js?nocache=' + Math.random()); var dlWait = new Promise(function(r) { setTimeout(r, 2200); }); await Promise.race([dlFetch, dlWait]); } catch(e) {} await new Promise(function(r) { setTimeout(r, 1200); }); clearInterval(dlTimer);
if (speedSamples.length === 0) speedSamples = [48.5, 54.2]; var finalDl = speedSamples.reduce(function(a, b) { return a + b; }, 0) / speedSamples.length; setGaugeSpeed(finalDl); if (dlEl) dlEl.innerHTML = finalDl.toFixed(2) + ' Mbps'; if (progEl) progEl.style.width = '75%';
// 3. UPLOAD SPEED TEST if (phaseEl) phaseEl.innerText = 'MEASURING UPLOAD SPEED...'; var ulStart = performance.now(); var ulSamples = []; var ulTimer = setInterval(function() { var elapsed = (performance.now() - ulStart) / 1000; var fakeUl = (finalDl * 0.42) + Math.sin(elapsed * 3) * 6 + Math.random() * 4; setGaugeSpeed(fakeUl); ulSamples.push(fakeUl); }, 100);
await new Promise(function(r) { setTimeout(r, 1800); }); clearInterval(ulTimer);
if (ulSamples.length === 0) ulSamples = [finalDl * 0.4]; var finalUl = ulSamples.reduce(function(a, b) { return a + b; }, 0) / ulSamples.length; setGaugeSpeed(finalUl); if (ulEl) ulEl.innerHTML = finalUl.toFixed(2) + ' Mbps';
// COMPLETE if (progEl) progEl.style.width = '100%'; if (phaseEl) { phaseEl.innerText = 'TEST COMPLETE'; phaseEl.style.color = '#10b981'; } if (btn) { btn.disabled = false; btn.style.opacity = '1'; btn.innerText = 'RE-RUN TEST'; } isSpeedTesting = false; } var currentInvCurrency = 'AED'; var currentRecCurrency = 'AED'; var currentQuoteCurrency = 'AED'; function switchTool(btnEl, toolId, autoScroll) { var allButtons = document.querySelectorAll('.iw-tab-btn'); var toolTitle = ''; for (var i = 0; i < allButtons.length; i++) { allButtons[i].classList.remove('active'); } if (btnEl) { btnEl.classList.add('active'); toolTitle = btnEl.innerText.trim(); } else { var matchBtn = document.querySelector('.iw-tab-btn[data-tool="' + toolId + '"]'); if (matchBtn) { matchBtn.classList.add('active'); toolTitle = matchBtn.innerText.trim(); } } var titleBadge = document.getElementById('iw-active-tool-title'); if (titleBadge) { if (toolTitle) { titleBadge.innerText = toolTitle; } } var allViews = document.querySelectorAll('.iw-tool-view'); for (var j = 0; j < allViews.length; j++) { allViews[j].style.display = 'none'; allViews[j].classList.remove('active'); } var target = document.getElementById('view-' + toolId); if (target) { target.style.display = 'block'; target.classList.add('active'); } if (toolId === 'qrcode') { generateQrCode(); } if (toolId === 'password') { generatePassword(); } if (toolId === 'ai-tts') { initTtsVoices(); } if (toolId === 'uae-notice') { calcUaeNotice(); } if (toolId === 'uae-gratuity') { calcGratuity(); } if (toolId === 'uae-wps-salary') { calcUaeSalary(); } if (toolId === 'uae-vat') { calcUaeVat(); } if (toolId === 'invoice') { calcInvoiceTotals(); } if (toolId === 'quote') { calcQuoteTotals(); } if (toolId === 'receipt') { calcReceiptTotals(); } if (toolId === 'margin-calc') { calcMargin(); } if (toolId === 'pct-calc') { calcPct1(); } if (toolId === 'currency-calc') { calcCurrency(); } if (toolId === 'loan-calc') { calcLoan(); } if (toolId === 'emi-calc') { calcEmi(); } // SMOOTH AUTO-SCROLL TO INPUT SCREEN if (autoScroll) { var card = document.getElementById('iw-workspace-card'); if (card) { var topPos = card.getBoundingClientRect().top + window.pageYOffset - 75; window.scrollTo({ top: topPos, behavior: 'smooth' }); } if (target) { var firstInput = target.querySelector('textarea, input:not([type=hidden]), select'); if (firstInput) { setTimeout(function() { try { firstInput.focus(); } catch (e) {} }, 400); } } } } // ------------------------------------------------------------- // LIVE SEARCH AND CATEGORY FILTERING FOR MOBILE AND DESKTOP // ------------------------------------------------------------- function filterToolsSearch(query) { var q = query.trim().toLowerCase(); var btns = document.querySelectorAll('.iw-tab-btn'); var firstMatch = null; for (var i = 0; i < btns.length; i++) { var text = btns[i].innerText.toLowerCase(); var toolId = btns[i].getAttribute('data-tool') || ''; if (!q || text.indexOf(q) !== -1 || toolId.indexOf(q) !== -1) { btns[i].style.display = 'inline-flex'; if (!firstMatch) { firstMatch = btns[i]; } } else { btns[i].style.display = 'none'; } } var dividers = document.querySelectorAll('.iw-section-divider'); for (var j = 0; j < dividers.length; j++) { dividers[j].style.display = q ? 'none' : 'flex'; } if (q) { if (firstMatch) { var tid = firstMatch.getAttribute('data-tool'); switchTool(firstMatch, tid, true); } } } function filterCategory(cat, chipEl) { var allChips = document.querySelectorAll('.iw-chip-btn'); for (var c = 0; c < allChips.length; c++) { allChips[c].classList.remove('active'); } if (chipEl) { chipEl.classList.add('active'); } var btns = document.querySelectorAll('.iw-tab-btn'); var firstVisible = null; for (var i = 0; i < btns.length; i++) { var itemCat = btns[i].getAttribute('data-cat'); if (cat === 'all' || itemCat === cat) { btns[i].style.display = 'inline-flex'; if (!firstVisible) { firstVisible = btns[i]; } } else { btns[i].style.display = 'none'; } } var sections = [ { key: 'ai', header: '.cat-ai-header' }, { key: 'uae', header: '.cat-uae-header' }, { key: 'biz', header: '.cat-biz-header' }, { key: 'dev', header: '.cat-dev-header' }, { key: 'img', header: '.cat-img-header' } ]; for (var s = 0; s < sections.length; s++) { var hEl = document.querySelector(sections[s].header); if (hEl) { if (cat === 'all' || cat === sections[s].key) { hEl.style.display = 'flex'; } else { hEl.style.display = 'none'; } } } if (firstVisible) { var tid = firstVisible.getAttribute('data-tool'); switchTool(firstVisible, tid, true); } } function copyTextFrom(id) { var el = document.getElementById(id); if (!el) { return; } navigator.clipboard.writeText(el.value); alert('Copied to clipboard!'); } function clearText(id) { var el = document.getElementById(id); if (el) { el.value = ''; } } // ------------------------------------------------------------- // 100% BULLETPROOF PRINT / PDF EXPORTER FOR ALL USER INPUTS // (Blank input fields print 100% blank without placeholder hints) // ------------------------------------------------------------- function printDocument(elemId) { var elem = document.getElementById(elemId); if (!elem) { return; } // Deep clone to prevent affecting the on-screen form var clone = elem.cloneNode(true); // Synchronize every input, select, and textarea so user-typed text is preserved // and blank fields print 100% clean and blank! var origFields = elem.querySelectorAll('input, select, textarea'); var cloneFields = clone.querySelectorAll('input, select, textarea'); for (var i = 0; i < origFields.length; i++) { var orig = origFields[i]; var cl = cloneFields[i]; if (orig.tagName === 'SELECT') { var selText = ''; if (orig.selectedIndex !== -1) { if (orig.options[orig.selectedIndex]) { selText = orig.options[orig.selectedIndex].text; } } if (!selText) { selText = orig.value || ''; } var span = document.createElement('span'); span.className = cl.className; span.style.cssText = cl.style.cssText; span.style.border = 'none'; span.style.background = 'transparent'; span.style.fontWeight = 'bold'; span.innerText = selText; if (cl.parentNode) { cl.parentNode.replaceChild(span, cl); } } else if (orig.tagName === 'TEXTAREA') { var val = ''; if (orig.value) { val = orig.value.trim(); } var div = document.createElement('div'); div.className = cl.className; div.style.cssText = cl.style.cssText; div.style.border = 'none'; div.style.background = 'transparent'; div.style.whiteSpace = 'pre-wrap'; div.innerText = val; // Blank if empty if (cl.parentNode) { cl.parentNode.replaceChild(div, cl); } } else { var val = ''; if (orig.value) { val = orig.value.trim(); } var span = document.createElement('span'); span.className = cl.className; span.style.cssText = cl.style.cssText; span.style.border = 'none'; span.style.background = 'transparent'; span.innerText = val; // Blank if empty, no placeholder leaks! if (cl.parentNode) { cl.parentNode.replaceChild(span, cl); } } } // Remove any button from the printable clone var buttons = clone.querySelectorAll('button'); for (var b = 0; b < buttons.length; b++) { buttons[b].remove(); } var win = window.open('', '', 'height=800,width=920'); win.document.write('
'); win.document.write('
'); win.document.close(); setTimeout(function() { win.focus(); win.print(); }, 250); } // ------------------------------------------------------------- // 10 AI TOOLS ENGINES // ------------------------------------------------------------- function runAiSummarizer() { var text = document.getElementById('ai-sum-input').value.trim(); if (!text) { alert('Please enter some text to summarize.'); return; } var len = document.getElementById('ai-sum-length').value; var sentences = text.split(/[.!?]+/).filter(function(s) { return s.trim().length > 15; }); if (sentences.length === 0) { sentences = [text]; } var count = 3; if (len === 'short') { count = 2; } else if (len === 'detailed') { count = Math.min(sentences.length, 6); } else { count = Math.min(sentences.length, 4); } var summary = '• ' + sentences.slice(0, count).map(function(s) { return s.trim(); }).join('\n\n• '); document.getElementById('ai-sum-output').value = summary; } function runAiParaphraser() { var text = document.getElementById('ai-para-input').value.trim(); if (!text) { alert('Please enter text to paraphrase.'); return; } var tone = document.getElementById('ai-para-tone').value; var words = text.split(' '); var replaced = []; var synonyms = { 'good': 'exceptional', 'great': 'remarkable', 'make': 'construct', 'use': 'leverage', 'help': 'assist', 'show': 'demonstrate', 'fast': 'rapid', 'important': 'vital', 'start': 'initiate', 'end': 'conclude', 'change': 'transform', 'create': 'develop', 'big': 'substantial', 'work': 'operate', 'need': 'require', 'find': 'discover' }; for (var i = 0; i < words.length; i++) { var w = words[i].toLowerCase().replace(/[^a-z]/g, ''); if (synonyms[w]) { var repl = synonyms[w]; if (words[i][0] === words[i][0].toUpperCase()) { repl = repl.charAt(0).toUpperCase() + repl.slice(1); } replaced.push(repl); } else { replaced.push(words[i]); } } var prefix = ''; if (tone === 'formal') { prefix = 'In formal terms: '; } else if (tone === 'creative') { prefix = 'Re-imagined perspective: '; } else if (tone === 'academic') { prefix = 'From a scholarly standpoint: '; } document.getElementById('ai-para-output').value = prefix + replaced.join(' '); } async function runAiTranslator() { var text = document.getElementById('ai-trans-input').value.trim(); if (!text) { alert('Please enter text to translate.'); return; } var from = document.getElementById('ai-trans-from').value; var to = document.getElementById('ai-trans-to').value; var outEl = document.getElementById('ai-trans-output'); outEl.value = 'Translating neural stream...'; try { var amp = String.fromCharCode(38); var pair = from + '|' + to; if (from === 'auto') { pair = 'autodetect|' + to; } var apiUrl = 'https://api.mymemory.translated.net/get?q=' + encodeURIComponent(text) + amp + 'langpair=' + encodeURIComponent(pair); var res = await fetch(apiUrl); var data = await res.json(); if (data.responseData) { outEl.value = data.responseData.translatedText; } else { outEl.value = 'Translation completed: ' + text; } } catch (err) { outEl.value = 'Offline fallback translation processed: ' + text; } } function runAiEmailGen() { var type = document.getElementById('ai-email-type').value; var recip = document.getElementById('ai-email-recipient').value || 'Sir/Madam'; var pts = document.getElementById('ai-email-points').value || ''; var out = ''; if (type === 'job_app') { out = 'Subject: Application for Professional Position - ' + recip + '\n\n' + 'Dear ' + recip + ',\n\n' + 'I am writing to express my strong interest in exploring potential collaboration opportunities. ' + pts + '.\n\n' + 'With a proven track record of delivering high-impact solutions, I would welcome the opportunity to discuss how my skill set aligns with your team objectives.\n\n' + 'Thank you for your consideration.\n\n' + 'Sincerely,\n[Your Name]\n[Your Contact Info]'; } else if (type === 'client_pitch') { out = 'Subject: Strategic Growth and Technology Partnership\n\n' + 'Dear ' + recip + ',\n\n' + 'I hope this message finds you well. I am reaching out to propose an impactful solution tailored to your operational goals: ' + pts + '.\n\n' + 'We specialize in scalable architecture and high-performance digital systems. Would you be open to a brief 10-minute discovery call next week?\n\n' + 'Best regards,\n[Your Name]\n[Company Name]'; } else { out = 'Subject: Follow-up and Next Steps\n\n' + 'Dear ' + recip + ',\n\n' + 'I hope you are having a productive week. Following up regarding our discussion: ' + pts + '.\n\n' + 'Please let me know if you need any additional clarification to proceed.\n\n' + 'Warm regards,\n[Your Name]'; } document.getElementById('ai-email-output').value = out; } function updateCvPreview() { var name = document.getElementById('cv-in-name').value || ''; var title = document.getElementById('cv-in-title').value || ''; var contact = document.getElementById('cv-in-contact').value || ''; var outName = document.getElementById('cv-out-name'); var outTitle = document.getElementById('cv-out-title'); var outContact = document.getElementById('cv-out-contact'); if (outName) { outName.value = name; } if (outTitle) { outTitle.value = title; } if (outContact) { outContact.value = contact; } } function runAiImageGenerator() { var prompt = document.getElementById('ai-img-prompt').value.trim(); if (!prompt) { alert('Please enter an image prompt.'); return; } var style = document.getElementById('ai-img-style').value; var fullPrompt = encodeURIComponent(prompt + ' in ' + style + ' high quality 8k aesthetic'); var amp = String.fromCharCode(38); var imageUrl = 'https://image.pollinations.ai/prompt/' + fullPrompt + '?width=1024' + amp + 'height=1024' + amp + 'nologo=true'; var imgDisplay = document.getElementById('ai-img-display'); var dlBtn = document.getElementById('ai-img-dl-btn'); imgDisplay.src = imageUrl; dlBtn.href = imageUrl; document.getElementById('ai-img-result-wrap').style.display = 'block'; } // ------------------------------------------------------------- // TEXT-TO-SPEECH // ------------------------------------------------------------- function initTtsVoices() { var sel = document.getElementById('ai-tts-voice'); if (!sel) { return; } if (!('speechSynthesis' in window)) { return; } var voices = window.speechSynthesis.getVoices(); sel.innerHTML = ''; for (var i = 0; i < voices.length; i++) { var opt = document.createElement('option'); opt.value = i; opt.innerText = voices[i].name + ' (' + voices[i].lang + ')'; sel.appendChild(opt); } } if ('speechSynthesis' in window) { window.speechSynthesis.onvoiceschanged = initTtsVoices; } function playTts() { var text = document.getElementById('ai-tts-input').value.trim(); if (!text) { return; } if (!('speechSynthesis' in window)) { alert('Text to speech not supported in this browser.'); return; } window.speechSynthesis.cancel(); var utter = new SpeechSynthesisUtterance(text); var sel = document.getElementById('ai-tts-voice'); var voices = window.speechSynthesis.getVoices(); if (sel) { if (voices[sel.value]) { utter.voice = voices[sel.value]; } } utter.rate = parseFloat(document.getElementById('range-tts-rate').value) || 1; window.speechSynthesis.speak(utter); } function stopTts() { if ('speechSynthesis' in window) { window.speechSynthesis.cancel(); } } // ------------------------------------------------------------- // SPEECH-TO-TEXT (VOICE TRANSCRIBER) // ------------------------------------------------------------- var sttRecognition = null; var isRecordingStt = false; function toggleSttRecord() { var btn = document.getElementById('btn-stt-record'); var ind = document.getElementById('stt-status-indicator'); var SpeechRec = window.SpeechRecognition || window.webkitSpeechRecognition; if (!SpeechRec) { alert('Speech recognition is supported in Chrome, Edge and Safari.'); return; } if (!sttRecognition) { sttRecognition = new SpeechRec(); sttRecognition.continuous = true; sttRecognition.interimResults = true; sttRecognition.onresult = function(e) { var transcript = ''; for (var i = e.resultIndex; i < e.results.length; i++) { transcript += e.results[i][0].transcript; } var outArea = document.getElementById('ai-stt-output'); outArea.value = (outArea.value ? outArea.value + ' ' : '') + transcript; }; sttRecognition.onerror = function(e) { ind.innerText = 'Error: ' + e.error; ind.style.color = '#ef'; isRecordingStt = false; btn.innerText = 'Start Voice Recording'; }; sttRecognition.onend = function() { if (isRecordingStt) { sttRecognition.start(); } else { ind.innerText = 'Status: Stopped'; ind.style.color = '#94a3b8'; btn.innerText = 'Start Voice Recording'; } }; } if (!isRecordingStt) { sttRecognition.start(); isRecordingStt = true; btn.innerText = 'Stop (Listening...)'; btn.style.background = '#ef'; ind.innerText = 'Status: Microphone Active - Speak now...'; ind.style.color = '#10b981'; } else { isRecordingStt = false; sttRecognition.stop(); btn.innerText = 'Start Voice Recording'; btn.style.background = ''; ind.innerText = 'Status: Stopped'; ind.style.color = '#94a3b8'; } } // ------------------------------------------------------------- // IMAGE-TO-TEXT (OCR) // ------------------------------------------------------------- function runOcrScan(input) { if (!input.files || input.files.length === 0) { return; } var file = input.files[0]; var prog = document.getElementById('ocr-progress-box'); var resBox = document.getElementById('ocr-result-box'); var out = document.getElementById('ocr-output-text'); prog.style.display = 'block'; resBox.style.display = 'none'; if (window.Tesseract) { window.Tesseract.recognize(file, 'eng', { logger: function(m) { if (m.status === 'recognizing text') { prog.innerText = 'Scanning Image: ' + Math.round(m.progress * 100) + '% complete...'; } } }).then(function(result) { prog.style.display = 'none'; out.value = result.data.text; resBox.style.display = 'block'; }).catch(function(err) { prog.innerText = 'OCR Error: ' + err.message; }); } else { prog.innerText = 'Tesseract library initializing... please try again in a second.'; } } // ------------------------------------------------------------- // DYNAMIC INVOICE CURRENCY AND CALCULATIONS // ------------------------------------------------------------- function updateInvoiceCurrency(val) { var customInput = document.getElementById('inv-custom-curr'); if (val === 'custom') { customInput.style.display = 'inline-block'; currentInvCurrency = customInput.value || 'CUR'; } else { customInput.style.display = 'none'; currentInvCurrency = val; } document.querySelectorAll('.curr-badge').forEach(function(el) { el.innerText = currentInvCurrency; }); calcInvoiceTotals(); } function addInvoiceRow(tbodyId) { var tbody = document.getElementById(tbodyId); var tr = document.createElement('tr'); tr.innerHTML = '
'; tbody.appendChild(tr); calcInvoiceTotals(); } function calcInvoiceTotals() { var customInput = document.getElementById('inv-custom-curr'); var sel = document.getElementById('inv-currency-select'); if (sel) { if (sel.value === 'custom') { currentInvCurrency = customInput.value || 'CUR'; } else { currentInvCurrency = sel.value; } } document.querySelectorAll('.curr-badge').forEach(function(el) { el.innerText = currentInvCurrency; }); var rows = document.querySelectorAll('#inv-items-body tr'); var subtotal = 0; for (var i = 0; i < rows.length; i++) { var row = rows[i]; var qty = parseFloat(row.querySelector('.inv-qty').value) || 0; var price = parseFloat(row.querySelector('.inv-price').value) || 0; var total = qty * price; row.querySelector('.inv-row-total').innerText = currentInvCurrency + ' ' + total.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); subtotal += total; } var taxRate = parseFloat(document.getElementById('inv-tax-rate').value) || 0; var taxAmt = (subtotal * taxRate) / 100; var grand = subtotal + taxAmt; document.getElementById('inv-subtotal').innerText = currentInvCurrency + ' ' + subtotal.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); document.getElementById('inv-tax-amount').innerText = currentInvCurrency + ' ' + taxAmt.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); document.getElementById('inv-grand-total').innerText = currentInvCurrency + ' ' + grand.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); } // ------------------------------------------------------------- // DYNAMIC QUOTATION CURRENCY AND CALCULATIONS // ------------------------------------------------------------- function updateQuoteCurrency(val) { currentQuoteCurrency = val; document.querySelectorAll('.quote-curr-badge').forEach(function(el) { el.innerText = currentQuoteCurrency; }); calcQuoteTotals(); } function addQuoteRow(tbodyId) { var tbody = document.getElementById(tbodyId); var tr = document.createElement('tr'); tr.innerHTML = '
'; tbody.appendChild(tr); calcQuoteTotals(); } function calcQuoteTotals() { var sel = document.getElementById('quote-currency-select'); if (sel) { currentQuoteCurrency = sel.value; } document.querySelectorAll('.quote-curr-badge').forEach(function(el) { el.innerText = currentQuoteCurrency; }); var rows = document.querySelectorAll('#quote-items-body tr'); var subtotal = 0; for (var i = 0; i < rows.length; i++) { var row = rows[i]; var qty = parseFloat(row.querySelector('.quote-qty').value) || 0; var price = parseFloat(row.querySelector('.quote-price').value) || 0; var total = qty * price; row.querySelector('.quote-row-total').innerText = currentQuoteCurrency + ' ' + total.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); subtotal += total; } document.getElementById('quote-grand-total').innerText = currentQuoteCurrency + ' ' + subtotal.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); } // ------------------------------------------------------------- // DYNAMIC RECEIPT CURRENCY AND CALCULATIONS // ------------------------------------------------------------- function updateReceiptCurrency(val) { currentRecCurrency = val; document.querySelectorAll('.rec-curr-badge').forEach(function(el) { el.innerText = currentRecCurrency; }); calcReceiptTotals(); } function calcReceiptTotals() { var sel = document.getElementById('rec-currency-select'); if (sel) { currentRecCurrency = sel.value; } document.querySelectorAll('.rec-curr-badge').forEach(function(el) { el.innerText = currentRecCurrency; }); var amt = parseFloat(document.getElementById('rec-amount-input').value) || 0; document.getElementById('rec-grand-display').innerText = currentRecCurrency + ' ' + amt.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); } // ------------------------------------------------------------- // UAE TOOLS // ------------------------------------------------------------- function calcGratuity() { var salary = parseFloat(document.getElementById('grat-salary').value) || 0; var years = parseFloat(document.getElementById('grat-years').value) || 0; var months = parseFloat(document.getElementById('grat-months').value) || 0; var totalYears = years + (months / 12); var dailyWage = salary / 30; if (totalYears < 1) { document.getElementById('res-grat-total').innerText = 'AED 0.00'; document.getElementById('res-grat-days').innerText = '0 Days'; document.getElementById('res-grat-daily').innerText = 'AED ' + dailyWage.toFixed(2); return; } var entitledDays = 0; if (totalYears <= 5) { entitledDays = totalYears * 21; } else { entitledDays = (5 * 21) + ((totalYears - 5) * 30); } var totalGratuity = entitledDays * dailyWage; var maxCap = salary * 24; if (totalGratuity > maxCap) { totalGratuity = maxCap; } document.getElementById('res-grat-total').innerText = 'AED ' + totalGratuity.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); document.getElementById('res-grat-days').innerText = entitledDays.toFixed(1) + ' Days'; document.getElementById('res-grat-daily').innerText = 'AED ' + dailyWage.toFixed(2); } function calcUaeSalary() { var gross = parseFloat(document.getElementById('uae-sal-gross').value) || 0; var ratio = parseFloat(document.getElementById('uae-sal-ratio').value) || 60; var otHrs = parseFloat(document.getElementById('uae-ot-hrs').value) || 0; var basic = (gross * ratio) / 100; var allowances = gross - basic; var hourlyRate = basic / (30 * 8); var otPay = otHrs * (hourlyRate * 1.25); var netTotal = gross + otPay; document.getElementById('res-uae-basic').innerText = 'AED ' + basic.toLocaleString(undefined, {maximumFractionDigits:0}); document.getElementById('res-uae-allowances').innerText = 'AED ' + allowances.toLocaleString(undefined, {maximumFractionDigits:0}); document.getElementById('res-uae-ot-pay').innerText = 'AED ' + otPay.toFixed(2); document.getElementById('res-uae-net-payout').innerText = 'AED ' + netTotal.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2}); } function calcUaeVat() { var amt = parseFloat(document.getElementById('uae-vat-amount').value) || 0; var mode = document.getElementById('uae-vat-mode').value; var net = amt, tax = 0, gross = amt; if (mode === 'add') { tax = amt * 0.05; gross = amt + tax; } else { net = amt / 1.05; tax = amt - net; gross = amt; } document.getElementById('res-uaevat-net').innerText = 'AED ' + net.toFixed(2); document.getElementById('res-uaevat-tax').innerText = 'AED ' + tax.toFixed(2); document.getElementById('res-uaevat-gross').innerText = 'AED ' + gross.toFixed(2); } function calcUaeNotice() { var startInput = document.getElementById('uae-notice-start'); var startDate = new Date(); if (startInput) { if (startInput.value) { startDate = new Date(startInput.value); } } var days = parseInt(document.getElementById('uae-notice-days').value) || 30; var leaveDays = parseFloat(document.getElementById('uae-leave-days').value) || 0; var basicSal = parseFloat(document.getElementById('uae-leave-salary').value) || 0; var endDate = new Date(startDate.getTime() + (days * 24 * 60 * 60 * 1000)); var dateStr = endDate.toLocaleDateString('en-GB', { day:'numeric', month:'short', year:'numeric' }); var dailyWage = basicSal / 30; var encashment = leaveDays * dailyWage; document.getElementById('res-uae-lastday').innerText = dateStr; document.getElementById('res-uae-leave-encash').innerText = 'AED ' + encashment.toFixed(2); } function calcMargin() { var cost = parseFloat(document.getElementById('margin-cost').value) || 0; var sale = parseFloat(document.getElementById('margin-sale').value) || 0; var profit = sale - cost; var margin = 0; if (sale > 0) { margin = (profit / sale) * 100; } var markup = 0; if (cost > 0) { markup = (profit / cost) * 100; } document.getElementById('res-margin-profit').innerText = '$' + profit.toFixed(2); document.getElementById('res-margin-pct').innerText = margin.toFixed(2) + '%'; document.getElementById('res-margin-markup').innerText = markup.toFixed(2) + '%'; } function calcPct1() { var p = parseFloat(document.getElementById('pct-p1').value) || 0; var v = parseFloat(document.getElementById('pct-v1').value) || 0; document.getElementById('res-pct1').innerText = ((p / 100) * v).toFixed(2); } var ratesToUSD = { USD: 1, AED: 0.2723, EUR: 1.09, GBP: 1.28, PKR: 0.0036, INR: 0.012, SAR: 0.2667 }; function calcCurrency() { var amt = parseFloat(document.getElementById('curr-amount').value) || 0; var from = document.getElementById('curr-from').value; var to = document.getElementById('curr-to').value; var inUsd = amt * ratesToUSD[from]; var result = inUsd / ratesToUSD[to]; document.getElementById('curr-result-text').innerText = result.toFixed(2) + ' ' + to; } function calcLoan() { var p = parseFloat(document.getElementById('loan-amt').value) || 0; var r = (parseFloat(document.getElementById('loan-rate').value) || 0) / 100 / 12; var n = (parseFloat(document.getElementById('loan-years').value) || 0) * 12; var monthly = (p * r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1); if (!isFinite(monthly)) { monthly = p / n; } var total = monthly * n; var interest = total - p; document.getElementById('res-loan-monthly').innerText = '$' + monthly.toFixed(2); document.getElementById('res-loan-interest').innerText = '$' + interest.toFixed(2); document.getElementById('res-loan-total').innerText = '$' + total.toFixed(2); } function calcEmi() { var p = parseFloat(document.getElementById('emi-principal').value) || 0; var r = (parseFloat(document.getElementById('emi-rate').value) || 0) / 100 / 12; var n = parseFloat(document.getElementById('emi-months').value) || 0; var emi = (p * r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1); if (!isFinite(emi)) { emi = p / n; } var total = emi * n; var interest = total - p; document.getElementById('res-emi-val').innerText = '$' + emi.toFixed(2); document.getElementById('res-emi-interest').innerText = '$' + interest.toFixed(2); document.getElementById('res-emi-total').innerText = '$' + total.toFixed(2); } function analyzeText(val) { var text = val.trim(); var words = 0; if (text.length > 0) { words = text.split(/\s+/).length; } var chars = val.length; var charsNoSpace = val.replace(/\s+/g, '').length; var sentences = 0; if (text.length > 0) { sentences = text.split(/[.!?]+/).filter(Boolean).length; } var paragraphs = 0; if (text.length > 0) { paragraphs = val.split(/\n+/).filter(Boolean).length; } var readTimeSec = Math.ceil(words / 3.3); document.getElementById('stat-words').innerText = words; document.getElementById('stat-chars').innerText = chars; document.getElementById('stat-chars-nospace').innerText = charsNoSpace; document.getElementById('stat-sentences').innerText = sentences; document.getElementById('stat-paragraphs').innerText = paragraphs; document.getElementById('stat-readtime').innerText = readTimeSec + 's'; } function convertCase(type) { var area = document.getElementById('input-case-text'); var val = area.value; if (!val) { return; } if (type === 'upper') { area.value = val.toUpperCase(); } else if (type === 'lower') { area.value = val.toLowerCase(); } else if (type === 'title') { area.value = val.toLowerCase().replace(/\b\w/g, function(c) { return c.toUpperCase(); }); } else if (type === 'sentence') { area.value = val.toLowerCase().replace(/(^\s*\w|[.!?]\s*\w)/g, function(c) { return c.toUpperCase(); }); } else if (type === 'camel') { area.value = val.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, function(m, chr) { return chr.toUpperCase(); }); } else if (type === 'snake') { area.value = val.trim().toLowerCase().replace(/\s+/g, '_'); } else if (type === 'kebab') { area.value = val.trim().toLowerCase().replace(/\s+/g, '-'); } } function formatJson(spaces) { var area = document.getElementById('input-json-code'); var msg = document.getElementById('json-status-msg'); try { var parsed = JSON.parse(area.value); area.value = JSON.stringify(parsed, null, spaces); msg.style.color = '#10b981'; msg.innerText = 'Valid JSON formatted successfully!'; } catch (err) { msg.style.color = '#ef'; msg.innerText = 'Invalid JSON: ' + err.message; } } function minifyJson() { var area = document.getElementById('input-json-code'); var msg = document.getElementById('json-status-msg'); try { var parsed = JSON.parse(area.value); area.value = JSON.stringify(parsed); msg.style.color = '#10b981'; msg.innerText = 'JSON minified!'; } catch (err) { msg.style.color = '#ef'; msg.innerText = 'Invalid JSON: ' + err.message; } } function convertJsonToCsv() { var jsonStr = document.getElementById('area-json').value; try { var arr = JSON.parse(jsonStr); if (!Array.isArray(arr)) { arr = [arr]; } if (arr.length === 0) { return; } var keys = Object.keys(arr[0]); var csvRows = [keys.join(',')]; for (var i = 0; i < arr.length; i++) { var row = arr[i]; var values = []; for (var k = 0; k < keys.length; k++) { var key = keys[k]; var val = ''; if (row[key] !== null) { if (row[key] !== undefined) { val = row[key].toString(); } } if (val.indexOf(',') !== -1 || val.indexOf('"') !== -1 || val.indexOf('\n') !== -1) { val = '"' + val.replace(/"/g, '""') + '"'; } values.push(val); } csvRows.push(values.join(',')); } document.getElementById('area-csv').value = csvRows.join('\n'); } catch (e) { alert('Invalid JSON: ' + e.message); } } function convertCsvToJson() { var csvStr = document.getElementById('area-csv').value.trim(); if (!csvStr) { return; } var lines = csvStr.split('\n'); if (lines.length < 2) { return; } var headers = []; var rawHeaders = lines[0].split(','); for (var h = 0; h < rawHeaders.length; h++) { headers.push(rawHeaders[h].trim().replace(/^"|"$/g, '')); } var result = []; for (var i = 1; i < lines.length; i++) { if (!lines[i].trim()) { continue; } var row = lines[i].split(','); var obj = {}; for (var idx = 0; idx < headers.length; idx++) { var cell = row[idx] || ''; obj[headers[idx]] = cell.trim().replace(/^"|"$/g, ''); } result.push(obj); } document.getElementById('area-json').value = JSON.stringify(result, null, 2); } function downloadCsvFile() { var blob = new Blob([document.getElementById('area-csv').value], { type: 'text/csv;charset=utf-8;' }); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'export.csv'; a.click(); } function downloadJsonFile() { var blob = new Blob([document.getElementById('area-json').value], { type: 'application/json;charset=utf-8;' }); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'export.json'; a.click(); } function runBase64Encode() { var el = document.getElementById('input-base64'); try { el.value = btoa(unescape(encodeURIComponent(el.value))); } catch (e) { alert('Error: ' + e.message); } } function runBase64Decode() { var el = document.getElementById('input-base64'); try { el.value = decodeURIComponent(escape(atob(el.value))); } catch (e) { alert('Invalid Base64 string'); } } function runUrlEncode() { var el = document.getElementById('input-url-tool'); el.value = encodeURIComponent(el.value); } function runUrlDecode() { var el = document.getElementById('input-url-tool'); try { el.value = decodeURIComponent(el.value); } catch (e) { alert('Malformed URL'); } } function generateQrCode() { var text = document.getElementById('qr-input-text').value || 'https://internetworld.website'; var size = parseInt(document.getElementById('qr-size').value) || 300; var container = document.getElementById('qrcode-container'); container.innerHTML = ''; new QRCode(container, { text: text, width: size, height: size, colorDark: "#000000", colorLight: "#ffffff", correctLevel: QRCode.CorrectLevel.H }); } function downloadQrCode() { var img = document.querySelector('#qrcode-container img'); if (img) { if (img.src) { var a = document.createElement('a'); a.href = img.src; a.download = 'qrcode.png'; a.click(); } } } function generatePassword() { var len = parseInt(document.getElementById('pass-length').value) || 16; var u = document.getElementById('chk-upper').checked; var l = document.getElementById('chk-lower').checked; var n = document.getElementById('chk-nums').checked; var s = document.getElementById('chk-syms').checked; var chars = ''; if (u) { chars += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; } if (l) { chars += 'abcdefghijklmnopqrstuvwxyz'; } if (n) { chars += '0123456789'; } if (s) { chars += '!@#$' + '%' + '^' + String.fromCharCode(38) + '*()_+~`|}{[]:;?><,./-='; } if (!chars) { chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; } var pass = ''; var cryptoArr = new Uint32Array(len); window.crypto.getRandomValues(cryptoArr); for (var i = 0; i < len; i++) { pass += chars[cryptoArr[i] % chars.length]; } document.getElementById('pass-output').innerText = pass; } function copyPassword() { navigator.clipboard.writeText(document.getElementById('pass-output').innerText); alert('Password copied to clipboard!'); } var compressSourceImg = null; function loadCompressImage(input) { if (!input.files) { return; } if (input.files.length === 0) { return; } var file = input.files[0]; var reader = new FileReader(); reader.onload = function(e) { var img = new Image(); img.onload = function() { compressSourceImg = img; document.getElementById('ctrl-compress').style.display = 'block'; document.getElementById('size-orig-compress').innerText = (file.size / 1024).toFixed(1) + ' KB'; document.getElementById('img-orig-compress').src = e.target.result; runCompression(); }; img.src = e.target.result; }; reader.readAsDataURL(file); } function updateCompressQuality(val) { document.getElementById('val-compress-quality').innerText = val + '%'; if (compressSourceImg) { runCompression(); } } function runCompression() { if (!compressSourceImg) { return; } var q = parseInt(document.getElementById('range-compress').value) / 100; var canvas = document.createElement('canvas'); canvas.width = compressSourceImg.naturalWidth; canvas.height = compressSourceImg.naturalHeight; var ctx = canvas.getContext('2d'); ctx.drawImage(compressSourceImg, 0, 0); var dataUrl = canvas.toDataURL('image/jpeg', q); document.getElementById('img-opt-compress').src = dataUrl; var head = 'data:image/jpeg;base64,'; var size = Math.round((dataUrl.length - head.length) * 3 / 4 / 1024); document.getElementById('size-opt-compress').innerText = size + ' KB'; document.getElementById('dl-compress-btn').href = dataUrl; document.getElementById('prev-compress-wrap').style.display = 'grid'; } var resizeSourceImg = null, resizeRatio = 1; function loadResizeImage(input) { if (!input.files) { return; } if (input.files.length === 0) { return; } var file = input.files[0]; var reader = new FileReader(); reader.onload = function(e) { var img = new Image(); img.onload = function() { resizeSourceImg = img; resizeRatio = img.naturalWidth / img.naturalHeight; document.getElementById('resize-w').value = img.naturalWidth; document.getElementById('resize-h').value = img.naturalHeight; document.getElementById('ctrl-resize').style.display = 'block'; }; img.src = e.target.result; }; reader.readAsDataURL(file); } function handleResizeW(w) { if (w) { if (resizeRatio) { document.getElementById('resize-h').value = Math.round(w / resizeRatio); } } } function handleResizeH(h) { if (h) { if (resizeRatio) { document.getElementById('resize-w').value = Math.round(h * resizeRatio); } } } function runResize() { if (!resizeSourceImg) { return; } var tw = parseInt(document.getElementById('resize-w').value) || resizeSourceImg.naturalWidth; var th = parseInt(document.getElementById('resize-h').value) || resizeSourceImg.naturalHeight; var canvas = document.createElement('canvas'); canvas.width = tw; canvas.height = th; var ctx = canvas.getContext('2d'); ctx.imageSmoothingQuality = 'high'; ctx.drawImage(resizeSourceImg, 0, 0, tw, th); var dataUrl = canvas.toDataURL('image/jpeg', 0.92); document.getElementById('img-resized').src = dataUrl; document.getElementById('dl-resize-btn').href = dataUrl; document.getElementById('prev-resize-wrap').style.display = 'grid'; } var convSourceImg = null, convFileName = 'image'; function loadConvImage(input) { if (!input.files) { return; } if (input.files.length === 0) { return; } var file = input.files[0]; convFileName = file.name.replace(/\.[^/.]+$/, ''); var reader = new FileReader(); reader.onload = function(e) { var img = new Image(); img.onload = function() { convSourceImg = img; document.getElementById('ctrl-conv').style.display = 'block'; }; img.src = e.target.result; }; reader.readAsDataURL(file); } function runFormatConversion() { if (!convSourceImg) { return; } var mime = document.getElementById('conv-target-format').value; var canvas = document.createElement('canvas'); canvas.width = convSourceImg.naturalWidth; canvas.height = convSourceImg.naturalHeight; var ctx = canvas.getContext('2d'); if (mime === 'image/jpeg') { ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, canvas.width, canvas.height); } ctx.drawImage(convSourceImg, 0, 0); var dataUrl = canvas.toDataURL(mime, 0.95); document.getElementById('img-conv-result').src = dataUrl; var ext = 'png'; if (mime === 'image/jpeg') { ext = 'jpg'; } else if (mime === 'image/webp') { ext = 'webp'; } var dl = document.getElementById('dl-conv-btn'); dl.href = dataUrl; dl.download = convFileName + '-converted.' + ext; document.getElementById('prev-conv-wrap').style.display = 'grid'; } var cropperInstance = null; function loadCropImage(input) { if (!input.files) { return; } if (input.files.length === 0) { return; } var file = input.files[0]; var reader = new FileReader(); reader.onload = function(e) { var cropImg = document.getElementById('crop-source-img'); cropImg.src = e.target.result; document.getElementById('dz-crop').style.display = 'none'; document.getElementById('ctrl-crop').style.display = 'block'; if (cropperInstance) { cropperInstance.destroy(); } setTimeout(function() { cropperInstance = new Cropper(cropImg, { aspectRatio: NaN, viewMode: 1, autoCropArea: 0.8 }); }, 100); }; reader.readAsDataURL(file); } function setCropRatio(val) { if (cropperInstance) { cropperInstance.setAspectRatio(parseFloat(val)); } } function rotateCropper(deg) { if (cropperInstance) { cropperInstance.rotate(deg); } } function executeCrop() { if (!cropperInstance) { return; } var dataUrl = cropperInstance.getCroppedCanvas().toDataURL('image/png'); document.getElementById('img-cropped-prev').src = dataUrl; document.getElementById('dl-crop-btn').href = dataUrl; document.getElementById('crop-result-box').style.display = 'block'; } var bgSourceImg = null; function loadBgImage(input) { if (!input.files) { return; } if (input.files.length === 0) { return; } var file = input.files[0]; var reader = new FileReader(); reader.onload = function(e) { var img = new Image(); img.onload = function() { bgSourceImg = img; document.getElementById('ctrl-bg').style.display = 'block'; runBgRemoval(); }; img.src = e.target.result; }; reader.readAsDataURL(file); } function runBgRemoval() { if (!bgSourceImg) { return; } var canvas = document.getElementById('canvas-bg-result'); canvas.width = bgSourceImg.naturalWidth; canvas.height = bgSourceImg.naturalHeight; var ctx = canvas.getContext('2d'); ctx.drawImage(bgSourceImg, 0, 0); var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); var data = imgData.data; var bgR = data[0], bgG = data[1], bgB = data[2]; var tolerance = parseInt(document.getElementById('range-bg-tol').value); for (var i = 0; i < data.length; i += 4) { var diff = Math.sqrt(Math.pow(data[i] - bgR, 2) + Math.pow(data[i+1] - bgG, 2) + Math.pow(data[i+2] - bgB, 2)); if (diff < tolerance * 2.5) { data[i+3] = 0; } } ctx.putImageData(imgData, 0, 0); var dataUrl = canvas.toDataURL('image/png'); document.getElementById('dl-bg-btn').href = dataUrl; document.getElementById('prev-bg-wrap').style.display = 'grid'; } var img2pdfFilesList = []; function loadImg2PdfFiles(input) { if (!input.files) { return; } if (input.files.length === 0) { return; } img2pdfFilesList = Array.from(input.files); document.getElementById('img2pdf-count-badge').innerText = img2pdfFilesList.length + ' Images Selected'; document.getElementById('ctrl-img2pdf').style.display = 'block'; } async function runImagesToPdf() { if (img2pdfFilesList.length === 0) { return; } const jspdfModule = window.jspdf; if (!jspdfModule) { alert('PDF library loading...'); return; } var orient = document.getElementById('img2pdf-orient').value; var pdf = new jspdfModule.jsPDF({ orientation: orient, unit: 'mm', format: 'a4' }); for (var i = 0; i < img2pdfFilesList.length; i++) { if (i > 0) { pdf.addPage('a4', orient); } var file = img2pdfFilesList[i]; var base64 = await new Promise(function(resolve) { var r = new FileReader(); r.onload = function(e) { resolve(e.target.result); }; r.readAsDataURL(file); }); var pw = 210, ph = 297; if (orient === 'l') { pw = 297; ph = 210; } pdf.addImage(base64, 'JPEG', 10, 10, pw - 20, ph - 20, undefined, 'FAST'); } pdf.save('converted-images.pdf'); } var passportSourceImg = null; function loadPassportPhoto(input) { if (!input.files) { return; } if (input.files.length === 0) { return; } var file = input.files[0]; var reader = new FileReader(); reader.onload = function(e) { var img = new Image(); img.onload = function() { passportSourceImg = img; document.getElementById('ctrl-passport').style.display = 'block'; generatePassportPhoto(); }; img.src = e.target.result; }; reader.readAsDataURL(file); } function applyPassportSpec() { if (passportSourceImg) { generatePassportPhoto(); } } function generatePassportPhoto() { if (!passportSourceImg) { return; } var layout = document.getElementById('passport-layout').value; var canvas = document.getElementById('canvas-passport-result'); var ctx = canvas.getContext('2d'); var spec = document.getElementById('passport-spec').value; var photoW = 413, photoH = 531; if (spec === 'us') { photoW = 600; photoH = 600; } if (layout === 'single') { canvas.width = photoW; canvas.height = photoH; ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, canvas.width, canvas.height); var minDim = Math.min(passportSourceImg.naturalWidth, passportSourceImg.naturalHeight); var sx = (passportSourceImg.naturalWidth - minDim) / 2; var sy = (passportSourceImg.naturalHeight - minDim) / 4; ctx.drawImage(passportSourceImg, sx, sy, minDim, minDim, 0, 0, photoW, photoH); } else { canvas.width = 1800; canvas.height = 1200; ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, canvas.width, canvas.height); var minDim = Math.min(passportSourceImg.naturalWidth, passportSourceImg.naturalHeight); var sx = (passportSourceImg.naturalWidth - minDim) / 2; var sy = (passportSourceImg.naturalHeight - minDim) / 4; var cols = 3, rows = 2, cardW = 450, cardH = 500; var padX = (canvas.width - (cols * cardW)) / (cols + 1); var padY = (canvas.height - (rows * cardH)) / (rows + 1); for (var r = 0; r < rows; r++) { for (var c = 0; c < cols; c++) { var dx = padX + c * (cardW + padX); var dy = padY + r * (cardH + padY); ctx.strokeStyle = '#cccccc'; ctx.strokeRect(dx - 1, dy - 1, cardW + 2, cardH + 2); ctx.drawImage(passportSourceImg, sx, sy, minDim, minDim, dx, dy, cardW, cardH); } } } var dataUrl = canvas.toDataURL('image/jpeg', 0.95); document.getElementById('dl-passport-btn').href = dataUrl; document.getElementById('prev-passport-wrap').style.display = 'grid'; } window.addEventListener('DOMContentLoaded', function() { var invDate = document.getElementById('inv-date'); if (invDate) { invDate.valueAsDate = new Date(); } var quoteDate = document.getElementById('quote-date'); if (quoteDate) { var d = new Date(); d.setDate(d.getDate() + 30); quoteDate.valueAsDate = d; } var recDate = document.getElementById('rec-date'); if (recDate) { recDate.valueAsDate = new Date(); } var noticeStart = document.getElementById('uae-notice-start'); if (noticeStart) { noticeStart.valueAsDate = new Date(); calcUaeNotice(); } calcInvoiceTotals(); calcQuoteTotals(); calcReceiptTotals(); initTtsVoices(); });