Title-verifier / static /script.js
danmagino's picture
Upload 24 files
e9a924c verified
Raw
History Blame Contribute Delete
8.59 kB
// Initialize Lucide icons
lucide.createIcons();
// Global variables
let uploadedImageData = null;
let uploadedMetadata = null;
let currentThreshold = 0.5;
let showGradCAM = false;
// DOM elements
const fileInput = document.getElementById('fileInput');
const metadataInput = document.getElementById('metadataInput');
const uploadArea = document.getElementById('uploadArea');
const uploadContent = document.getElementById('uploadContent');
const uploadedContent = document.getElementById('uploadedContent');
const uploadedImage = document.getElementById('uploadedImage');
const metadataStatus = document.getElementById('metadataStatus');
const analyzeBtn = document.getElementById('analyzeBtn');
const analyzingBtn = document.getElementById('analyzingBtn');
const thresholdSlider = document.getElementById('threshold');
const thresholdValue = document.getElementById('thresholdValue');
const resultsSection = document.getElementById('resultsSection');
const readyState = document.getElementById('readyState');
const toggleGradCAM = document.getElementById('toggleGradCAM');
const gradcamContent = document.getElementById('gradcamContent');
const predictionResult = document.getElementById('predictionResult');
const confidenceScore = document.getElementById('confidenceScore');
const confidenceBar = document.getElementById('confidenceBar');
const processingTime = document.getElementById('processingTime');
const gradcamOriginal = document.getElementById('gradcamOriginal');
const gradcamHeatmap = document.getElementById('gradcamHeatmap');
const metadataSection = document.getElementById('metadataSection');
const metadataContent = document.getElementById('metadataContent');
// Threshold slider handler
thresholdSlider.addEventListener('input', function() {
currentThreshold = parseFloat(this.value);
thresholdValue.textContent = Math.round(currentThreshold * 100) + '%';
thresholdSlider.setAttribute('aria-valuenow', currentThreshold);
document.getElementById('thresholdDisplay').textContent = `Threshold: ${Math.round(currentThreshold * 100)}%`;
});
// File upload handlers
fileInput.addEventListener('change', handleFileUpload);
metadataInput.addEventListener('change', handleMetadataUpload);
// Drag and drop handlers
uploadArea.addEventListener('dragenter', handleDrag);
uploadArea.addEventListener('dragover', handleDrag);
uploadArea.addEventListener('dragleave', handleDragLeave);
uploadArea.addEventListener('drop', handleDrop);
// Analyze button handler
analyzeBtn.addEventListener('click', analyzeDocument);
// Grad-CAM toggle
toggleGradCAM.addEventListener('click', function() {
showGradCAM = !showGradCAM;
if (showGradCAM) {
gradcamContent.classList.remove('hidden');
this.querySelector('span').textContent = 'Hide Analysis';
} else {
gradcamContent.classList.add('hidden');
this.querySelector('span').textContent = 'Show Analysis';
}
});
function handleDrag(e) {
e.preventDefault();
e.stopPropagation();
uploadArea.classList.add('drag-over');
}
function handleDragLeave(e) {
e.preventDefault();
e.stopPropagation();
uploadArea.classList.remove('drag-over');
}
function handleDrop(e) {
e.preventDefault();
e.stopPropagation();
uploadArea.classList.remove('drag-over');
const files = e.dataTransfer.files;
for (let file of files) {
if (file.type.startsWith('image/')) {
processFile(file, 'image');
} else if (file.name.endsWith('.xlsx')) {
processFile(file, 'metadata');
}
}
}
function handleFileUpload(e) {
const file = e.target.files[0];
if (file) {
processFile(file, 'image');
}
}
function handleMetadataUpload(e) {
const file = e.target.files[0];
if (file) {
processFile(file, 'metadata');
}
}
function processFile(file, type) {
if (type === 'image') {
// Validate image
if (!file.type.startsWith('image/')) {
alert('Please select an image file (JPG, JPEG, PNG)');
return;
}
if (file.size > 10 * 1024 * 1024) {
alert('Image file size must be less than 10MB');
return;
}
// Display uploaded image
const reader = new FileReader();
reader.onload = function(e) {
uploadedImageData = e.target.result;
uploadedImage.src = uploadedImageData;
// Update UI
uploadContent.classList.add('hidden');
uploadedContent.classList.remove('hidden');
uploadArea.classList.add('uploaded');
analyzeBtn.classList.remove('hidden');
// Hide results
resultsSection.classList.add('hidden');
readyState.classList.remove('hidden');
};
reader.readAsDataURL(file);
fileInput.file = file; // Store file for analysis
} else if (type === 'metadata') {
// Validate metadata
if (!file.name.endsWith('.xlsx')) {
alert('Please select an XLSX file for metadata');
return;
}
if (file.size > 10 * 1024 * 1024) {
alert('Metadata file size must be less than 10MB');
return;
}
// Store metadata file
uploadedMetadata = file;
metadataStatus.classList.remove('hidden');
metadataStatus.textContent = `Metadata file uploaded: ${file.name}`;
}
}
function analyzeDocument() {
if (!uploadedImageData || !fileInput.file) {
alert('Please upload an image first');
return;
}
// Show analyzing state
analyzeBtn.classList.add('hidden');
analyzingBtn.classList.remove('hidden');
// Prepare form data
const formData = new FormData();
formData.append('file', fileInput.file);
formData.append('threshold', currentThreshold);
if (uploadedMetadata) {
formData.append('metadata', uploadedMetadata);
}
// Send to Flask backend
fetch('/analyze', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.error) {
alert(data.error);
throw new Error(data.error);
}
// Update results
confidenceScore.textContent = data.confidence + '%';
processingTime.textContent = data.processing_time + 'ms';
confidenceBar.style.width = data.confidence + '%';
confidenceBar.className = `h-3 rounded-full transition-all duration-500 ${data.is_authentic ? 'bg-green-500' : 'bg-red-500'}`;
// Update prediction
predictionResult.className = `p-4 sm:p-6 rounded-xl border-2 ${data.is_authentic ? 'bg-green-50 border-green-200' : 'bg-red-50 border-red-200'}`;
predictionResult.innerHTML = `
<div class="flex items-center space-x-3">
<i data-lucide="${data.is_authentic ? 'check-circle' : 'alert-triangle'}" class="h-6 sm:h-8 w-6 sm:w-8 ${data.is_authentic ? 'text-green-600' : 'text-red-600'}"></i>
<div>
<h4 class="text-base sm:text-lg font-semibold ${data.is_authentic ? 'text-green-800' : 'text-red-800'}">
Document is ${data.is_authentic ? 'Authentic' : 'Possibly Fake'}
</h4>
<p class="text-xs sm:text-sm ${data.is_authentic ? 'text-green-600' : 'text-red-600'}">
${data.is_authentic ? 'High similarity to verified land title documents in our database.' : 'Low similarity suggests potential forgery or document type mismatch.'}
</p>
</div>
</div>
`;
// Update Grad-CAM
gradcamOriginal.src = data.original_image;
gradcamHeatmap.src = data.heatmap_image;
// Update metadata
if (data.metadata) {
metadataSection.classList.remove('hidden');
metadataContent.textContent = data.metadata;
} else {
metadataSection.classList.add('hidden');
}
// Show results
readyState.classList.add('hidden');
resultsSection.classList.remove('hidden');
// Reset buttons
analyzingBtn.classList.add('hidden');
analyzeBtn.classList.remove('hidden');
// Re-initialize icons
lucide.createIcons();
})
.catch(error => {
console.error('Error:', error);
alert('Error analyzing document');
analyzingBtn.classList.add('hidden');
analyzeBtn.classList.remove('hidden');
});
}