clipboard-parser / index.html
MarkTheArtist's picture
Add 2 files
a0ff15d verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Line-by-Line Clipboard Parser</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>
.clipboard-display {
min-height: 150px;
transition: all 0.3s ease;
}
.progress-bar {
transition: width 0.3s ease;
}
.fade-in {
animation: fadeIn 0.5s;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
</style>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center p-4">
<div class="w-full max-w-2xl bg-white rounded-xl shadow-lg overflow-hidden">
<div class="bg-indigo-600 p-6 text-white">
<div class="flex items-center justify-between">
<h1 class="text-2xl font-bold flex items-center">
<i class="fas fa-clipboard-list mr-3"></i>
Line-by-Line Clipboard Parser
</h1>
<div class="flex space-x-2">
<button id="resetBtn" class="bg-indigo-700 hover:bg-indigo-800 px-4 py-2 rounded-lg text-sm font-medium transition">
<i class="fas fa-redo mr-1"></i> Reset
</button>
</div>
</div>
<p class="mt-2 opacity-90">Paste your multi-line text and cycle through each line</p>
</div>
<div class="p-6">
<div class="mb-6">
<label for="pasteArea" class="block text-gray-700 font-medium mb-2">Paste your text here:</label>
<textarea id="pasteArea" rows="5" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition" placeholder="Paste your multi-line content here..."></textarea>
<div class="flex justify-between mt-2">
<button id="parseBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-6 py-2 rounded-lg font-medium flex items-center transition disabled:opacity-50" disabled>
<i class="fas fa-play mr-2"></i> Start Parsing
</button>
<span id="lineCount" class="text-gray-500 text-sm self-center">0 lines detected</span>
</div>
</div>
<div class="mb-6">
<div class="flex justify-between mb-2">
<span class="text-gray-700 font-medium">Current Clipboard:</span>
<span id="currentLineNum" class="text-indigo-600 font-medium">Line 0/0</span>
</div>
<div class="relative">
<div id="clipboardDisplay" class="clipboard-display bg-gray-50 border border-gray-300 rounded-lg p-4 text-gray-700 whitespace-pre-wrap fade-in">
<div class="absolute inset-0 flex items-center justify-center text-gray-400">
<i class="fas fa-clipboard text-4xl opacity-30"></i>
</div>
</div>
<button id="copyBtn" class="absolute top-2 right-2 bg-gray-200 hover:bg-gray-300 p-2 rounded-md text-gray-700 transition opacity-0 invisible">
<i class="fas fa-copy"></i>
</button>
</div>
<div class="mt-2 flex items-center">
<div class="w-full bg-gray-200 rounded-full h-2.5 mr-2">
<div id="progressBar" class="progress-bar bg-indigo-600 h-2.5 rounded-full" style="width: 0%"></div>
</div>
<span id="progressText" class="text-sm text-gray-500">0%</span>
</div>
</div>
<div class="flex justify-between">
<button id="prevBtn" class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-6 py-2 rounded-lg font-medium flex items-center transition disabled:opacity-50" disabled>
<i class="fas fa-arrow-left mr-2"></i> Previous
</button>
<button id="nextBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-6 py-2 rounded-lg font-medium flex items-center transition disabled:opacity-50" disabled>
Next <i class="fas fa-arrow-right ml-2"></i>
</button>
</div>
</div>
<div class="bg-gray-50 px-6 py-4 border-t border-gray-200">
<div class="flex items-center text-sm text-gray-500">
<i class="fas fa-info-circle mr-2 text-indigo-500"></i>
<span>Click "Next" to copy the next line to clipboard</span>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const pasteArea = document.getElementById('pasteArea');
const parseBtn = document.getElementById('parseBtn');
const nextBtn = document.getElementById('nextBtn');
const prevBtn = document.getElementById('prevBtn');
const resetBtn = document.getElementById('resetBtn');
const copyBtn = document.getElementById('copyBtn');
const clipboardDisplay = document.getElementById('clipboardDisplay');
const lineCount = document.getElementById('lineCount');
const currentLineNum = document.getElementById('currentLineNum');
const progressBar = document.getElementById('progressBar');
const progressText = document.getElementById('progressText');
let lines = [];
let currentLineIndex = -1;
// Update button states based on textarea content
pasteArea.addEventListener('input', function() {
const text = pasteArea.value.trim();
parseBtn.disabled = text.length === 0;
// Count lines for display
const tempLines = text.split('\n').filter(line => line.trim() !== '');
lineCount.textContent = `${tempLines.length} line${tempLines.length !== 1 ? 's' : ''} detected`;
});
// Parse button click handler
parseBtn.addEventListener('click', function() {
const text = pasteArea.value;
lines = text.split('\n').filter(line => line.trim() !== '');
if (lines.length > 0) {
currentLineIndex = -1;
updateUI();
nextBtn.disabled = false;
parseBtn.disabled = true;
pasteArea.disabled = true;
// Show success message
showToast('Text parsed successfully!', 'success');
}
});
// Next button click handler
nextBtn.addEventListener('click', function() {
if (currentLineIndex < lines.length - 1) {
currentLineIndex++;
copyToClipboard(lines[currentLineIndex]);
updateUI();
prevBtn.disabled = currentLineIndex <= 0;
// Show feedback
showToast('Copied to clipboard!', 'success');
}
if (currentLineIndex >= lines.length - 1) {
nextBtn.disabled = true;
}
});
// Previous button click handler
prevBtn.addEventListener('click', function() {
if (currentLineIndex > 0) {
currentLineIndex--;
copyToClipboard(lines[currentLineIndex]);
updateUI();
nextBtn.disabled = false;
// Show feedback
showToast('Copied to clipboard!', 'success');
}
if (currentLineIndex <= 0) {
prevBtn.disabled = true;
}
});
// Reset button click handler
resetBtn.addEventListener('click', function() {
pasteArea.value = '';
lines = [];
currentLineIndex = -1;
parseBtn.disabled = true;
nextBtn.disabled = true;
prevBtn.disabled = true;
pasteArea.disabled = false;
updateUI();
lineCount.textContent = '0 lines detected';
// Show feedback
showToast('Reset complete', 'info');
});
// Copy button click handler
copyBtn.addEventListener('click', function() {
if (currentLineIndex >= 0 && currentLineIndex < lines.length) {
copyToClipboard(lines[currentLineIndex]);
showToast('Copied again!', 'success');
}
});
// Update UI elements
function updateUI() {
if (currentLineIndex >= 0 && currentLineIndex < lines.length) {
clipboardDisplay.innerHTML = `<span class="text-indigo-600 font-medium">Line ${currentLineIndex + 1}:</span>\n${lines[currentLineIndex]}`;
clipboardDisplay.classList.remove('opacity-0');
copyBtn.classList.remove('opacity-0', 'invisible');
} else {
clipboardDisplay.innerHTML = '<div class="absolute inset-0 flex items-center justify-center text-gray-400"><i class="fas fa-clipboard text-4xl opacity-30"></i></div>';
clipboardDisplay.classList.add('opacity-0');
copyBtn.classList.add('opacity-0', 'invisible');
}
currentLineNum.textContent = `Line ${currentLineIndex + 1}/${lines.length}`;
// Update progress
const progress = lines.length > 0 ? ((currentLineIndex + 1) / lines.length) * 100 : 0;
progressBar.style.width = `${progress}%`;
progressText.textContent = `${Math.round(progress)}%`;
}
// Copy text to clipboard
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(function() {
console.log('Copying to clipboard was successful!');
}, function(err) {
console.error('Could not copy text: ', err);
showToast('Failed to copy to clipboard', 'error');
});
}
// Show toast notification
function showToast(message, type) {
const toast = document.createElement('div');
toast.className = `fixed bottom-4 right-4 px-6 py-3 rounded-lg shadow-lg text-white font-medium flex items-center ${type === 'success' ? 'bg-green-500' : type === 'error' ? 'bg-red-500' : 'bg-blue-500'} animate-bounce`;
toast.innerHTML = `
<i class="fas ${type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-circle' : 'fa-info-circle'} mr-2"></i>
${message}
`;
document.body.appendChild(toast);
setTimeout(() => {
toast.classList.remove('animate-bounce');
toast.classList.add('opacity-0', 'transition-opacity', 'duration-300');
setTimeout(() => {
document.body.removeChild(toast);
}, 300);
}, 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=MarkTheArtist/clipboard-parser" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>