anycoder-aeee9a95 / index.html
HI7RAI's picture
Upload folder using huggingface_hub
875e739 verified
Raw
History Blame Contribute Delete
44.5 kB
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Deep Web Scraper Pro</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--bg-primary: #0a0a0f;
--bg-secondary: #12121a;
--bg-tertiary: #1a1a25;
--accent-primary: #00d4ff;
--accent-secondary: #7c3aed;
--accent-gradient: linear-gradient(135deg, #00d4ff 0%, #7c3aed 100%);
--text-primary: #ffffff;
--text-secondary: #a0a0b0;
--border-color: #2a2a3a;
--success: #10b981;
--warning: #f59e0b;
--error: #ef4444;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
overflow-x: hidden;
}
/* Animated background */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
radial-gradient(ellipse at 20% 20%, rgba(0, 212, 255, 0.08) 0%, transparent 50%),
radial-gradient(ellipse at 80% 80%, rgba(124, 58, 237, 0.08) 0%, transparent 50%);
pointer-events: none;
z-index: 0;
}
.container {
max-width: 1600px;
margin: 0 auto;
padding: 20px;
position: relative;
z-index: 1;
}
/* Header */
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 0;
border-bottom: 1px solid var(--border-color);
margin-bottom: 30px;
}
.logo {
display: flex;
align-items: center;
gap: 15px;
}
.logo-icon {
width: 50px;
height: 50px;
background: var(--accent-gradient);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
box-shadow: 0 10px 30px rgba(0, 212, 255, 0.3);
}
.logo-text {
font-size: 24px;
font-weight: 700;
background: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header-links {
display: flex;
gap: 20px;
align-items: center;
}
.header-links a {
color: var(--text-secondary);
text-decoration: none;
font-size: 14px;
transition: color 0.3s;
}
.header-links a:hover {
color: var(--accent-primary);
}
/* Main Input Section */
.input-section {
background: var(--bg-secondary);
border-radius: 20px;
padding: 30px;
margin-bottom: 30px;
border: 1px solid var(--border-color);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
.input-tabs {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.input-tab {
padding: 12px 24px;
background: var(--bg-tertiary);
border: none;
border-radius: 10px;
color: var(--text-secondary);
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 8px;
}
.input-tab.active {
background: var(--accent-gradient);
color: white;
}
.input-tab:hover:not(.active) {
background: var(--bg-primary);
color: var(--text-primary);
}
.input-wrapper {
display: flex;
gap: 15px;
}
.url-input {
flex: 1;
padding: 16px 20px;
background: var(--bg-primary);
border: 2px solid var(--border-color);
border-radius: 12px;
color: var(--text-primary);
font-size: 16px;
outline: none;
transition: all 0.3s;
}
.url-input:focus {
border-color: var(--accent-primary);
box-shadow: 0 0 20px rgba(0, 212, 255, 0.2);
}
.url-input::placeholder {
color: var(--text-secondary);
}
.scrape-btn {
padding: 16px 40px;
background: var(--accent-gradient);
border: none;
border-radius: 12px;
color: white;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 10px;
white-space: nowrap;
}
.scrape-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(0, 212, 255, 0.4);
}
.scrape-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
}
/* Code Input Area */
.code-input-area {
display: none;
margin-top: 20px;
}
.code-input-area.active {
display: block;
}
.code-textarea {
width: 100%;
min-height: 200px;
padding: 20px;
background: var(--bg-primary);
border: 2px solid var(--border-color);
border-radius: 12px;
color: var(--text-primary);
font-family: 'Fira Code', 'Consolas', monospace;
font-size: 14px;
resize: vertical;
outline: none;
transition: all 0.3s;
}
.code-textarea:focus {
border-color: var(--accent-primary);
}
/* Progress Section */
.progress-section {
display: none;
margin: 30px 0;
padding: 30px;
background: var(--bg-secondary);
border-radius: 20px;
border: 1px solid var(--border-color);
}
.progress-section.active {
display: block;
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.progress-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.progress-title {
font-size: 18px;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.progress-percentage {
font-size: 32px;
font-weight: 700;
background: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.progress-bar-container {
background: var(--bg-primary);
border-radius: 10px;
height: 20px;
overflow: hidden;
margin-bottom: 15px;
}
.progress-bar {
height: 100%;
background: var(--accent-gradient);
border-radius: 10px;
width: 0%;
transition: width 0.3s ease;
position: relative;
}
.progress-bar::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.progress-status {
color: var(--text-secondary);
font-size: 14px;
}
.progress-stats {
display: flex;
gap: 30px;
margin-top: 20px;
flex-wrap: wrap;
}
.stat-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 15px;
background: var(--bg-tertiary);
border-radius: 10px;
}
.stat-icon {
width: 40px;
height: 40px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
.stat-icon.js { background: rgba(247, 223, 30, 0.2); color: #f7df1e; }
.stat-icon.css { background: rgba(38, 77, 228, 0.2); color: #264de4; }
.stat-icon.pages { background: rgba(16, 185, 129, 0.2); color: var(--success); }
.stat-info {
display: flex;
flex-direction: column;
}
.stat-label {
font-size: 12px;
color: var(--text-secondary);
}
.stat-value {
font-size: 18px;
font-weight: 600;
}
/* Results Section */
.results-section {
display: none;
}
.results-section.active {
display: block;
}
.results-grid {
display: grid;
grid-template-columns: 350px 1fr;
gap: 30px;
}
@media (max-width: 1200px) {
.results-grid {
grid-template-columns: 1fr;
}
}
/* Links Panel */
.links-panel {
background: var(--bg-secondary);
border-radius: 20px;
border: 1px solid var(--border-color);
overflow: hidden;
}
.panel-header {
padding: 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.panel-title {
font-size: 18px;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.links-count {
background: var(--accent-gradient);
padding: 4px 12px;
border-radius: 20px;
font-size: 14px;
font-weight: 600;
}
.links-filter {
display: flex;
gap: 8px;
}
.filter-btn {
padding: 8px 16px;
background: var(--bg-tertiary);
border: none;
border-radius: 8px;
color: var(--text-secondary);
cursor: pointer;
font-size: 13px;
transition: all 0.3s;
}
.filter-btn.active {
background: var(--accent-primary);
color: var(--bg-primary);
}
.links-list {
max-height: 600px;
overflow-y: auto;
padding: 10px;
}
.link-item {
padding: 15px;
background: var(--bg-tertiary);
border-radius: 12px;
margin-bottom: 10px;
cursor: pointer;
transition: all 0.3s;
border: 2px solid transparent;
}
.link-item:hover {
border-color: var(--accent-primary);
transform: translateX(5px);
}
.link-item.selected {
border-color: var(--accent-primary);
background: rgba(0, 212, 255, 0.1);
}
.link-type {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
margin-bottom: 8px;
}
.link-type.js {
background: rgba(247, 223, 30, 0.2);
color: #f7df1e;
}
.link-type.css {
background: rgba(38, 77, 228, 0.2);
color: #264de4;
}
.link-url {
font-size: 13px;
color: var(--text-primary);
word-break: break-all;
font-family: 'Fira Code', monospace;
}
.link-size {
font-size: 12px;
color: var(--text-secondary);
margin-top: 5px;
}
/* Preview Panel */
.preview-panel {
background: var(--bg-secondary);
border-radius: 20px;
border: 1px solid var(--border-color);
overflow: hidden;
}
.preview-header {
padding: 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 15px;
}
.preview-title {
font-size: 18px;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.preview-actions {
display: flex;
gap: 10px;
}
.action-btn {
padding: 10px 20px;
background: var(--bg-tertiary);
border: 1px solid var(--border-color);
border-radius: 10px;
color: var(--text-primary);
cursor: pointer;
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s;
}
.action-btn:hover {
background: var(--accent-primary);
color: var(--bg-primary);
border-color: var(--accent-primary);
}
.preview-content {
padding: 20px;
min-height: 500px;
}
.preview-frame {
width: 100%;
height: 500px;
border: none;
border-radius: 12px;
background: var(--bg-primary);
}
.preview-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 400px;
color: var(--text-secondary);
}
.preview-empty i {
font-size: 60px;
margin-bottom: 20px;
opacity: 0.5;
}
/* CSS Transform Controls */
.transform-controls {
display: none;
padding: 20px;
background: var(--bg-tertiary);
border-top: 1px solid var(--border-color);
}
.transform-controls.active {
display: block;
}
.transform-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
color: var(--accent-primary);
}
.transform-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.transform-item {
display: flex;
flex-direction: column;
gap: 8px;
}
.transform-label {
font-size: 13px;
color: var(--text-secondary);
display: flex;
justify-content: space-between;
}
.transform-value {
color: var(--accent-primary);
font-family: monospace;
}
.transform-slider {
-webkit-appearance: none;
width: 100%;
height: 6px;
background: var(--bg-primary);
border-radius: 3px;
outline: none;
}
.transform-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 18px;
height: 18px;
background: var(--accent-gradient);
border-radius: 50%;
cursor: pointer;
box-shadow: 0 2px 10px rgba(0, 212, 255, 0.5);
}
.transform-presets {
display: flex;
gap: 10px;
margin-top: 15px;
flex-wrap: wrap;
}
.preset-btn {
padding: 8px 16px;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 8px;
color: var(--text-secondary);
cursor: pointer;
font-size: 13px;
transition: all 0.3s;
}
.preset-btn:hover {
border-color: var(--accent-primary);
color: var(--accent-primary);
}
/* Stored Files Section */
.stored-section {
margin-top: 30px;
background: var(--bg-secondary);
border-radius: 20px;
border: 1px solid var(--border-color);
overflow: hidden;
}
.stored-header {
padding: 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.stored-title {
font-size: 18px;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.stored-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
padding: 20px;
}
.stored-card {
background: var(--bg-tertiary);
border-radius: 16px;
overflow: hidden;
border: 2px solid var(--border-color);
transition: all 0.3s;
}
.stored-card:hover {
border-color: var(--accent-primary);
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}
.stored-preview {
height: 150px;
background: var(--bg-primary);
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid var(--border-color);
}
.stored-preview iframe {
width: 100%;
height: 100%;
border: none;
}
.stored-info {
padding: 15px;
}
.stored-filename {
font-size: 14px;
font-weight: 600;
margin-bottom: 5px;
word-break: break-all;
}
.stored-meta {
font-size: 12px;
color: var(--text-secondary);
display: flex;
justify-content: space-between;
}
.stored-actions {
padding: 10px 15px;
display: flex;
gap: 10px;
}
.stored-btn {
flex: 1;
padding: 8px;
background: var(--bg-secondary);
border: none;
border-radius: 8px;
color: var(--text-secondary);
cursor: pointer;
font-size: 12px;
transition: all 0.3s;
}
.stored-btn:hover {
background: var(--accent-primary);
color: var(--bg-primary);
}
/* Scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: var(--bg-primary);
}
::-webkit-scrollbar-thumb {
background: var(--border-color);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--accent-primary);
}
/* Toast Notifications */
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 1000;
display: flex;
flex-direction: column;
gap: 10px;
}
.toast {
padding: 15px 20px;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 12px;
display: flex;
align-items: center;
gap: 12px;
animation: slideIn 0.3s ease;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.toast.success { border-left: 4px solid var(--success); }
.toast.error { border-left: 4px solid var(--error); }
.toast.warning { border-left: 4px solid var(--warning); }
.toast-icon {
font-size: 20px;
}
.toast.success .toast-icon { color: var(--success); }
.toast.error .toast-icon { color: var(--error); }
.toast.warning .toast-icon { color: var(--warning); }
/* Loading Animation */
.loading-spinner {
width: 20px;
height: 20px;
border: 2px solid transparent;
border-top-color: white;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Empty State */
.empty-state {
text-align: center;
padding: 60px 20px;
color: var(--text-secondary);
}
.empty-state i {
font-size: 80px;
margin-bottom: 20px;
opacity: 0.3;
}
.empty-state h3 {
font-size: 20px;
margin-bottom: 10px;
color: var(--text-primary);
}
/* Responsive */
@media (max-width: 768px) {
.container {
padding: 10px;
}
header {
flex-direction: column;
gap: 15px;
}
.input-wrapper {
flex-direction: column;
}
.scrape-btn {
width: 100%;
justify-content: center;
}
.progress-stats {
flex-direction: column;
}
.transform-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<div class="logo">
<div class="logo-icon">
<i class="fas fa-spider"></i>
</div>
<span class="logo-text">Deep Web Scraper Pro</span>
</div>
<div class="header-links">
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">Built with anycoder</a>
<a href="#"><i class="fas fa-cog"></i> Settings</a>
</div>
</header>
<section class="input-section">
<div class="input-tabs">
<button class="input-tab active" data-tab="url">
<i class="fas fa-link"></i> URL Input
</button>
<button class="input-tab" data-tab="source">
<i class="fas fa-code"></i> Source Code
</button>
</div>
<div class="input-wrapper" id="url-input-wrapper">
<input type="text" class="url-input" id="urlInput" placeholder="Enter website URL (e.g., https://example.com)">
<button class="scrape-btn" id="scrapeBtn">
<i class="fas fa-search"></i>
Start Scraping
</button>
</div>
<div class="code-input-area" id="code-input-area">
<textarea class="code-textarea" id="sourceCodeInput" placeholder="Paste your HTML source code here..."></textarea>
<button class="scrape-btn" id="scrapeSourceBtn" style="margin-top: 15px;">
<i class="fas fa-search"></i>
Analyze Source
</button>
</div>
</section>
<section class="progress-section" id="progressSection">
<div class="progress-header">
<div class="progress-title">
<i class="fas fa-spinner fa-spin"></i>
<span>Scraping in Progress...</span>
</div>
<div class="progress-percentage" id="progressPercent">0%</div>
</div>
<div class="progress-bar-container">
<div class="progress-bar" id="progressBar"></div>
</div>
<div class="progress-status" id="progressStatus">Initializing scraper...</div>
<div class="progress-stats">
<div class="stat-item">
<div class="stat-icon pages">
<i class="fas fa-globe"></i>
</div>
<div class="stat-info">
<span class="stat-label">Pages Scraped</span>
<span class="stat-value" id="pagesCount">0</span>
</div>
</div>
<div class="stat-item">
<div class="stat-icon js">
<i class="fab fa-js"></i>
</div>
<div class="stat-info">
<span class="stat-label">JavaScript Files</span>
<span class="stat-value" id="jsCount">0</span>
</div>
</div>
<div class="stat-item">
<div class="stat-icon css">
<i class="fab fa-css3-alt"></i>
</div>
<div class="stat-info">
<span class="stat-label">CSS Files</span>
<span class="stat-value" id="cssCount">0</span>
</div>
</div>
</div>
</section>
<section class="results-section" id="resultsSection">
<div class="results-grid">
<div class="links-panel">
<div class="panel-header">
<div class="panel-title">
<i class="fas fa-list"></i>
Extracted Resources
<span class="links-count" id="linksCount">0</span>
</div>
<div class="links-filter">
<button class="filter-btn active" data-filter="all">All</button>
<button class="filter-btn" data-filter="js">JS</button>
<button class="filter-btn" data-filter="css">CSS</button>
</div>
</div>
<div class="links-list" id="linksList">
<!-- Links will be inserted here -->
</div>
</div>
<div class="preview-panel">
<div class="preview-header">
<div class="preview-title">
<i class="fas fa-eye"></i>
Preview
<span id="previewFileName" style="color: var(--text-secondary); font-weight: normal; font-size: 14px;"></span>
</div>
<div class="preview-actions">
<button class="action-btn" id="saveBtn">
<i class="fas fa-save"></i> Save
</button>
<button class="action-btn" id="downloadBtn">
<i class="fas fa-download"></i> Download
</button>
<button class="action-btn" id="transformBtn">
<i class="fas fa-magic"></i> Transform
</button>
</div>
</div>
<div class="preview-content">
<iframe class="preview-frame" id="previewFrame" sandbox="allow-same-origin"></iframe>
</div>
<div class="transform-controls" id="transformControls">
<div class="transform-title">
<i class="fas fa-magic"></i> CSS Transform Controls
</div>
<div class="transform-grid">
<div class="transform-item">
<div class="transform-label">
<span>Translate X</span>
<span class="transform-value" id="translateXVal">0px</span>
</div>
<input type="range" class="transform-slider" id="translateX" min="-200" max="200" value="0">
</div>
<div class="transform-item">
<div class="transform-label">
<span>Translate Y</span>
<span class="transform-value" id="translateYVal">0px</span>
</div>
<input type="range" class="transform-slider" id="translateY" min="-200" max="200" value="0">
</div>
<div class="transform-item">
<div class="transform-label">
<span>Rotate</span>
<span class="transform-value" id="rotateVal">0deg</span>
</div>
<input type="range" class="transform-slider" id="rotate" min="-360" max="360" value="0">
</div>
<div class="transform-item">
<div class="transform-label">
<span>Scale</span>
<span class="transform-value" id="scaleVal">1</span>
</div>
<input type="range" class="transform-slider" id="scale" min="0.1" max="3" step="0.1" value="1">
</div>
<div class="transform-item">
<div class="transform-label">
<span>Skew X</span>
<span class="transform-value" id="skewXVal">0deg</span>
</div>
<input type="range" class="transform-slider" id="skewX" min="-45" max="45" value="0">
</div>
<div class="transform-item">
<div class="transform-label">
<span>Skew Y</span>
<span class="transform-value" id="skewYVal">0deg</span>
</div>
<input type="range" class="transform-slider" id="skewY" min="-45" max="45" value="0">
</div>
<div class="transform-item">
<div class="transform-label">
<span>Perspective</span>
<span class="transform-value" id="perspectiveVal">500px</span>
</div>
<input type="range" class="transform-slider" id="perspective" min="100" max="1000" value="500">
</div>
<div class="transform-item">
<div class="transform-label">
<span>Opacity</span>
<span class="transform-value" id="opacityVal">1</span>
</div>
<input type="range" class="transform-slider" id="opacity" min="0" max="1" step="0.1" value="1">
</div>
</div>
<div class="transform-presets">
<button class="preset-btn" data-preset="reset">Reset</button>
<button class="preset-btn" data-preset="flip">Flip</button>
<button class="preset-btn" data-preset="zoom">Zoom In</button>
<button class="preset-btn" data-preset="tilt">3D Tilt</button>
<button class="preset-btn" data-preset="spin">Spin</button>
<button class="preset-btn" data-preset="shake">Shake</button>
</div>
</div>
</div>
</div>
</section>
<section class="stored-section" id="storedSection">
<div class="stored-header">
<div class="stored-title">
<i class="fas fa-folder-open"></i>
Saved Files Stream
<span class="links-count" id="storedCount">0</span>
</div>
<button class="action-btn" id="clearStorageBtn">
<i class="fas fa-trash"></i> Clear All
</button>
</div>
<div class="stored-grid" id="storedGrid">
<!-- Stored files will be inserted here -->
</div>
</section>
</div>
<div class="toast-container" id="toastContainer"></div>
<script>
// Application State
const state = {
links: [],
selectedLink: null,
storedFiles: [],
isScraping: false
};
// DOM Elements
const elements = {
urlInput: document.getElementById('urlInput'),
sourceCodeInput: document.getElementById('sourceCodeInput'),
scrapeBtn: document.getElementById('scrapeBtn'),
scrapeSourceBtn: document.getElementById('scrapeSourceBtn'),
progressSection: document.getElementById('progressSection'),
progressBar: document.getElementById('progressBar'),
progressPercent: document.getElementById('progressPercent'),
progressStatus: document.getElementById('progressStatus'),
pagesCount: document.getElementById('pagesCount'),
jsCount: document.getElementById('jsCount'),
cssCount: document.getElementById('cssCount'),
resultsSection: document.getElementById('resultsSection'),
linksList: document.getElementById('linksList'),
linksCount: document.getElementById('linksCount'),
previewFrame: document.getElementById('previewFrame'),
previewFileName: document.getElementById('previewFileName'),
transformControls: document.getElementById('transformControls'),
storedSection: document.getElementById('storedSection'),
storedGrid: document.getElementById('storedGrid'),
storedCount: document.getElementById('storedCount'),
toastContainer: document.getElementById('toastContainer')
};
// Tab Switching
document.querySelectorAll('.input-tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('.input-tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
const tabType = tab.dataset.tab;
document.getElementById('url-input-wrapper').style.display = tabType === 'url' ? 'flex' : 'none';
document.getElementById('code-input-area').classList.toggle('active', tabType === 'source');
});
});
// Filter Buttons
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
renderLinks(btn.dataset.filter);
});
});
// Transform Controls
const transformSliders = ['translateX', 'translateY', 'rotate', 'scale', 'skewX', 'skewY', 'perspective', 'opacity'];
transformSliders.forEach(id => {
const slider = document.getElementById(id);
if (slider) {
slider.addEventListener('input', updateTransform);
}
});
function updateTransform() {
const translateX = document.getElementById('translateX').value;
const translateY = document.getElementById('translateY').value;
const rotate = document.getElementById('rotate').value;
const scale = document.getElementById('scale').value;
const skewX = document.getElementById('skewX').value;
const skewY = document.getElementById('skewY').value;
const perspective = document.getElementById('perspective').value;
const opacity = document.getElementById('opacity').value;
// Update display values
document.getElementById('translateXVal').textContent = translateX + 'px';
document.getElementById('translateYVal').textContent = translateY + 'px';
document.getElementById('rotateVal').textContent = rotate + 'deg';
document.getElementById('scaleVal').textContent = scale;
document.getElementById('skewXVal').textContent = skewX + 'deg';
document.getElementById('skewYVal').textContent = skewY + 'deg';
document.getElementById('perspectiveVal').textContent = perspective + 'px';
document.getElementById('opacityVal').textContent = opacity;
// Apply transform
const transform = `perspective(${perspective}px) translateX(${translateX}px) translateY(${translateY}px) rotate(${rotate}deg) scale(${scale}) skewX(${skewX}deg) skewY(${skewY}deg)`;
elements.previewFrame.style.transform = transform;
elements.previewFrame.style.opacity = opacity;
}
// Preset Buttons
document.querySelectorAll('.preset-btn').forEach(btn => {
btn.addEventListener('click', () => {
const preset = btn.dataset.preset;
applyPreset(preset);
});
});
function applyPreset(preset) {
switch(preset) {
case 'reset':
setTransformValues(0, 0, 0, 1, 0, 0, 500, 1);
break;
case 'flip':
setTransformValues(0, 0, 180, 1, 0, 0, 500, 1);
break;
case 'zoom':
setTransformValues(0, 0, 0, 1.5, 0, 0, 500, 1);
break;
case 'tilt':
setTransformValues(0, 0, 0, 1, 20, 20, 500, 1);
break;
case 'spin':
setTransformValues(0, 0, 360, 1, 0, 0, 500, 1);
break;
case 'shake':
setTransformValues(20, 0, 0, 1, 0, 0, 500, 1);
setTimeout(() => setTransformValues(-20, 0, 0, 1, 0, 0, 500, 1), 100);
setTimeout(() => setTransformValues(0, 0, 0, 1, 0, 0, 500, 1), 200);
break;
}
updateTransform();
}
function setTransformValues(tx, ty, r, s, sx, sy, p, o) {
document.getElementById('translateX').value = tx;
document.getElementById('translateY').value = ty;
document.getElementById('rotate').value = r;
document.getElementById('scale').value = s;
document.getElementById('skewX').value = sx;
document.getElementById('skewY').value = sy;
document.getElementById('perspective').value = p;
document.getElementById('opacity').value = o;
}
// Toggle Transform Controls
document.getElementById('transformBtn').addEventListener('click', () => {
elements.transformControls.classList.toggle('active');
});
// Toast Notifications
function showToast(message, type = 'success') {
const toast = document.createElement('div');
toast.className = `toast ${type}`;
let icon = 'check-circle';
if (type === 'error') icon = 'exclamation-circle';
if (type === 'warning') icon = 'exclamation-triangle';
toast.innerHTML = `
<i class="fas fa-${icon} toast-icon"></i>
<span>${message}</span>
`;
elements.toastContainer.appendChild(toast);
setTimeout(() => {
toast.style.animation = 'slideIn 0.3s reverse';
setTimeout(() => toast.remove(), 300);
}, 3000);
}
// Simulated Scraping Process
async function simulateScraping(input, isUrl = true) {
state.isScraping = true;
elements.scrapeBtn.disabled = true;
elements.scrapeBtn.innerHTML = '<div class="loading-spinner"></div> Scraping...';
elements.progressSection.classList.add('active');
elements.resultsSection.classList.remove('active');
const links = [];
// Simulate crawling multiple pages
const pages = isUrl ? 5 : 1;
for (let i = 0; i <= 100; i += 5) {
await delay(100);
updateProgress(i, `Scanning page ${Math.ceil(i/20)} of ${pages}...`);
// Simulate finding links at certain progress points
if (i === 20) {
links.push(...generateMockLinks(input, 'js', 3));
}
if (i === 40) {
links.push(...generateMockLinks(input, 'css', 2));
}
if (i === 60) {
links.push(...generateMockLinks(input, 'js', 2));
}
if (i === 80) {
links.push(...generateMockLinks(input, 'css', 3));
}
}
state.links = links;
state.isScraping = false;
elements.scrapeBtn.disabled = false;
elements.scrapeBtn.innerHTML = '<i class="fas fa-search"></i> Start Scraping';
showToast(`Found ${links.length} resources!`, 'success');
displayResults();
}
function generateMockLinks(base, type, count) {
const links = [];
const domains = ['jquery.com', 'cdnjs.cloudflare.com', 'unpkg.com', 'google.com'];
for (let i = 0; i < count; i++) {
const domain = domains[Math.floor(Math.random() * domains.length)];
const version = Math.floor(Math.random() * 10) + 1;
const size = Math.floor(Math.random() * 100) + 10;
if (type === 'js') {
links.push({
type: 'js',
url: `https://${domain}/ajax/libs/${type}${version}.${i}/lib.min.js`,
size: size + ' KB'
});
} else {
links.push({
type: 'css',
url: `https://${domain