Posts

Made a Small WebApp to Organize My Posts Images [Code Inside]

3 comments·0 reblogs
ahmadmanga
75
·
0 views
·
min-read

Lately, I've been posting way more screenshots in my Gaming Community articles than before, and the time I spent copying and pasting the URLs is getting unbearable...

I'm uploading the images through INLEO. If I upload the images one-by-one the time in-between piles up, but if I upload in bulk, the URLs drop as soon as each image finishes uploading, so I can't control their order. I used to do it this way in the past few weeks...

The other day, I asked AI to code me something that gives me the images as small thumbnails. It allows me to order them via Drag-and-Drop. The app should give me the new order as the output I can copy. Also, it works offline!!

The version I currently use doesn't keep the aspect ratio of the images, and I also need to put the images in a table after I order them, so I might update the code to provide these features, but I decided to share the current version here.

I feel so proud!

Image from thread


This code was generated with GLM 4.7 via Venice.ai:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <title>Image Grid Reorder Tool</title> 
    <!-- SortableJS for Drag and Drop --> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.2/Sortable.min.js"></script> 
    <style> 
        body { 
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; 
            padding: 20px; 
            background-color: #f4f4f9; 
            color: #333; 
            max-width: 1200px; 
            margin: 0 auto; 
        } 
 
        .section { 
            background: white; 
            padding: 20px; 
            border-radius: 8px; 
            box-shadow: 0 2px 10px rgba(0,0,0,0.1); 
            margin-bottom: 20px; 
        } 
 
        h2 { margin-top: 0; font-size: 1.2rem; } 
 
        textarea { 
            width: 100%; 
            height: 100px; 
            padding: 10px; 
            border: 1px solid #ccc; 
            border-radius: 4px; 
            box-sizing: border-box; 
            font-family: monospace; 
            resize: vertical; 
        } 
 
        .controls { 
            display: flex; 
            align-items: center; 
            gap: 20px; 
            margin-top: 10px; 
        } 
 
        input[type="number"] { 
            width: 60px; 
            padding: 5px; 
        } 
 
        button { 
            padding: 10px 20px; 
            background-color: #007bff; 
            color: white; 
            border: none; 
            border-radius: 4px; 
            cursor: pointer; 
            font-weight: bold; 
        } 
 
        button:hover { 
            background-color: #0056b3; 
        } 
 
        #image-grid { 
            display: grid; 
            gap: 15px; 
            margin-top: 20px; 
            min-height: 100px; 
            border: 2px dashed #eee; 
            padding: 10px; 
        } 
 
        .grid-item { 
            background: #eee; 
            border-radius: 4px; 
            overflow: hidden; 
            cursor: grab; 
            position: relative; 
            aspect-ratio: 1 / 1; 
            display: flex; 
            align-items: center; 
            justify-content: center; 
            border: 1px solid #ddd; 
        } 
 
        .grid-item:active { 
            cursor: grabbing; 
        } 
 
        .grid-item img { 
            width: 100%; 
            height: 100%; 
            object-fit: cover; 
            display: block; 
        } 
 
        .sortable-ghost { 
            opacity: 0.3; 
        } 
 
        #output-text { 
            height: 150px; 
            background-color: #f8f9fa; 
        } 
 
        .copy-btn { 
            margin-top: 10px; 
            background-color: #28a745; 
        } 
    </style> 
</head> 
<body> 
 
    <div class="section"> 
 
 
        <h2>[Input] Paste Text with Image URLs</h2> 
        <textarea id="input-text" placeholder="Paste text here... The app will find all URLs ending in jpg, png, webp, etc."></textarea> 
         
        <div class="controls"> 
            <div> 
                <label for="grid-columns">Columns: </label> 
                <input type="number" id="grid-columns" value="4" min="1" max="12"> 
             
 
</div> 
 
            <button id="generate-btn">[Generate Blocks Button]</button> 
        </div> 
    </div> 
 
    <div class="section"> 
 
 
        <h2>[The Image Section] Drag to Reorder</h2> 
        <div id="image-grid"> 
 
</div> 
 
    </div> 
 
    <div class="section"> 
 
 
        <h2>[The Output section]</h2> 
        <textarea id="output-text" readonly placeholder="Reordered URLs will appear here..."></textarea> 
        <button class="copy-btn" onclick="copyOutput()">Copy to Clipboard</button> 
     
 
</div> 
 
 
    <script> 
        const inputText = document.getElementById('input-text'); 
        const outputText = document.getElementById('output-text'); 
        const imageGrid = document.getElementById('image-grid'); 
        const generateBtn = document.getElementById('generate-btn'); 
        const gridColumns = document.getElementById('grid-columns'); 
 
        let sortableInstance = null; 
 
        // Initialize SortableJS 
        function initSortable() { 
            if (sortableInstance) sortableInstance.destroy(); 
            sortableInstance = new Sortable(imageGrid, { 
                animation: 150, 
                ghostClass: 'sortable-ghost', 
                onEnd: updateOutput 
            }); 
        } 
 
        // Extract URLs from text 
        function extractUrls(text) { 
            const urlRegex = /https?:\/\/[^\s<]+?\.(jpg|jpeg|png|gif|webp|svg|bmp)/gi; 
            return text.match(urlRegex) || []; 
        } 
 
        // Update the grid layout 
        function updateGridLayout() { 
            imageGrid.style.gridTemplateColumns = `repeat(${gridColumns.value}, 1fr)`; 
        } 
 
        // Generate the image blocks 
        generateBtn.addEventListener('click', () => { 
            const urls = extractUrls(inputText.value); 
            imageGrid.innerHTML = ''; 
             
            if (urls.length === 0) { 
                alert("No image URLs found."); 
                return; 
            } 
 
            urls.forEach(url => { 
                const div = document.createElement('div'); 
                div.className = 'grid-item'; 
                div.dataset.url = url; 
 
                const img = document.createElement('img'); 
                img.src = url; 
                img.loading = "lazy"; 
                 
                // Handle broken images 
                img.onerror = () => { 
                    div.style.backgroundColor = '#ffcccc'; 
                    div.innerText = 'Broken Link'; 
                }; 
 
                div.appendChild(img); 
                imageGrid.appendChild(div); 
            }); 
 
            updateGridLayout(); 
            initSortable(); 
            updateOutput(); 
        }); 
 
        // Sync Output Textarea with Grid Order 
        function updateOutput() { 
            const items = imageGrid.querySelectorAll('.grid-item'); 
            const orderedUrls = Array.from(items).map(item => item.dataset.url); 
            outputText.value = orderedUrls.join('\n'); 
        } 
 
        // Listen for column changes in real-time 
        gridColumns.addEventListener('input', updateGridLayout); 
 
        // Copy Function 
        function copyOutput() { 
            outputText.select(); 
            document.execCommand('copy'); 
            alert('Copied to clipboard!'); 
        } 
    </script> 
</body> 
</html> 

Posted Using INLEO