universefile / index.html
nkp's picture
Add 3 files
65063f7 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Universal File Converter</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.dropzone {
border: 2px dashed #3b82f6;
transition: all 0.3s ease;
}
.dropzone.active {
border-color: #10b981;
background-color: #f0f9ff;
}
.progress-bar {
transition: width 0.3s ease;
}
.file-icon {
font-size: 2rem;
}
.file-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.tooltip {
visibility: hidden;
opacity: 0;
transition: opacity 0.3s;
}
.has-tooltip:hover .tooltip {
visibility: visible;
opacity: 1;
}
.download-options {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.download-options.active {
max-height: 300px;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8">
<header class="text-center mb-10">
<h1 class="text-4xl font-bold text-blue-600 mb-2">Universal File Converter</h1>
<p class="text-gray-600">Auto-detect file types and convert to your desired format</p>
</header>
<div class="max-w-4xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-8">
<div id="dropzone" class="dropzone rounded-lg p-10 text-center cursor-pointer">
<div class="flex flex-col items-center justify-center">
<i class="fas fa-cloud-upload-alt text-blue-500 text-5xl mb-4"></i>
<h3 class="text-xl font-semibold text-gray-700 mb-2">Drag & Drop files here</h3>
<p class="text-gray-500 mb-4">or click to browse your files</p>
<input type="file" id="fileInput" class="hidden" multiple>
<button id="browseBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg transition duration-300">
Select Files
</button>
</div>
</div>
</div>
<div id="fileList" class="max-w-4xl mx-auto mb-8 hidden">
<h2 class="text-2xl font-semibold text-gray-800 mb-4">Selected Files</h2>
<div id="filesContainer" class="space-y-3"></div>
</div>
<div id="conversionOptions" class="max-w-4xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-8 hidden">
<h2 class="text-2xl font-semibold text-gray-800 mb-6">Conversion Options</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label class="block text-gray-700 font-medium mb-2">Output Format</label>
<div class="grid grid-cols-2 gap-3">
<button data-format="pdf" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-blue-100 border border-gray-200 rounded-lg p-3 transition">
<i class="fas fa-file-pdf text-red-500 mr-2"></i> PDF
</button>
<button data-format="excel" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-green-100 border border-gray-200 rounded-lg p-3 transition">
<i class="fas fa-file-excel text-green-600 mr-2"></i> Excel
</button>
<button data-format="word" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-blue-100 border border-gray-200 rounded-lg p-3 transition">
<i class="fas fa-file-word text-blue-600 mr-2"></i> Word
</button>
<button data-format="xml" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-orange-100 border border-gray-200 rounded-lg p-3 transition">
<i class="fas fa-file-code text-orange-500 mr-2"></i> XML
</button>
<button data-format="text" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-gray-200 border border-gray-200 rounded-lg p-3 transition">
<i class="fas fa-file-alt text-gray-600 mr-2"></i> Text
</button>
<button data-format="csv" class="format-btn flex items-center justify-center bg-gray-100 hover:bg-green-100 border border-gray-200 rounded-lg p-3 transition">
<i class="fas fa-file-csv text-green-700 mr-2"></i> CSV
</button>
</div>
</div>
<div>
<label class="block text-gray-700 font-medium mb-2">Options</label>
<div class="space-y-3">
<div class="flex items-center">
<input type="checkbox" id="preserveLayout" class="rounded text-blue-600 mr-2">
<label for="preserveLayout">Preserve original layout</label>
</div>
<div class="flex items-center">
<input type="checkbox" id="mergeFiles" class="rounded text-blue-600 mr-2">
<label for="mergeFiles">Merge all files into one</label>
</div>
<div class="flex items-center">
<input type="checkbox" id="compressOutput" class="rounded text-blue-600 mr-2">
<label for="compressOutput">Compress output files</label>
</div>
</div>
</div>
</div>
<div class="flex justify-center">
<button id="convertBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-8 rounded-lg transition duration-300 flex items-center">
<i class="fas fa-exchange-alt mr-2"></i> Convert Files
</button>
</div>
</div>
<div id="progressSection" class="max-w-4xl mx-auto mb-8 hidden">
<h2 class="text-2xl font-semibold text-gray-800 mb-4">Conversion Progress</h2>
<div class="bg-white rounded-xl shadow-md overflow-hidden p-6">
<div id="progressContainer" class="space-y-4"></div>
</div>
</div>
<div id="downloadSection" class="max-w-4xl mx-auto hidden">
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-semibold text-gray-800">Download Converted Files</h2>
<button id="toggleDownloadOptions" class="text-blue-600 hover:text-blue-800 font-medium flex items-center">
<i class="fas fa-cog mr-2"></i> Download Options
</button>
</div>
<div id="downloadOptions" class="download-options bg-white rounded-lg p-4 mb-4">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-gray-700 font-medium mb-2">Download Quality</label>
<select id="downloadQuality" class="w-full border border-gray-300 rounded-lg p-2">
<option value="high">High Quality (Recommended)</option>
<option value="medium">Medium Quality</option>
<option value="low">Low Quality (Smaller Size)</option>
</select>
</div>
<div>
<label class="block text-gray-700 font-medium mb-2">Download Method</label>
<select id="downloadMethod" class="w-full border border-gray-300 rounded-lg p-2">
<option value="individual">Individual Files</option>
<option value="zip">ZIP Archive</option>
</select>
</div>
</div>
<div class="mt-4 flex justify-end">
<button id="applyDownloadOptions" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg">
Apply Options
</button>
</div>
</div>
<div id="downloadContainer" class="grid grid-cols-1 md:grid-cols-2 gap-4"></div>
<div class="mt-6 flex justify-center">
<button id="downloadAllBtn" class="bg-green-600 hover:bg-green-700 text-white font-medium py-3 px-6 rounded-lg flex items-center">
<i class="fas fa-download mr-2"></i> Download All Files
</button>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM elements
const dropzone = document.getElementById('dropzone');
const fileInput = document.getElementById('fileInput');
const browseBtn = document.getElementById('browseBtn');
const fileList = document.getElementById('fileList');
const filesContainer = document.getElementById('filesContainer');
const conversionOptions = document.getElementById('conversionOptions');
const convertBtn = document.getElementById('convertBtn');
const progressSection = document.getElementById('progressSection');
const progressContainer = document.getElementById('progressContainer');
const downloadSection = document.getElementById('downloadSection');
const downloadContainer = document.getElementById('downloadContainer');
const formatBtns = document.querySelectorAll('.format-btn');
const toggleDownloadOptions = document.getElementById('toggleDownloadOptions');
const downloadOptions = document.getElementById('downloadOptions');
const downloadAllBtn = document.getElementById('downloadAllBtn');
const applyDownloadOptions = document.getElementById('applyDownloadOptions');
let selectedFiles = [];
let selectedFormat = null;
let convertedFiles = [];
let downloadQuality = 'high';
let downloadMethod = 'individual';
// Event listeners
browseBtn.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', handleFileSelect);
// Drag and drop events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropzone.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, unhighlight, false);
});
function highlight() {
dropzone.classList.add('active');
}
function unhighlight() {
dropzone.classList.remove('active');
}
dropzone.addEventListener('drop', handleDrop, false);
// Format selection
formatBtns.forEach(btn => {
btn.addEventListener('click', function() {
formatBtns.forEach(b => b.classList.remove('border-blue-500', 'bg-blue-50'));
this.classList.add('border-blue-500', 'bg-blue-50');
selectedFormat = this.getAttribute('data-format');
});
});
// Convert button
convertBtn.addEventListener('click', startConversion);
// Download options toggle
toggleDownloadOptions.addEventListener('click', function() {
downloadOptions.classList.toggle('active');
});
// Apply download options
applyDownloadOptions.addEventListener('click', function() {
downloadQuality = document.getElementById('downloadQuality').value;
downloadMethod = document.getElementById('downloadMethod').value;
showAlert('Download options updated successfully', 'success');
downloadOptions.classList.remove('active');
});
// Download all files
downloadAllBtn.addEventListener('click', function() {
if (downloadMethod === 'zip') {
// Simulate downloading a ZIP archive
const zipName = `converted_files_${new Date().getTime()}.zip`;
showAlert(`Preparing ZIP archive: ${zipName}`, 'success');
// In a real app, this would trigger the actual ZIP download
setTimeout(() => {
showAlert(`Downloading ${zipName}`, 'success');
}, 1500);
} else {
// Simulate downloading all files individually
showAlert('Starting download of all files', 'success');
// In a real app, this would trigger all individual downloads
document.querySelectorAll('.download-btn').forEach(btn => {
setTimeout(() => {
btn.click();
}, 300);
});
}
});
// File handling functions
function handleFileSelect(e) {
const files = e.target.files || e.dataTransfer.files;
processFiles(files);
}
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
processFiles(files);
}
function processFiles(files) {
selectedFiles = Array.from(files);
if (selectedFiles.length > 0) {
fileList.classList.remove('hidden');
conversionOptions.classList.remove('hidden');
filesContainer.innerHTML = '';
selectedFiles.forEach((file, index) => {
const fileCard = createFileCard(file, index);
filesContainer.appendChild(fileCard);
});
}
}
function createFileCard(file, index) {
const fileType = getFileType(file.name);
const icon = getFileIcon(fileType);
const fileSize = formatFileSize(file.size);
const card = document.createElement('div');
card.className = 'file-card bg-white rounded-lg border border-gray-200 p-4 flex items-center justify-between transition duration-300';
card.innerHTML = `
<div class="flex items-center">
<div class="file-icon text-3xl mr-4 ${getFileIconColor(fileType)}">
${icon}
</div>
<div>
<h3 class="font-medium text-gray-800 truncate max-w-xs">${file.name}</h3>
<p class="text-sm text-gray-500">${fileType.toUpperCase()}${fileSize}</p>
</div>
</div>
<div class="flex items-center">
<button class="remove-file-btn text-red-500 hover:text-red-700 p-2 rounded-full" data-index="${index}">
<i class="fas fa-times"></i>
</button>
</div>
`;
// Add remove file functionality
card.querySelector('.remove-file-btn').addEventListener('click', function() {
const index = parseInt(this.getAttribute('data-index'));
selectedFiles.splice(index, 1);
if (selectedFiles.length === 0) {
fileList.classList.add('hidden');
conversionOptions.classList.add('hidden');
} else {
// Re-render file list
filesContainer.innerHTML = '';
selectedFiles.forEach((file, idx) => {
filesContainer.appendChild(createFileCard(file, idx));
});
}
});
return card;
}
function getFileType(filename) {
const extension = filename.split('.').pop().toLowerCase();
const fileTypes = {
// Documents
'pdf': 'pdf',
'doc': 'word',
'docx': 'word',
'txt': 'text',
'rtf': 'text',
'odt': 'word',
// Spreadsheets
'xls': 'excel',
'xlsx': 'excel',
'csv': 'csv',
'ods': 'excel',
// Data
'xml': 'xml',
'json': 'json',
// Images
'jpg': 'image',
'jpeg': 'image',
'png': 'image',
'gif': 'image',
'svg': 'image',
'webp': 'image',
// Archives
'zip': 'archive',
'rar': 'archive',
'7z': 'archive',
'tar': 'archive',
'gz': 'archive'
};
return fileTypes[extension] || 'file';
}
function getFileIcon(fileType) {
const icons = {
'pdf': '<i class="fas fa-file-pdf"></i>',
'word': '<i class="fas fa-file-word"></i>',
'excel': '<i class="fas fa-file-excel"></i>',
'csv': '<i class="fas fa-file-csv"></i>',
'text': '<i class="fas fa-file-alt"></i>',
'xml': '<i class="fas fa-file-code"></i>',
'json': '<i class="fas fa-file-code"></i>',
'image': '<i class="fas fa-file-image"></i>',
'archive': '<i class="fas fa-file-archive"></i>',
'file': '<i class="fas fa-file"></i>'
};
return icons[fileType] || icons['file'];
}
function getFileIconColor(fileType) {
const colors = {
'pdf': 'text-red-500',
'word': 'text-blue-600',
'excel': 'text-green-600',
'csv': 'text-green-700',
'text': 'text-gray-600',
'xml': 'text-orange-500',
'json': 'text-yellow-500',
'image': 'text-purple-500',
'archive': 'text-yellow-600',
'file': 'text-gray-500'
};
return colors[fileType] || colors['file'];
}
function 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];
}
// Conversion functions
function startConversion() {
if (!selectedFormat) {
showAlert('Please select an output format', 'error');
return;
}
if (selectedFiles.length === 0) {
showAlert('No files selected for conversion', 'error');
return;
}
// Show progress section
progressSection.classList.remove('hidden');
progressContainer.innerHTML = '';
// Hide download section if shown
downloadSection.classList.add('hidden');
// Reset converted files array
convertedFiles = [];
// Simulate conversion process
selectedFiles.forEach((file, index) => {
const progressItem = document.createElement('div');
progressItem.className = 'bg-gray-50 rounded-lg p-4';
progressItem.innerHTML = `
<div class="flex justify-between items-center mb-2">
<div class="flex items-center truncate">
<span class="font-medium text-gray-700 truncate max-w-xs">${file.name}</span>
<div class="has-tooltip relative ml-2">
<i class="fas fa-info-circle text-blue-500"></i>
<div class="tooltip absolute z-10 w-48 bg-gray-800 text-white text-xs rounded p-2 -left-24 -top-10">
Converting to ${selectedFormat.toUpperCase()}
</div>
</div>
</div>
<span class="text-sm font-medium text-gray-500" id="progressPercent-${index}">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="progressBar-${index}" class="progress-bar h-2.5 rounded-full bg-blue-600" style="width: 0%"></div>
</div>
`;
progressContainer.appendChild(progressItem);
// Simulate progress
simulateConversionProgress(index, file);
});
}
function simulateConversionProgress(index, file) {
let progress = 0;
const interval = setInterval(() => {
progress += Math.floor(Math.random() * 10) + 5;
if (progress >= 100) {
progress = 100;
clearInterval(interval);
// Store converted file info
const originalName = file.name;
const newName = originalName.substring(0, originalName.lastIndexOf('.')) + '.' + selectedFormat;
convertedFiles.push({
originalName,
newName,
format: selectedFormat,
size: Math.floor(file.size * (0.7 + Math.random() * 0.3)) // Random size for demo
});
// When all files are converted
if (convertedFiles.length === selectedFiles.length) {
setTimeout(showDownloadOptions, 1000);
}
}
document.getElementById(`progressBar-${index}`).style.width = `${progress}%`;
document.getElementById(`progressPercent-${index}`).textContent = `${progress}%`;
}, 200);
}
function showDownloadOptions() {
downloadSection.classList.remove('hidden');
downloadContainer.innerHTML = '';
convertedFiles.forEach((file, index) => {
const downloadCard = document.createElement('div');
downloadCard.className = 'bg-white rounded-lg border border-gray-200 p-4 flex items-center justify-between';
downloadCard.innerHTML = `
<div class="flex items-center truncate">
<div class="mr-3 text-2xl ${getFileIconColor(file.format)}">
${getFileIcon(file.format)}
</div>
<div class="truncate">
<h3 class="font-medium text-gray-800 truncate">${file.newName}</h3>
<p class="text-sm text-gray-500">${formatFileSize(file.size)} • From ${file.originalName}</p>
</div>
</div>
<div class="flex space-x-2">
<button class="preview-btn text-blue-600 hover:text-blue-800 p-2 rounded-full" data-index="${index}">
<i class="fas fa-eye"></i>
</button>
<button class="download-btn bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition duration-300" data-index="${index}">
<i class="fas fa-download mr-2"></i> Download
</button>
</div>
`;
downloadContainer.appendChild(downloadCard);
});
// Add preview functionality
document.querySelectorAll('.preview-btn').forEach(btn => {
btn.addEventListener('click', function() {
const index = parseInt(this.getAttribute('data-index'));
const file = convertedFiles[index];
showAlert(`Previewing ${file.newName} (simulated)`, 'success');
});
});
// Add download functionality
document.querySelectorAll('.download-btn').forEach(btn => {
btn.addEventListener('click', function() {
const index = parseInt(this.getAttribute('data-index'));
const file = convertedFiles[index];
// In a real app, this would download the actual converted file
// Here we're just simulating the download
showAlert(`Downloading ${file.newName} (${downloadQuality} quality)`, 'success');
});
});
}
function showAlert(message, type) {
const alert = document.createElement('div');
alert.className = `fixed top-4 right-4 px-6 py-3 rounded-lg shadow-lg text-white font-medium ${
type === 'error' ? 'bg-red-500' : 'bg-green-500'
}`;
alert.textContent = message;
document.body.appendChild(alert);
setTimeout(() => {
alert.classList.add('opacity-0', 'transition-opacity', 'duration-500');
setTimeout(() => alert.remove(), 500);
}, 3000);
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=nkp/universefile" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>