Drop PDF files here
or click to browse
Maximum 20MB per file
`;
return new Blob([htmlTemplate], { type: 'text/html' });
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
readFileAsArrayBuffer(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(new Error('Failed to read file'));
reader.readAsArrayBuffer(file);
});
}
handleError(fileObj, message) {
const progressBar = document.getElementById(`progress-${fileObj.id}`);
const downloadBtn = document.getElementById(`download-${fileObj.id}`);
if (progressBar) progressBar.style.width = '0%';
if (downloadBtn) {
downloadBtn.textContent = 'Failed';
downloadBtn.disabled = true;
}
this.showStatus(`✗ ${fileObj.file.name}: ${message}`, 'error');
}
downloadFile(fileObj) {
if (!fileObj.converted || !fileObj.downloadUrl) return;
const link = document.createElement('a');
link.href = fileObj.downloadUrl;
link.download = fileObj.fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
downloadAll() {
const convertedFiles = this.files.filter(f => f.converted);
if (convertedFiles.length === 0) {
this.showStatus('No converted files to download', 'error');
return;
}
this.showStatus(`Downloading ${convertedFiles.length} files...`, 'success');
convertedFiles.forEach((fileObj, index) => {
setTimeout(() => {
this.downloadFile(fileObj);
}, index * 300);
});
}
removeFile(fileId) {
const fileObj = this.files.find(f => f.id === fileId);
if (fileObj && fileObj.downloadUrl) {
URL.revokeObjectURL(fileObj.downloadUrl);
}
this.files = this.files.filter(f => f.id !== fileId);
const element = document.getElementById(`file-${fileId}`);
if (element) element.remove();
if (this.files.length === 0) {
document.getElementById('processingArea').style.display = 'none';
}
}
clearAll() {
this.files.forEach(fileObj => {
if (fileObj.downloadUrl) {
URL.revokeObjectURL(fileObj.downloadUrl);
}
});
this.files = [];
document.getElementById('fileList').innerHTML = '';
document.getElementById('processingArea').style.display = 'none';
this.hideStatus();
}
showProcessingArea() {
document.getElementById('processingArea').style.display = 'block';
}
formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
showStatus(message, type) {
const statusEl = document.getElementById('statusMessage');
statusEl.textContent = message;
statusEl.className = `status-message status-${type}`;
statusEl.style.display = 'block';
if (type === 'success') {
setTimeout(() => this.hideStatus(), 4000);
} else {
setTimeout(() => this.hideStatus(), 6000);
}
}
hideStatus() {
const statusEl = document.getElementById('statusMessage');
if (statusEl) statusEl.style.display = 'none';
}
}
// Initialize the converter when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
// Wait a bit for PDF.js to load, then initialize
setTimeout(() => {
window.pdfConverter = new PDFToHTMLConverter();
}, 500);
});// Fallback initialization on window load
window.addEventListener('load', () => {
if (!window.pdfConverter) {
setTimeout(() => {
window.pdfConverter = new PDFToHTMLConverter();
}, 200);
}
});