Manga_OCR / static /ui /scripts.js
Drag2121's picture
tesseract
a91e387
// Debug helpers
function debug(message) {
console.log(`[Debug] ${message}`);
}
document.addEventListener('DOMContentLoaded', function() {
// Debug print
debug("UI initialized");
// Get DOM elements
const urlForm = document.getElementById('url-form');
const pdfForm = document.getElementById('pdf-form');
const tabButtons = document.querySelectorAll('.tab-btn');
const tabPanes = document.querySelectorAll('.tab-pane');
const fileInput = document.getElementById('pdf-file');
const fileNameDisplay = document.querySelector('.file-name');
const resultsContainer = document.getElementById('results');
const resultsGrid = document.querySelector('.results-grid');
const progressContainer = document.querySelector('.progress-container');
const progressText = document.querySelector('.progress-text');
const progressFill = document.querySelector('.progress-fill');
const tryNowBtn = document.getElementById('try-now-btn');
// Handle Try Now button click
if (tryNowBtn) {
tryNowBtn.addEventListener('click', function() {
const translatorSection = document.getElementById('translator');
translatorSection.scrollIntoView({ behavior: 'smooth' });
});
}
// Handle tab switching
tabButtons.forEach(button => {
button.addEventListener('click', function() {
// Get the target tab
const tabId = this.getAttribute('data-tab');
// Remove active class from all tabs and panes
tabButtons.forEach(btn => btn.classList.remove('active'));
tabPanes.forEach(pane => pane.classList.remove('active'));
// Add active class to current tab and pane
this.classList.add('active');
document.getElementById(tabId).classList.add('active');
debug(`Switched to tab: ${tabId}`);
});
});
// Handle file input change
if (fileInput) {
fileInput.addEventListener('change', function() {
if (this.files.length > 0) {
const fileName = this.files[0].name;
fileNameDisplay.textContent = fileName;
debug(`Selected file: ${fileName}`);
} else {
fileNameDisplay.textContent = 'No file chosen';
}
});
}
// Handle URL form submission
if (urlForm) {
urlForm.addEventListener('submit', async function(e) {
e.preventDefault();
// Get form data
const url = document.getElementById('manga-url').value;
const srcLang = document.getElementById('url-src-lang').value;
const tgtLang = document.getElementById('url-tgt-lang').value;
debug(`Submitting URL form with url=${url}, srcLang=${srcLang}, tgtLang=${tgtLang}`);
// Show progress bar
resultsGrid.innerHTML = '';
progressFill.style.width = '0%';
progressText.textContent = 'Preparing translation...';
progressContainer.style.display = 'block';
// Submit form data to API
try {
// Create the request body
const requestBody = {
url: url,
src_lang: srcLang,
tgt_lang: tgtLang,
translator: 'google'
};
// Call the API with streaming response
await handleTranslation('/translate/url', requestBody);
} catch (error) {
debug(`Error during URL translation: ${error}`);
showError("An error occurred during translation. Please try again.");
}
});
}
// Handle PDF form submission
if (pdfForm) {
pdfForm.addEventListener('submit', async function(e) {
e.preventDefault();
// Check if a file is selected
if (!fileInput.files[0]) {
showError("Please select a PDF file first.");
return;
}
// Get form data
const file = fileInput.files[0];
const srcLang = document.getElementById('pdf-src-lang').value;
const tgtLang = document.getElementById('pdf-tgt-lang').value;
debug(`Submitting PDF form with file=${file.name}, srcLang=${srcLang}, tgtLang=${tgtLang}`);
// Show progress bar
resultsGrid.innerHTML = '';
progressFill.style.width = '0%';
progressText.textContent = 'Preparing PDF translation...';
progressContainer.style.display = 'block';
// Create FormData
const formData = new FormData();
formData.append('file', file);
formData.append('src_lang', srcLang);
formData.append('tgt_lang', tgtLang);
formData.append('translator', 'google');
// Submit form data to API
try {
// Call the translation endpoint with streaming response
await handlePdfTranslation('/translate/pdf', formData);
} catch (error) {
debug(`Error during PDF translation: ${error}`);
showError("An error occurred during translation. Please try again.");
}
});
}
// Function to handle URL translation with streaming response
async function handleTranslation(endpoint, requestBody) {
try {
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let receivedImages = 0;
let totalImages = 5; // Default assumption, will be updated if more info is available
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
// Process the streamed response
const text = decoder.decode(value, { stream: true });
const lines = text.split('\n\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.substring(6));
processTranslationUpdate(data, receivedImages, totalImages);
if (data.status === 'success' && data.image_url) {
receivedImages++;
updateProgress(receivedImages, totalImages);
} else if (data.status === 'complete') {
progressContainer.style.display = 'none';
}
} catch (e) {
debug(`Error parsing JSON: ${e}`);
}
}
}
}
} catch (error) {
debug(`Error during translation: ${error}`);
showError("An error occurred during translation. Please try again.");
}
}
// Function to handle PDF translation with streaming response
async function handlePdfTranslation(endpoint, formData) {
try {
const response = await fetch(endpoint, {
method: 'POST',
body: formData
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let receivedImages = 0;
let totalImages = 5; // Default assumption, will be updated if more info is available
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
// Process the streamed response
const text = decoder.decode(value, { stream: true });
const lines = text.split('\n\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.substring(6));
processTranslationUpdate(data, receivedImages, totalImages);
if (data.status === 'success' && data.image_url) {
receivedImages++;
updateProgress(receivedImages, totalImages);
} else if (data.status === 'complete') {
progressContainer.style.display = 'none';
}
} catch (e) {
debug(`Error parsing JSON: ${e}`);
}
}
}
}
} catch (error) {
debug(`Error during translation: ${error}`);
showError("An error occurred during translation. Please try again.");
}
}
// Process translation updates
function processTranslationUpdate(data, currentImage, totalImages) {
debug(`Received update: ${JSON.stringify(data)}`);
if (data.status === 'error') {
showError(data.message || "An error occurred during translation.");
progressContainer.style.display = 'none';
return;
}
if (data.status === 'processing') {
progressText.textContent = data.message || `Processing image ${currentImage + 1}/${totalImages}...`;
return;
}
if (data.status === 'success' && data.image_url) {
// Add the translated image to the results
addImageToResults(data.image_url);
}
if (data.status === 'complete') {
progressText.textContent = 'Translation complete!';
progressFill.style.width = '100%';
setTimeout(() => {
progressContainer.style.display = 'none';
}, 1000);
}
}
// Update progress bar
function updateProgress(current, total) {
const percentage = Math.min(Math.round((current / total) * 100), 100);
progressFill.style.width = `${percentage}%`;
progressText.textContent = `Processing page ${current}/${total}...`;
}
// Add an image to the results grid
function addImageToResults(imageUrl) {
// Create result card
const resultCard = document.createElement('div');
resultCard.className = 'result-card';
// Create image
const img = document.createElement('img');
img.className = 'result-image';
img.src = imageUrl;
img.alt = 'Translated Image';
img.loading = 'lazy';
// Create actions div
const actionsDiv = document.createElement('div');
actionsDiv.className = 'result-actions';
// Create download link
const downloadLink = document.createElement('a');
downloadLink.href = imageUrl;
downloadLink.download = 'translated-' + imageUrl.split('/').pop();
downloadLink.className = 'btn';
downloadLink.innerHTML = '<i class="fas fa-download"></i> Download';
// Create view link
const viewLink = document.createElement('a');
viewLink.href = imageUrl;
viewLink.target = '_blank';
viewLink.className = 'btn';
viewLink.innerHTML = '<i class="fas fa-external-link-alt"></i> View';
// Append elements
actionsDiv.appendChild(downloadLink);
actionsDiv.appendChild(viewLink);
resultCard.appendChild(img);
resultCard.appendChild(actionsDiv);
resultsGrid.appendChild(resultCard);
}
// Show error message
function showError(message) {
resultsGrid.innerHTML = `
<div class="error-message">
<i class="fas fa-exclamation-circle"></i>
<p>${message}</p>
</div>
`;
}
// Create placeholder image on page load for visual preview
function createPlaceholderImage() {
const placeholderUrl = '/static/ui/placeholder.png';
debug('Creating placeholder UI example');
// Only add placeholder if no results yet
if (resultsGrid.children.length === 0) {
addImageToResults(placeholderUrl);
addImageToResults(placeholderUrl);
}
}
// Optional: Add placeholder images for demo purposes
// Uncomment to enable placeholders on page load
// createPlaceholderImage();
});