document.addEventListener('DOMContentLoaded', function() { // Initialize empty results array const scanResults = []; // Camera and storage access variables let cameraStream = null; let isCameraActive = false; const cameraVideo = document.getElementById('cameraStream'); const captureCanvas = document.getElementById('captureCanvas'); const placeholderImage = document.getElementById('placeholderImage'); const uploadButton = document.getElementById('uploadButton'); const captureButton = document.getElementById('captureButton'); const textPreview = document.querySelector('.text-preview'); // Tab switching functionality const tabButtons = document.querySelectorAll('.tab-button'); const tabContents = document.querySelectorAll('.tab-content'); // Initialize tabs - show home tab by default document.getElementById('home').classList.add('active'); tabButtons.forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const tabId = this.getAttribute('data-tab'); // Remove active class from all tabs and buttons tabButtons.forEach(btn => btn.classList.remove('active')); tabContents.forEach(content => content.classList.remove('active')); // Add active class to clicked tab and button this.classList.add('active'); document.getElementById(tabId).classList.add('active'); // Stop camera when leaving home tab if (tabId !== 'home') { stopCamera(); } }); }); // Initialize the first tab as active const initialTab = document.querySelector('.tab-button[data-tab="home"]'); if (initialTab) { initialTab.classList.add('active'); } // Request camera permission and initialize camera async function initializeCamera() { try { // Stop any existing camera stream stopCamera(); // Try environment camera first, then user camera, then any camera const constraints = [ { video: { facingMode: 'environment' } }, { video: { facingMode: 'user' } }, { video: true } ]; let stream = null; for (const constraint of constraints) { try { stream = await navigator.mediaDevices.getUserMedia(constraint); break; } catch (err) { console.warn(`Camera constraint failed:`, constraint, err); continue; } } if (!stream) { throw new Error('No camera available'); } cameraStream = stream; cameraVideo.srcObject = stream; isCameraActive = true; // Wait for video to load metadata await new Promise((resolve) => { cameraVideo.onloadedmetadata = resolve; }); return true; } catch (error) { console.error('Error accessing camera:', error); alert('Camera access is required for capturing images. Please allow camera permissions and ensure a camera is connected.'); isCameraActive = false; return false; } } // Stop camera stream function stopCamera() { if (cameraStream) { const tracks = cameraStream.getTracks(); tracks.forEach(track => { track.stop(); }); cameraStream = null; } isCameraActive = false; cameraVideo.style.display = 'none'; placeholderImage.style.display = 'block'; } // Capture image from camera async function captureImage() { // Ensure camera is initialized if (!isCameraActive) { const initialized = await initializeCamera(); if (!initialized) { alert('Failed to access camera. Please check permissions.'); return; } } try { // Show camera stream and hide placeholder placeholderImage.style.display = 'none'; cameraVideo.style.display = 'block'; // Small delay to let camera stabilize await new Promise(resolve => setTimeout(resolve, 200)); // Set canvas dimensions to match video captureCanvas.width = cameraVideo.videoWidth || 640; captureCanvas.height = cameraVideo.videoHeight || 480; const context = captureCanvas.getContext('2d'); // Draw video frame to canvas context.drawImage(cameraVideo, 0, 0, captureCanvas.width, captureCanvas.height); // Get image data URL const imageData = captureCanvas.toDataURL('image/jpeg', 0.8); // Process the captured image processCapturedImage(imageData); // Stop camera after capture stopCamera(); } catch (error) { console.error('Error capturing image:', error); alert('Failed to capture image. Please try again.'); stopCamera(); } } // Process captured image and show results function processCapturedImage(imageData) { // Show image preview const imagePreviewContainer = document.querySelector('.image-preview-container'); const previewImage = document.getElementById('preview-image'); previewImage.src = imageData; imagePreviewContainer.style.display = 'block'; // Store and simulate OCR results with sample data const result = { type: 'scan', content: 'The quick brown fox jumps over the lazy dog\n1234567890', confidence: '98.7%', timestamp: new Date().toISOString(), imageData: imageData }; scanResults.push(result); // Show results with image preview and processed text textPreview.innerHTML = `

Scan Results

The quick brown fox jumps over the lazy dog

1234567890

Confidence: 98.7%

Processed at ${new Date().toLocaleTimeString()}

`; // Add processed text section after results const processedTextSection = document.createElement('div'); processedTextSection.className = 'processed-text-section'; processedTextSection.innerHTML = `

Processed Text

The quick brown fox jumps over the lazy dog 1234567890
`; textPreview.appendChild(processedTextSection); } // Capture button functionality captureButton.addEventListener('click', async function() { await captureImage(); }); // Upload button functionality uploadButton.addEventListener('click', function() { // Create file input for upload const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = 'image/*'; fileInput.style.display = 'none'; document.body.appendChild(fileInput); fileInput.addEventListener('change', function(e) { const file = e.target.files[0]; if (file) { // Stop camera if active stopCamera(); // Show upload processing textPreview.innerHTML = `

Processing image...

`; const reader = new FileReader(); reader.onload = function(event) { setTimeout(() => { // Show image preview const imagePreviewContainer = document.querySelector('.image-preview-container'); const previewImage = document.getElementById('preview-image'); previewImage.src = event.target.result; imagePreviewContainer.style.display = 'block'; // Store and simulate OCR results with sample data const result = { type: 'document', content: 'Invoice #INV-2023-0456\nClient: Acme Corporation\nTotal: $1,245.00\nDue Date: 12/15/2023', timestamp: new Date().toISOString(), imageData: event.target.result }; scanResults.push(result); // Show results with image preview and processed text textPreview.innerHTML = `

Document Analysis

Invoice #INV-2023-0456

Client: Acme Corporation

Total: $1,245.00

Due Date: 12/15/2023

Processed at ${new Date().toLocaleTimeString()}

`; // Add processed text section after results const processedTextSection = document.createElement('div'); processedTextSection.className = 'processed-text-section'; processedTextSection.innerHTML = `

Processed Text

Invoice #INV-2023-0456 Client: Acme Corporation Total: $1,245.00 Due Date: 12/15/2023
`; textPreview.appendChild(processedTextSection); }, 1500); }; reader.readAsDataURL(file); } }); fileInput.click(); }); // Function to close image preview window.closeImagePreview = function() { const imagePreviewContainer = document.querySelector('.image-preview-container'); imagePreviewContainer.style.display = 'none'; }; }); // Add scanning animation styles const style = document.createElement('style'); style.textContent = ` .scanning-animation { position: relative; height: 100%; overflow: hidden; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 15px; } .scan-line { position: absolute; top: 0; left: 0; width: 100%; height: 2px; background: var(--primary-color); animation: scan 1.5s linear infinite; } @keyframes scan { 0% { top: 0; opacity: 0; } 10% { opacity: 1; } 90% { opacity: 1; } 100% { top: 100%; opacity: 0; } } .result-header { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; } .result-icon { width: 30px; height: 30px; background: var(--secondary-color); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: var(--primary-color); } .result-content { margin: 10px 0; } .result-meta { margin-top: 8px; font-size: 0.8rem; color: var(--light-text); } .confidence { background: rgba(37, 99, 235, 0.1); padding: 4px 8px; border-radius: 4px; } .upload-animation { position: relative; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 15px; } .progress-bar { width: 80%; height: 8px; background: var(--border-color); border-radius: 4px; overflow: hidden; } .progress { height: 100%; width: 0; background: linear-gradient(90deg, var(--primary-color), var(--primary-dark)); animation: progress 2.5s ease-out forwards; } @keyframes progress { 0% { width: 0; } 100% { width: 100%; } } `; document.head.appendChild(style);