maydayjeffk commited on
Commit
ce11844
·
verified ·
1 Parent(s): b79b754

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +628 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Batch Image Downloader And Converter
3
- emoji: 🏢
4
- colorFrom: green
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: batch-image-downloader-and-converter
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,628 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>PUNK IMAGE GRABBER - Stick It To The Man</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ @import url('https://fonts.googleapis.com/css2?family=Rubik+Mono+One&family=VT323&display=swap');
11
+
12
+ body {
13
+ background-color: #000;
14
+ font-family: 'VT323', monospace;
15
+ color: #fff;
16
+ overflow-x: hidden;
17
+ }
18
+
19
+ .title {
20
+ font-family: 'Rubik Mono One', sans-serif;
21
+ text-shadow: 3px 3px 0 #f00, -3px -3px 0 #00f;
22
+ }
23
+
24
+ .graffiti {
25
+ position: absolute;
26
+ transform: rotate(-5deg);
27
+ color: #ff0;
28
+ font-size: 1.2rem;
29
+ text-shadow: 2px 2px 0 #000;
30
+ z-index: 100;
31
+ }
32
+
33
+ .graffiti-1 {
34
+ top: 15%;
35
+ left: 5%;
36
+ }
37
+
38
+ .graffiti-2 {
39
+ top: 65%;
40
+ right: 5%;
41
+ }
42
+
43
+ .graffiti-3 {
44
+ bottom: 10%;
45
+ left: 10%;
46
+ }
47
+
48
+ .btn-punk {
49
+ background: linear-gradient(45deg, #f00, #00f);
50
+ border: 2px solid #fff;
51
+ color: white;
52
+ font-weight: bold;
53
+ transition: all 0.3s;
54
+ }
55
+
56
+ .btn-punk:hover {
57
+ transform: scale(1.05);
58
+ box-shadow: 0 0 15px #f00;
59
+ }
60
+
61
+ .carousel {
62
+ background-color: rgba(0, 0, 0, 0.9);
63
+ border: 3px solid #f00;
64
+ }
65
+
66
+ .image-tile {
67
+ border: 2px solid #fff;
68
+ transition: all 0.3s;
69
+ }
70
+
71
+ .image-tile:hover {
72
+ border-color: #f00;
73
+ transform: scale(1.02);
74
+ }
75
+
76
+ .selected {
77
+ border: 3px solid #00f;
78
+ box-shadow: 0 0 15px #00f;
79
+ }
80
+
81
+ .progress-bar {
82
+ height: 10px;
83
+ background-color: #333;
84
+ }
85
+
86
+ .progress-fill {
87
+ height: 100%;
88
+ background: linear-gradient(90deg, #f00, #00f);
89
+ transition: width 0.3s;
90
+ }
91
+
92
+ .filetype-badge {
93
+ background-color: #333;
94
+ border: 1px solid #fff;
95
+ }
96
+
97
+ .convert-option {
98
+ border: 1px solid #fff;
99
+ transition: all 0.3s;
100
+ }
101
+
102
+ .convert-option:hover {
103
+ background-color: #333;
104
+ border-color: #f00;
105
+ }
106
+
107
+ .convert-option.selected-format {
108
+ background-color: #00f;
109
+ color: #fff;
110
+ }
111
+
112
+ .spray-paint {
113
+ position: absolute;
114
+ width: 100%;
115
+ height: 100%;
116
+ pointer-events: none;
117
+ z-index: -1;
118
+ opacity: 0.1;
119
+ }
120
+ </style>
121
+ </head>
122
+ <body>
123
+ <!-- Spray paint background effect -->
124
+ <div class="spray-paint">
125
+ <div style="position: absolute; top: 20%; left: 10%; width: 200px; height: 150px; background-color: #f00; transform: rotate(-15deg);"></div>
126
+ <div style="position: absolute; top: 60%; right: 15%; width: 180px; height: 120px; background-color: #00f; transform: rotate(10deg);"></div>
127
+ <div style="position: absolute; bottom: 10%; left: 50%; width: 150px; height: 100px; background-color: #ff0; transform: rotate(-5deg);"></div>
128
+ </div>
129
+
130
+ <!-- Graffiti tags -->
131
+ <div class="graffiti graffiti-1">FUCK CAPITALISM</div>
132
+ <div class="graffiti graffiti-2">TRUMP IS A FASCIST</div>
133
+ <div class="graffiti graffiti-3">EAT THE RICH</div>
134
+
135
+ <div class="container mx-auto px-4 py-8">
136
+ <header class="text-center mb-8">
137
+ <h1 class="title text-5xl md:text-6xl mb-4">PUNK IMAGE GRABBER</h1>
138
+ <p class="text-xl">Steal images like you steal from the bourgeoisie</p>
139
+ </header>
140
+
141
+ <div class="max-w-3xl mx-auto bg-gray-900 p-6 rounded-lg border-2 border-red-500 mb-8 relative">
142
+ <h2 class="text-2xl mb-4">ENTER URL TO SCRAPE</h2>
143
+ <div class="flex">
144
+ <input type="text" id="urlInput" placeholder="https://example.com" class="flex-grow px-4 py-2 bg-black text-white border-2 border-white focus:border-red-500 outline-none">
145
+ <button id="scrapeBtn" class="btn-punk px-6 py-2 ml-2">
146
+ <i class="fas fa-skull-crossbones mr-2"></i>GRAB 'EM
147
+ </button>
148
+ </div>
149
+ <p class="text-sm mt-2 text-gray-400">Works with JPG, PNG, GIF, WEBP, SVG, BMP, TIFF, and more</p>
150
+
151
+ <div class="mt-6">
152
+ <h3 class="text-xl mb-2">OPTIONS</h3>
153
+ <div class="flex flex-wrap gap-4">
154
+ <label class="flex items-center">
155
+ <input type="checkbox" id="recursiveCheck" class="mr-2">
156
+ <span>Recursive scraping (Deeper = more dangerous)</span>
157
+ </label>
158
+ <label class="flex items-center">
159
+ <input type="checkbox" id="filterCheck" class="mr-2" checked>
160
+ <span>Filter out tiny images</span>
161
+ </label>
162
+ </div>
163
+ </div>
164
+
165
+ <div class="mt-6 hidden" id="progressContainer">
166
+ <div class="flex justify-between mb-2">
167
+ <span>Scraping progress...</span>
168
+ <span id="progressText">0%</span>
169
+ </div>
170
+ <div class="progress-bar">
171
+ <div id="progressFill" class="progress-fill" style="width: 0%"></div>
172
+ </div>
173
+ <div class="mt-2 text-sm" id="statusText">Waiting to start...</div>
174
+ </div>
175
+ </div>
176
+
177
+ <div class="hidden" id="resultsSection">
178
+ <div class="flex justify-between items-center mb-4">
179
+ <h2 class="text-3xl">YOUR STOLEN GOODS</h2>
180
+ <div>
181
+ <button id="selectAllBtn" class="btn-punk px-4 py-1 mr-2">
182
+ <i class="fas fa-check-double mr-1"></i>SELECT ALL
183
+ </button>
184
+ <button id="convertBtn" class="btn-punk px-4 py-1 mr-2">
185
+ <i class="fas fa-exchange-alt mr-1"></i>CONVERT
186
+ </button>
187
+ <button id="downloadBtn" class="btn-punk px-4 py-1 mr-2">
188
+ <i class="fas fa-download mr-1"></i>DOWNLOAD
189
+ </button>
190
+ <button id="deleteBtn" class="btn-punk bg-red-900 px-4 py-1">
191
+ <i class="fas fa-trash mr-1"></i>DELETE
192
+ </button>
193
+ </div>
194
+ </div>
195
+
196
+ <div id="imageGrid" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4 mb-8">
197
+ <!-- Images will be loaded here -->
198
+ </div>
199
+ </div>
200
+ </div>
201
+
202
+ <!-- Image Carousel Modal -->
203
+ <div id="carouselModal" class="fixed inset-0 bg-black bg-opacity-90 flex items-center justify-center z-50 hidden">
204
+ <div class="carousel w-full max-w-4xl p-4 relative">
205
+ <button id="closeCarousel" class="absolute top-2 right-2 text-white text-2xl z-50">&times;</button>
206
+
207
+ <div class="relative h-96 overflow-hidden mb-4">
208
+ <img id="carouselImage" src="" alt="" class="w-full h-full object-contain">
209
+ </div>
210
+
211
+ <div class="flex justify-between items-center">
212
+ <button id="prevBtn" class="btn-punk px-4 py-1">
213
+ <i class="fas fa-arrow-left mr-1"></i>PREV
214
+ </button>
215
+ <span id="imageCounter" class="text-xl">1/1</span>
216
+ <button id="nextBtn" class="btn-punk px-4 py-1">
217
+ NEXT <i class="fas fa-arrow-right ml-1"></i>
218
+ </button>
219
+ </div>
220
+ </div>
221
+ </div>
222
+
223
+ <!-- Convert Modal -->
224
+ <div id="convertModal" class="fixed inset-0 bg-black bg-opacity-90 flex items-center justify-center z-50 hidden">
225
+ <div class="carousel w-full max-w-2xl p-6 relative">
226
+ <button id="closeConvert" class="absolute top-2 right-2 text-white text-2xl z-50">&times;</button>
227
+
228
+ <h2 class="text-3xl mb-6">CONVERT TO WHAT?</h2>
229
+
230
+ <div class="grid grid-cols-2 sm:grid-cols-3 gap-4 mb-8">
231
+ <div class="convert-option p-4 text-center cursor-pointer" data-format="jpg">
232
+ <i class="fas fa-file-image text-4xl mb-2"></i>
233
+ <div>JPG</div>
234
+ </div>
235
+ <div class="convert-option p-4 text-center cursor-pointer" data-format="png">
236
+ <i class="fas fa-file-image text-4xl mb-2"></i>
237
+ <div>PNG</div>
238
+ </div>
239
+ <div class="convert-option p-4 text-center cursor-pointer" data-format="webp">
240
+ <i class="fas fa-file-image text-4xl mb-2"></i>
241
+ <div>WEBP</div>
242
+ </div>
243
+ <div class="convert-option p-4 text-center cursor-pointer" data-format="gif">
244
+ <i class="fas fa-file-image text-4xl mb-2"></i>
245
+ <div>GIF</div>
246
+ </div>
247
+ <div class="convert-option p-4 text-center cursor-pointer" data-format="bmp">
248
+ <i class="fas fa-file-image text-4xl mb-2"></i>
249
+ <div>BMP</div>
250
+ </div>
251
+ <div class="convert-option p-4 text-center cursor-pointer" data-format="ico">
252
+ <i class="fas fa-file-image text-4xl mb-2"></i>
253
+ <div>ICO</div>
254
+ </div>
255
+ </div>
256
+
257
+ <div class="flex justify-center">
258
+ <button id="confirmConvertBtn" class="btn-punk px-6 py-2">
259
+ <i class="fas fa-magic mr-2"></i>CONVERT THESE BITCHES
260
+ </button>
261
+ </div>
262
+ </div>
263
+ </div>
264
+
265
+ <!-- Delete Confirmation Modal -->
266
+ <div id="deleteModal" class="fixed inset-0 bg-black bg-opacity-90 flex items-center justify-center z-50 hidden">
267
+ <div class="carousel w-full max-w-md p-6 relative">
268
+ <h2 class="text-3xl mb-6 text-center">DESTROY THE EVIDENCE?</h2>
269
+ <p class="text-xl mb-8 text-center">This will delete <span id="deleteCount">0</span> selected images permanently.</p>
270
+
271
+ <div class="flex justify-center gap-4">
272
+ <button id="cancelDelete" class="btn-punk px-6 py-2">
273
+ <i class="fas fa-times mr-2"></i>NO, KEEP 'EM
274
+ </button>
275
+ <button id="confirmDelete" class="btn-punk bg-red-900 px-6 py-2">
276
+ <i class="fas fa-trash mr-2"></i>BURN IT ALL
277
+ </button>
278
+ </div>
279
+ </div>
280
+ </div>
281
+
282
+ <script>
283
+ // Global variables
284
+ let scrapedImages = [];
285
+ let currentCarouselIndex = 0;
286
+ let selectedImages = [];
287
+ let selectedFormat = null;
288
+
289
+ // DOM elements
290
+ const urlInput = document.getElementById('urlInput');
291
+ const scrapeBtn = document.getElementById('scrapeBtn');
292
+ const progressContainer = document.getElementById('progressContainer');
293
+ const progressFill = document.getElementById('progressFill');
294
+ const progressText = document.getElementById('progressText');
295
+ const statusText = document.getElementById('statusText');
296
+ const resultsSection = document.getElementById('resultsSection');
297
+ const imageGrid = document.getElementById('imageGrid');
298
+ const carouselModal = document.getElementById('carouselModal');
299
+ const carouselImage = document.getElementById('carouselImage');
300
+ const imageCounter = document.getElementById('imageCounter');
301
+ const closeCarousel = document.getElementById('closeCarousel');
302
+ const prevBtn = document.getElementById('prevBtn');
303
+ const nextBtn = document.getElementById('nextBtn');
304
+ const selectAllBtn = document.getElementById('selectAllBtn');
305
+ const downloadBtn = document.getElementById('downloadBtn');
306
+ const deleteBtn = document.getElementById('deleteBtn');
307
+ const convertBtn = document.getElementById('convertBtn');
308
+ const convertModal = document.getElementById('convertModal');
309
+ const closeConvert = document.getElementById('closeConvert');
310
+ const confirmConvertBtn = document.getElementById('confirmConvertBtn');
311
+ const deleteModal = document.getElementById('deleteModal');
312
+ const deleteCount = document.getElementById('deleteCount');
313
+ const cancelDelete = document.getElementById('cancelDelete');
314
+ const confirmDelete = document.getElementById('confirmDelete');
315
+ const recursiveCheck = document.getElementById('recursiveCheck');
316
+ const filterCheck = document.getElementById('filterCheck');
317
+
318
+ // Event listeners
319
+ scrapeBtn.addEventListener('click', startScraping);
320
+ closeCarousel.addEventListener('click', () => carouselModal.classList.add('hidden'));
321
+ prevBtn.addEventListener('click', showPrevImage);
322
+ nextBtn.addEventListener('click', showNextImage);
323
+ selectAllBtn.addEventListener('click', toggleSelectAll);
324
+ downloadBtn.addEventListener('click', downloadSelected);
325
+ deleteBtn.addEventListener('click', showDeleteConfirmation);
326
+ convertBtn.addEventListener('click', () => convertModal.classList.remove('hidden'));
327
+ closeConvert.addEventListener('click', () => convertModal.classList.add('hidden'));
328
+ confirmConvertBtn.addEventListener('click', convertImages);
329
+ cancelDelete.addEventListener('click', () => deleteModal.classList.add('hidden'));
330
+ confirmDelete.addEventListener('click', deleteSelected);
331
+
332
+ // Add event listeners to convert options
333
+ document.querySelectorAll('.convert-option').forEach(option => {
334
+ option.addEventListener('click', function() {
335
+ document.querySelectorAll('.convert-option').forEach(opt => {
336
+ opt.classList.remove('selected-format');
337
+ });
338
+ this.classList.add('selected-format');
339
+ selectedFormat = this.dataset.format;
340
+ });
341
+ });
342
+
343
+ // Functions
344
+ function startScraping() {
345
+ const url = urlInput.value.trim();
346
+ if (!url) {
347
+ alert("ENTER A URL, YOU REBEL!");
348
+ return;
349
+ }
350
+
351
+ // Reset state
352
+ scrapedImages = [];
353
+ selectedImages = [];
354
+ imageGrid.innerHTML = '';
355
+
356
+ // Show progress
357
+ progressContainer.classList.remove('hidden');
358
+ progressFill.style.width = '0%';
359
+ progressText.textContent = '0%';
360
+ statusText.textContent = 'Starting the digital heist...';
361
+
362
+ // Simulate scraping (in a real app, this would be an API call)
363
+ simulateScraping(url);
364
+ }
365
+
366
+ function simulateScraping(url) {
367
+ let progress = 0;
368
+ const interval = setInterval(() => {
369
+ progress += Math.random() * 10;
370
+ if (progress > 100) progress = 100;
371
+
372
+ progressFill.style.width = `${progress}%`;
373
+ progressText.textContent = `${Math.floor(progress)}%`;
374
+
375
+ if (progress < 30) {
376
+ statusText.textContent = 'Bypassing capitalist security...';
377
+ } else if (progress < 60) {
378
+ statusText.textContent = 'Stealing from the rich...';
379
+ } else if (progress < 90) {
380
+ statusText.textContent = 'Sticking it to the man...';
381
+ } else {
382
+ statusText.textContent = 'Almost there, comrade...';
383
+ }
384
+
385
+ if (progress >= 100) {
386
+ clearInterval(interval);
387
+ finishScraping();
388
+ }
389
+ }, 300);
390
+ }
391
+
392
+ function finishScraping() {
393
+ statusText.textContent = 'Done! Images loaded.';
394
+
395
+ // Generate mock images (in a real app, these would come from the scraping)
396
+ const mockImages = generateMockImages();
397
+ scrapedImages = mockImages;
398
+
399
+ // Display images
400
+ displayImages(mockImages);
401
+
402
+ // Show results section
403
+ resultsSection.classList.remove('hidden');
404
+ }
405
+
406
+ function generateMockImages() {
407
+ const formats = ['jpg', 'png', 'gif', 'webp', 'svg', 'bmp', 'tiff'];
408
+ const images = [];
409
+
410
+ const count = Math.floor(Math.random() * 50) + 30; // 30-80 images
411
+
412
+ for (let i = 0; i < count; i++) {
413
+ const format = formats[Math.floor(Math.random() * formats.length)];
414
+ const width = Math.floor(Math.random() * 1000) + 200;
415
+ const height = Math.floor(Math.random() * 800) + 200;
416
+
417
+ images.push({
418
+ url: `https://picsum.photos/${width}/${height}?random=${i}`,
419
+ format: format,
420
+ width: width,
421
+ height: height,
422
+ originalUrl: `https://example.com/images/image${i}.${format}`
423
+ });
424
+ }
425
+
426
+ // Filter out tiny images if option is checked
427
+ if (filterCheck.checked) {
428
+ return images.filter(img => img.width > 100 && img.height > 100);
429
+ }
430
+
431
+ return images;
432
+ }
433
+
434
+ function displayImages(images) {
435
+ imageGrid.innerHTML = '';
436
+
437
+ images.forEach((img, index) => {
438
+ const tile = document.createElement('div');
439
+ tile.className = 'image-tile relative group cursor-pointer';
440
+ tile.dataset.index = index;
441
+
442
+ tile.innerHTML = `
443
+ <div class="relative pb-full">
444
+ <img src="${img.url}" alt="Scraped image" class="absolute h-full w-full object-cover" loading="lazy">
445
+ </div>
446
+ <div class="absolute bottom-0 left-0 right-0 bg-black bg-opacity-70 p-2 hidden group-hover:block">
447
+ <span class="filetype-badge px-2 py-1 text-xs">${img.format.toUpperCase()}</span>
448
+ <span class="text-xs ml-2">${img.width}x${img.height}</span>
449
+ </div>
450
+ <div class="absolute top-2 right-2 hidden group-hover:block">
451
+ <button class="select-btn bg-blue-500 text-white rounded-full w-6 h-6 flex items-center justify-center">
452
+ <i class="fas fa-check text-xs"></i>
453
+ </button>
454
+ </div>
455
+ `;
456
+
457
+ tile.addEventListener('click', () => {
458
+ currentCarouselIndex = index;
459
+ showImageInCarousel();
460
+ });
461
+
462
+ // Add select button event
463
+ const selectBtn = tile.querySelector('.select-btn');
464
+ selectBtn.addEventListener('click', (e) => {
465
+ e.stopPropagation();
466
+ toggleImageSelection(index, tile);
467
+ });
468
+
469
+ imageGrid.appendChild(tile);
470
+ });
471
+ }
472
+
473
+ function showImageInCarousel() {
474
+ if (scrapedImages.length === 0) return;
475
+
476
+ const img = scrapedImages[currentCarouselIndex];
477
+ carouselImage.src = img.url;
478
+ imageCounter.textContent = `${currentCarouselIndex + 1}/${scrapedImages.length}`;
479
+ carouselModal.classList.remove('hidden');
480
+ }
481
+
482
+ function showPrevImage() {
483
+ if (currentCarouselIndex > 0) {
484
+ currentCarouselIndex--;
485
+ } else {
486
+ currentCarouselIndex = scrapedImages.length - 1;
487
+ }
488
+ showImageInCarousel();
489
+ }
490
+
491
+ function showNextImage() {
492
+ if (currentCarouselIndex < scrapedImages.length - 1) {
493
+ currentCarouselIndex++;
494
+ } else {
495
+ currentCarouselIndex = 0;
496
+ }
497
+ showImageInCarousel();
498
+ }
499
+
500
+ function toggleImageSelection(index, tile = null) {
501
+ if (!tile) {
502
+ tile = document.querySelector(`.image-tile[data-index="${index}"]`);
503
+ }
504
+
505
+ const selectedIndex = selectedImages.indexOf(index);
506
+ if (selectedIndex === -1) {
507
+ selectedImages.push(index);
508
+ tile.classList.add('selected');
509
+ } else {
510
+ selectedImages.splice(selectedIndex, 1);
511
+ tile.classList.remove('selected');
512
+ }
513
+
514
+ updateSelectionCount();
515
+ }
516
+
517
+ function toggleSelectAll() {
518
+ const allSelected = selectedImages.length === scrapedImages.length;
519
+
520
+ if (allSelected) {
521
+ // Deselect all
522
+ selectedImages = [];
523
+ document.querySelectorAll('.image-tile').forEach(tile => {
524
+ tile.classList.remove('selected');
525
+ });
526
+ } else {
527
+ // Select all
528
+ selectedImages = Array.from({ length: scrapedImages.length }, (_, i) => i);
529
+ document.querySelectorAll('.image-tile').forEach(tile => {
530
+ tile.classList.add('selected');
531
+ });
532
+ }
533
+
534
+ updateSelectionCount();
535
+ }
536
+
537
+ function updateSelectionCount() {
538
+ const count = selectedImages.length;
539
+ if (count > 0) {
540
+ selectAllBtn.innerHTML = `<i class="fas fa-check-double mr-1"></i>${count === scrapedImages.length ? 'DESELECT ALL' : 'SELECT ALL'}`;
541
+ } else {
542
+ selectAllBtn.innerHTML = '<i class="fas fa-check-double mr-1"></i>SELECT ALL';
543
+ }
544
+ }
545
+
546
+ function downloadSelected() {
547
+ if (selectedImages.length === 0) {
548
+ alert("SELECT SOME IMAGES FIRST, YOU ANARCHIST!");
549
+ return;
550
+ }
551
+
552
+ // In a real app, this would create a zip file of selected images
553
+ alert(`Preparing to download ${selectedImages.length} images...\n\n(In a real app, this would create a ZIP file)`);
554
+
555
+ // Simulate download
556
+ setTimeout(() => {
557
+ alert("Download complete! Stick it to the man!");
558
+ }, 1500);
559
+ }
560
+
561
+ function showDeleteConfirmation() {
562
+ if (selectedImages.length === 0) {
563
+ alert("SELECT SOME IMAGES TO DELETE, YOU DESTRUCTIVE PUNK!");
564
+ return;
565
+ }
566
+
567
+ deleteCount.textContent = selectedImages.length;
568
+ deleteModal.classList.remove('hidden');
569
+ }
570
+
571
+ function deleteSelected() {
572
+ // Sort in descending order to avoid index issues when deleting
573
+ const sortedIndexes = [...selectedImages].sort((a, b) => b - a);
574
+
575
+ // Delete from scrapedImages
576
+ sortedIndexes.forEach(index => {
577
+ scrapedImages.splice(index, 1);
578
+ });
579
+
580
+ // Reset selection
581
+ selectedImages = [];
582
+
583
+ // Redisplay images
584
+ displayImages(scrapedImages);
585
+
586
+ // Close modal
587
+ deleteModal.classList.add('hidden');
588
+
589
+ // Show message
590
+ alert("Images deleted! The evidence is destroyed!");
591
+ }
592
+
593
+ function convertImages() {
594
+ if (selectedImages.length === 0) {
595
+ alert("SELECT SOME IMAGES TO CONVERT, YOU REBEL!");
596
+ return;
597
+ }
598
+
599
+ if (!selectedFormat) {
600
+ alert("CHOOSE A FORMAT, YOU ANARCHIST!");
601
+ return;
602
+ }
603
+
604
+ // In a real app, this would convert images to the selected format
605
+ alert(`Converting ${selectedImages.length} images to ${selectedFormat.toUpperCase()}...\n\n(In a real app, this would use a conversion API)`);
606
+
607
+ // Simulate conversion
608
+ setTimeout(() => {
609
+ alert(`Conversion to ${selectedFormat.toUpperCase()} complete! Take that, capitalist image standards!`);
610
+ convertModal.classList.add('hidden');
611
+ }, 1500);
612
+ }
613
+
614
+ // Close modals when clicking outside
615
+ window.addEventListener('click', (e) => {
616
+ if (e.target === carouselModal) {
617
+ carouselModal.classList.add('hidden');
618
+ }
619
+ if (e.target === convertModal) {
620
+ convertModal.classList.add('hidden');
621
+ }
622
+ if (e.target === deleteModal) {
623
+ deleteModal.classList.add('hidden');
624
+ }
625
+ });
626
+ </script>
627
+ <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=maydayjeffk/batch-image-downloader-and-converter" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
628
+ </html>