Spaces:
Running
Running
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Auto-Clic Avancé</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> | |
| :root { | |
| --primary: #4f46e5; | |
| --secondary: #6b7280; | |
| --dark: #1f2937; | |
| --darker: #111827; | |
| --light: #f3f4f6; | |
| } | |
| body { | |
| background-color: var(--darker); | |
| color: var(--light); | |
| min-height: 100vh; | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| } | |
| .floating-bar { | |
| position: fixed; | |
| bottom: 20px; | |
| right: 20px; | |
| z-index: 1000; | |
| transition: all 0.3s ease; | |
| } | |
| .floating-button { | |
| width: 50px; | |
| height: 50px; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); | |
| transition: all 0.2s ease; | |
| } | |
| .floating-button:hover { | |
| transform: scale(1.1); | |
| } | |
| .floating-bar-expanded { | |
| width: 300px; | |
| min-height: 100px; | |
| border-radius: 15px; | |
| padding: 10px; | |
| background-color: var(--dark); | |
| box-shadow: 0 10px 15px rgba(0, 0, 0, 0.3); | |
| } | |
| .btn-active { | |
| box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.5); | |
| } | |
| .btn-small { | |
| width: 60px; | |
| height: 30px; | |
| font-size: 0.7rem; | |
| } | |
| .btn-medium { | |
| width: 100px; | |
| height: 50px; | |
| font-size: 0.9rem; | |
| } | |
| .btn-large { | |
| width: 140px; | |
| height: 70px; | |
| font-size: 1.1rem; | |
| } | |
| .click-indicator { | |
| position: absolute; | |
| top: -5px; | |
| right: -5px; | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background-color: #ef4444; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 0.6rem; | |
| font-weight: bold; | |
| } | |
| .modal-overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background-color: rgba(0, 0, 0, 0.7); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| z-index: 2000; | |
| } | |
| .modal-content { | |
| background-color: var(--dark); | |
| border-radius: 10px; | |
| width: 90%; | |
| max-width: 500px; | |
| max-height: 90vh; | |
| overflow-y: auto; | |
| padding: 20px; | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); | |
| } | |
| /* Animation pour les clics */ | |
| @keyframes clickAnimation { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(0.9); } | |
| 100% { transform: scale(1); } | |
| } | |
| .click-animation { | |
| animation: clickAnimation 0.2s ease; | |
| } | |
| /* Styles pour le tutoriel */ | |
| .tutorial-step { | |
| display: none; | |
| } | |
| .tutorial-step.active { | |
| display: block; | |
| } | |
| /* Styles pour la barre de tâches */ | |
| .taskbar { | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| height: 60px; | |
| background-color: var(--dark); | |
| border-top: 1px solid var(--secondary); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-around; | |
| z-index: 100; | |
| } | |
| .taskbar-btn { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 5px 10px; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| } | |
| .taskbar-btn:hover { | |
| background-color: rgba(79, 70, 229, 0.2); | |
| } | |
| .taskbar-btn i { | |
| font-size: 1.2rem; | |
| margin-bottom: 3px; | |
| } | |
| .taskbar-btn span { | |
| font-size: 0.7rem; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container mx-auto px-4 pb-20"> | |
| <header class="py-6 border-b border-gray-700"> | |
| <div class="flex justify-between items-center"> | |
| <h1 class="text-2xl font-bold text-indigo-400"> | |
| <i class="fas fa-robot mr-2"></i>Auto-Clic Avancé | |
| </h1> | |
| <button id="helpBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg"> | |
| <i class="fas fa-question-circle mr-2"></i>Aide | |
| </button> | |
| </div> | |
| </header> | |
| <div class="mt-6 flex justify-between items-center"> | |
| <h2 class="text-xl font-semibold">Vos boutons d'auto-clic</h2> | |
| <button id="addBtn" class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg"> | |
| <i class="fas fa-plus mr-2"></i>Ajouter un bouton | |
| </button> | |
| </div> | |
| <div id="buttonsContainer" class="mt-6 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> | |
| <!-- Les boutons seront ajoutés ici dynamiquement --> | |
| </div> | |
| <!-- Barre de tâches flottante --> | |
| <div id="floatingBar" class="floating-bar"> | |
| <div id="floatingToggle" class="floating-button bg-indigo-600 text-white"> | |
| <i class="fas fa-bolt"></i> | |
| </div> | |
| </div> | |
| <!-- Barre de tâches fixe en bas --> | |
| <div class="taskbar"> | |
| <div class="taskbar-btn" id="startAllBtn"> | |
| <i class="fas fa-play"></i> | |
| <span>Tout démarrer</span> | |
| </div> | |
| <div class="taskbar-btn" id="stopAllBtn"> | |
| <i class="fas fa-stop"></i> | |
| <span>Tout arrêter</span> | |
| </div> | |
| <div class="taskbar-btn" id="profilesBtn"> | |
| <i class="fas fa-save"></i> | |
| <span>Profils</span> | |
| </div> | |
| <div class="taskbar-btn" id="toggleTaskbarBtn"> | |
| <i class="fas fa-tasks"></i> | |
| <span>Barre flottante</span> | |
| </div> | |
| </div> | |
| <!-- Modals --> | |
| <!-- Modal d'ajout/modification de bouton --> | |
| <div id="buttonModal" class="modal-overlay hidden"> | |
| <div class="modal-content"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-semibold" id="modalTitle">Ajouter un bouton</h3> | |
| <button id="closeModal" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Nom du bouton</label> | |
| <input type="text" id="buttonName" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Intervalle entre clics (secondes)</label> | |
| <input type="number" id="clickInterval" min="0.1" step="0.1" value="1" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Nombre de clics</label> | |
| <div class="flex space-x-2"> | |
| <select id="clickCountType" class="flex-1 bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"> | |
| <option value="finite">Nombre défini</option> | |
| <option value="infinite">Infini</option> | |
| </select> | |
| <input type="number" id="clickCount" min="1" value="10" class="flex-1 bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Type de clic</label> | |
| <select id="clickType" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"> | |
| <option value="single">Clic simple</option> | |
| <option value="double">Double clic</option> | |
| <option value="long">Clic long (1s)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Taille du bouton</label> | |
| <div class="flex space-x-2"> | |
| <button type="button" data-size="small" class="size-btn flex-1 bg-gray-700 hover:bg-gray-600 border border-gray-600 rounded-lg px-3 py-2">Petit</button> | |
| <button type="button" data-size="medium" class="size-btn flex-1 bg-indigo-600 hover:bg-indigo-700 border border-indigo-600 rounded-lg px-3 py-2">Moyen</button> | |
| <button type="button" data-size="large" class="size-btn flex-1 bg-gray-700 hover:bg-gray-600 border border-gray-600 rounded-lg px-3 py-2">Grand</button> | |
| </div> | |
| </div> | |
| <div id="sequenceContainer" class="hidden"> | |
| <label class="block text-sm font-medium mb-1">Déclencher après ce bouton</label> | |
| <select id="nextButton" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"> | |
| <option value="">Aucun</option> | |
| <!-- Les boutons seront ajoutés ici dynamiquement --> | |
| </select> | |
| </div> | |
| <div class="pt-4"> | |
| <button id="saveButton" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg"> | |
| Enregistrer | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Modal des profils --> | |
| <div id="profilesModal" class="modal-overlay hidden"> | |
| <div class="modal-content"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-semibold">Gestion des profils</h3> | |
| <button id="closeProfilesModal" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Nom du profil</label> | |
| <div class="flex space-x-2"> | |
| <input type="text" id="profileName" class="flex-1 bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"> | |
| <button id="saveProfileBtn" class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg"> | |
| <i class="fas fa-save mr-2"></i>Enregistrer | |
| </button> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Profils sauvegardés</label> | |
| <div id="profilesList" class="bg-gray-700 border border-gray-600 rounded-lg max-h-40 overflow-y-auto"> | |
| <!-- Les profils seront listés ici dynamiquement --> | |
| </div> | |
| </div> | |
| <div class="pt-4 flex space-x-2"> | |
| <button id="loadProfileBtn" class="flex-1 bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg"> | |
| <i class="fas fa-folder-open mr-2"></i>Charger | |
| </button> | |
| <button id="deleteProfileBtn" class="flex-1 bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg"> | |
| <i class="fas fa-trash-alt mr-2"></i>Supprimer | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Modal d'aide/tutoriel --> | |
| <div id="helpModal" class="modal-overlay hidden"> | |
| <div class="modal-content"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-semibold">Comment utiliser Auto-Clic Avancé</h3> | |
| <button id="closeHelpModal" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="space-y-4"> | |
| <div class="tutorial-step active" data-step="1"> | |
| <h4 class="font-medium text-indigo-400">1. Ajouter un bouton</h4> | |
| <p class="text-sm text-gray-300">Cliquez sur "Ajouter un bouton" pour créer un nouveau bouton d'auto-clic. Vous pouvez personnaliser son nom, l'intervalle entre les clics, le nombre de clics et le type de clic.</p> | |
| <div class="flex justify-center mt-4"> | |
| <img src="https://via.placeholder.com/300x150?text=Ajouter+un+bouton" alt="Ajouter un bouton" class="rounded-lg border border-gray-600"> | |
| </div> | |
| </div> | |
| <div class="tutorial-step" data-step="2"> | |
| <h4 class="font-medium text-indigo-400">2. Configurer les paramètres</h4> | |
| <p class="text-sm text-gray-300">Dans la fenêtre de configuration, vous pouvez définir :</p> | |
| <ul class="text-sm text-gray-300 list-disc pl-5 mt-2"> | |
| <li>L'intervalle entre les clics (en secondes)</li> | |
| <li>Le nombre de clics (défini ou infini)</li> | |
| <li>Le type de clic (simple, double ou long)</li> | |
| <li>La taille du bouton (petit, moyen ou grand)</li> | |
| </ul> | |
| </div> | |
| <div class="tutorial-step" data-step="3"> | |
| <h4 class="font-medium text-indigo-400">3. Créer des séquences</h4> | |
| <p class="text-sm text-gray-300">Vous pouvez lier plusieurs boutons pour créer des séquences. Par exemple, le bouton A peut déclencher le bouton B une fois son exécution terminée.</p> | |
| <div class="flex justify-center mt-4"> | |
| <img src="https://via.placeholder.com/300x150?text=Créer+des+séquences" alt="Créer des séquences" class="rounded-lg border border-gray-600"> | |
| </div> | |
| </div> | |
| <div class="tutorial-step" data-step="4"> | |
| <h4 class="font-medium text-indigo-400">4. Utiliser la barre de tâches</h4> | |
| <p class="text-sm text-gray-300">Activez la barre de tâches flottante pour contrôler vos boutons depuis n'importe quelle application. La barre reste visible même en changeant d'onglet.</p> | |
| <div class="flex justify-center mt-4"> | |
| <img src="https://via.placeholder.com/300x150?text=Barre+de+tâches" alt="Barre de tâches" class="rounded-lg border border-gray-600"> | |
| </div> | |
| </div> | |
| <div class="pt-4 flex justify-between"> | |
| <button id="prevTutorialStep" class="bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-lg"> | |
| <i class="fas fa-arrow-left mr-2"></i>Précédent | |
| </button> | |
| <button id="nextTutorialStep" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg"> | |
| Suivant<i class="fas fa-arrow-right ml-2"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Variables globales | |
| let buttons = []; | |
| let activeButtons = {}; | |
| let currentButtonId = null; | |
| let isTaskbarVisible = false; | |
| let currentTutorialStep = 1; | |
| const totalTutorialSteps = 4; | |
| // DOM Elements | |
| const buttonsContainer = document.getElementById('buttonsContainer'); | |
| const addBtn = document.getElementById('addBtn'); | |
| const buttonModal = document.getElementById('buttonModal'); | |
| const closeModal = document.getElementById('closeModal'); | |
| const modalTitle = document.getElementById('modalTitle'); | |
| const saveButton = document.getElementById('saveButton'); | |
| const buttonName = document.getElementById('buttonName'); | |
| const clickInterval = document.getElementById('clickInterval'); | |
| const clickCountType = document.getElementById('clickCountType'); | |
| const clickCount = document.getElementById('clickCount'); | |
| const clickType = document.getElementById('clickType'); | |
| const sizeBtns = document.querySelectorAll('.size-btn'); | |
| const nextButton = document.getElementById('nextButton'); | |
| const sequenceContainer = document.getElementById('sequenceContainer'); | |
| const startAllBtn = document.getElementById('startAllBtn'); | |
| const stopAllBtn = document.getElementById('stopAllBtn'); | |
| const profilesBtn = document.getElementById('profilesBtn'); | |
| const toggleTaskbarBtn = document.getElementById('toggleTaskbarBtn'); | |
| const floatingBar = document.getElementById('floatingBar'); | |
| const floatingToggle = document.getElementById('floatingToggle'); | |
| const profilesModal = document.getElementById('profilesModal'); | |
| const closeProfilesModal = document.getElementById('closeProfilesModal'); | |
| const profileName = document.getElementById('profileName'); | |
| const saveProfileBtn = document.getElementById('saveProfileBtn'); | |
| const profilesList = document.getElementById('profilesList'); | |
| const loadProfileBtn = document.getElementById('loadProfileBtn'); | |
| const deleteProfileBtn = document.getElementById('deleteProfileBtn'); | |
| const helpBtn = document.getElementById('helpBtn'); | |
| const helpModal = document.getElementById('helpModal'); | |
| const closeHelpModal = document.getElementById('closeHelpModal'); | |
| const prevTutorialStep = document.getElementById('prevTutorialStep'); | |
| const nextTutorialStep = document.getElementById('nextTutorialStep'); | |
| const tutorialSteps = document.querySelectorAll('.tutorial-step'); | |
| // Initialisation | |
| document.addEventListener('DOMContentLoaded', () => { | |
| loadButtons(); | |
| updateNextButtonOptions(); | |
| // Charger les boutons depuis le localStorage | |
| const savedButtons = localStorage.getItem('autoClickButtons'); | |
| if (savedButtons) { | |
| buttons = JSON.parse(savedButtons); | |
| renderButtons(); | |
| } | |
| // Charger l'état de la barre de tâches | |
| const savedTaskbarState = localStorage.getItem('taskbarVisible'); | |
| if (savedTaskbarState === 'true') { | |
| toggleTaskbar(); | |
| } | |
| }); | |
| // Événements | |
| addBtn.addEventListener('click', () => { | |
| currentButtonId = null; | |
| modalTitle.textContent = 'Ajouter un bouton'; | |
| buttonName.value = ''; | |
| clickInterval.value = '1'; | |
| clickCountType.value = 'finite'; | |
| clickCount.value = '10'; | |
| clickType.value = 'single'; | |
| document.querySelector('.size-btn[data-size="medium"]').click(); | |
| sequenceContainer.classList.add('hidden'); | |
| buttonModal.classList.remove('hidden'); | |
| }); | |
| closeModal.addEventListener('click', () => { | |
| buttonModal.classList.add('hidden'); | |
| }); | |
| clickCountType.addEventListener('change', (e) => { | |
| clickCount.disabled = e.target.value === 'infinite'; | |
| }); | |
| sizeBtns.forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| sizeBtns.forEach(b => { | |
| b.classList.remove('bg-indigo-600', 'border-indigo-600'); | |
| b.classList.add('bg-gray-700', 'border-gray-600'); | |
| }); | |
| btn.classList.remove('bg-gray-700', 'border-gray-600'); | |
| btn.classList.add('bg-indigo-600', 'border-indigo-600'); | |
| }); | |
| }); | |
| saveButton.addEventListener('click', () => { | |
| const name = buttonName.value.trim() || `Bouton ${buttons.length + 1}`; | |
| const interval = parseFloat(clickInterval.value) || 1; | |
| const countType = clickCountType.value; | |
| const count = countType === 'finite' ? parseInt(clickCount.value) || 10 : Infinity; | |
| const type = clickType.value; | |
| const size = document.querySelector('.size-btn.bg-indigo-600').dataset.size; | |
| const nextBtnId = nextButton.value || null; | |
| const buttonData = { | |
| id: currentButtonId || Date.now().toString(), | |
| name, | |
| interval, | |
| countType, | |
| count, | |
| type, | |
| size, | |
| nextBtnId, | |
| clicks: 0, | |
| isActive: false | |
| }; | |
| if (currentButtonId) { | |
| // Mettre à jour le bouton existant | |
| const index = buttons.findIndex(b => b.id === currentButtonId); | |
| if (index !== -1) { | |
| buttons[index] = buttonData; | |
| } | |
| } else { | |
| // Ajouter un nouveau bouton | |
| buttons.push(buttonData); | |
| } | |
| saveButtons(); | |
| renderButtons(); | |
| buttonModal.classList.add('hidden'); | |
| }); | |
| startAllBtn.addEventListener('click', () => { | |
| buttons.forEach(button => { | |
| if (!button.isActive) { | |
| startButton(button.id); | |
| } | |
| }); | |
| }); | |
| stopAllBtn.addEventListener('click', () => { | |
| buttons.forEach(button => { | |
| if (button.isActive) { | |
| stopButton(button.id); | |
| } | |
| }); | |
| }); | |
| profilesBtn.addEventListener('click', () => { | |
| showProfilesModal(); | |
| }); | |
| toggleTaskbarBtn.addEventListener('click', () => { | |
| toggleTaskbar(); | |
| }); | |
| floatingToggle.addEventListener('click', () => { | |
| toggleFloatingBar(); | |
| }); | |
| helpBtn.addEventListener('click', () => { | |
| helpModal.classList.remove('hidden'); | |
| }); | |
| closeHelpModal.addEventListener('click', () => { | |
| helpModal.classList.add('hidden'); | |
| }); | |
| prevTutorialStep.addEventListener('click', () => { | |
| if (currentTutorialStep > 1) { | |
| currentTutorialStep--; | |
| updateTutorialSteps(); | |
| } | |
| }); | |
| nextTutorialStep.addEventListener('click', () => { | |
| if (currentTutorialStep < totalTutorialSteps) { | |
| currentTutorialStep++; | |
| updateTutorialSteps(); | |
| } | |
| }); | |
| // Fonctions | |
| function renderButtons() { | |
| buttonsContainer.innerHTML = ''; | |
| buttons.forEach(button => { | |
| const buttonElement = document.createElement('div'); | |
| buttonElement.className = 'bg-gray-800 border border-gray-700 rounded-lg p-4 relative'; | |
| buttonElement.dataset.id = button.id; | |
| let countDisplay = button.countType === 'infinite' ? '∞' : `${button.clicks}/${button.count}`; | |
| buttonElement.innerHTML = ` | |
| <div class="flex justify-between items-start mb-2"> | |
| <h3 class="font-medium text-lg">${button.name}</h3> | |
| <span class="text-xs bg-gray-700 px-2 py-1 rounded">${button.size === 'small' ? 'Petit' : button.size === 'medium' ? 'Moyen' : 'Grand'}</span> | |
| </div> | |
| <div class="grid grid-cols-2 gap-2 text-sm mb-3"> | |
| <div> | |
| <span class="text-gray-400">Intervalle:</span> | |
| <span>${button.interval}s</span> | |
| </div> | |
| <div> | |
| <span class="text-gray-400">Type:</span> | |
| <span>${button.type === 'single' ? 'Simple' : button.type === 'double' ? 'Double' : 'Long'}</span> | |
| </div> | |
| <div> | |
| <span class="text-gray-400">Clics:</span> | |
| <span>${countDisplay}</span> | |
| </div> | |
| <div> | |
| <span class="text-gray-400">État:</span> | |
| <span class="${button.isActive ? 'text-green-400' : 'text-red-400'}">${button.isActive ? 'Actif' : 'Inactif'}</span> | |
| </div> | |
| </div> | |
| <div class="flex space-x-2"> | |
| <button class="start-btn flex-1 bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded-lg text-sm" ${button.isActive ? 'disabled' : ''}> | |
| <i class="fas fa-play mr-1"></i>Démarrer | |
| </button> | |
| <button class="stop-btn flex-1 bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded-lg text-sm" ${!button.isActive ? 'disabled' : ''}> | |
| <i class="fas fa-stop mr-1"></i>Arrêter | |
| </button> | |
| </div> | |
| <div class="mt-3 flex justify-between"> | |
| <button class="edit-btn text-indigo-400 hover:text-indigo-300 text-sm"> | |
| <i class="fas fa-edit mr-1"></i>Modifier | |
| </button> | |
| <button class="delete-btn text-red-400 hover:text-red-300 text-sm"> | |
| <i class="fas fa-trash-alt mr-1"></i>Supprimer | |
| </button> | |
| </div> | |
| ${button.nextBtnId ? ` | |
| <div class="mt-2 text-xs text-gray-400"> | |
| <i class="fas fa-arrow-down mr-1"></i>Déclenchera: ${buttons.find(b => b.id === button.nextBtnId)?.name || 'Bouton suivant'} | |
| </div> | |
| ` : ''} | |
| `; | |
| buttonsContainer.appendChild(buttonElement); | |
| // Ajouter les événements | |
| const startBtn = buttonElement.querySelector('.start-btn'); | |
| const stopBtn = buttonElement.querySelector('.stop-btn'); | |
| const editBtn = buttonElement.querySelector('.edit-btn'); | |
| const deleteBtn = buttonElement.querySelector('.delete-btn'); | |
| startBtn.addEventListener('click', () => startButton(button.id)); | |
| stopBtn.addEventListener('click', () => stopButton(button.id)); | |
| editBtn.addEventListener('click', () => editButton(button.id)); | |
| deleteBtn.addEventListener('click', () => deleteButton(button.id)); | |
| }); | |
| updateFloatingBar(); | |
| } | |
| function startButton(buttonId) { | |
| const button = buttons.find(b => b.id === buttonId); | |
| if (!button || button.isActive) return; | |
| button.isActive = true; | |
| button.clicks = 0; | |
| saveButtons(); | |
| renderButtons(); | |
| let clickCount = 0; | |
| const maxClicks = button.count; | |
| // Simuler un clic | |
| function simulateClick() { | |
| if (!button.isActive) return; | |
| // Animation de clic | |
| const buttonElement = document.querySelector(`[data-id="${button.id}"]`); | |
| if (buttonElement) { | |
| buttonElement.classList.add('click-animation'); | |
| setTimeout(() => { | |
| buttonElement.classList.remove('click-animation'); | |
| }, 200); | |
| } | |
| // Mettre à jour le compteur | |
| clickCount++; | |
| button.clicks = clickCount; | |
| // Mettre à jour l'affichage | |
| const clickDisplay = buttonElement?.querySelector('span:contains("Clics:") + span'); | |
| if (clickDisplay) { | |
| clickDisplay.textContent = button.countType === 'infinite' ? | |
| `∞ (${clickCount})` : `${clickCount}/${button.count}`; | |
| } | |
| // Vérifier si on a atteint le nombre maximum de clics | |
| if (clickCount >= maxClicks && maxClicks !== Infinity) { | |
| stopButton(buttonId); | |
| // Démarrer le bouton suivant si configuré | |
| if (button.nextBtnId) { | |
| setTimeout(() => { | |
| startButton(button.nextBtnId); | |
| }, 1000); | |
| } | |
| return; | |
| } | |
| // Planifier le prochain clic | |
| activeButtons[buttonId] = setTimeout(simulateClick, button.interval * 1000); | |
| } | |
| // Démarrer le premier clic immédiatement | |
| simulateClick(); | |
| } | |
| function stopButton(buttonId) { | |
| const button = buttons.find(b => b.id === buttonId); | |
| if (!button || !button.isActive) return; | |
| button.isActive = false; | |
| clearTimeout(activeButtons[buttonId]); | |
| delete activeButtons[buttonId]; | |
| saveButtons(); | |
| renderButtons(); | |
| } | |
| function editButton(buttonId) { | |
| const button = buttons.find(b => b.id === buttonId); | |
| if (!button) return; | |
| currentButtonId = buttonId; | |
| modalTitle.textContent = 'Modifier le bouton'; | |
| buttonName.value = button.name; | |
| clickInterval.value = button.interval; | |
| clickCountType.value = button.countType; | |
| clickCount.value = button.countType === 'infinite' ? '10' : button.count; | |
| clickCount.disabled = button.countType === 'infinite'; | |
| clickType.value = button.type; | |
| // Sélectionner la taille | |
| sizeBtns.forEach(btn => { | |
| if (btn.dataset.size === button.size) { | |
| btn.classList.remove('bg-gray-700', 'border-gray-600'); | |
| btn.classList.add('bg-indigo-600', 'border-indigo-600'); | |
| } else { | |
| btn.classList.remove('bg-indigo-600', 'border-indigo-600'); | |
| btn.classList.add('bg-gray-700', 'border-gray-600'); | |
| } | |
| }); | |
| // Configurer la séquence | |
| if (button.nextBtnId) { | |
| sequenceContainer.classList.remove('hidden'); | |
| nextButton.value = button.nextBtnId; | |
| } else { | |
| sequenceContainer.classList.add('hidden'); | |
| } | |
| buttonModal.classList.remove('hidden'); | |
| } | |
| function deleteButton(buttonId) { | |
| if (confirm('Êtes-vous sûr de vouloir supprimer ce bouton ?')) { | |
| stopButton(buttonId); | |
| buttons = buttons.filter(b => b.id !== buttonId); | |
| saveButtons(); | |
| renderButtons(); | |
| updateNextButtonOptions(); | |
| } | |
| } | |
| function saveButtons() { | |
| localStorage.setItem('autoClickButtons', JSON.stringify(buttons)); | |
| } | |
| function loadButtons() { | |
| const savedButtons = localStorage.getItem('autoClickButtons'); | |
| if (savedButtons) { | |
| buttons = JSON.parse(savedButtons); | |
| renderButtons(); | |
| } | |
| } | |
| function updateNextButtonOptions() { | |
| nextButton.innerHTML = '<option value="">Aucun</option>'; | |
| buttons.forEach(button => { | |
| if (button.id !== currentButtonId) { | |
| const option = document.createElement('option'); | |
| option.value = button.id; | |
| option.textContent = button.name; | |
| nextButton.appendChild(option); | |
| } | |
| }); | |
| // Afficher/masquer le conteneur de séquence | |
| sequenceContainer.classList.toggle('hidden', buttons.length <= 1); | |
| } | |
| function toggleTaskbar() { | |
| isTaskbarVisible = !isTaskbarVisible; | |
| localStorage.setItem('taskbarVisible', isTaskbarVisible.toString()); | |
| if (isTaskbarVisible) { | |
| floatingBar.classList.add('floating-bar-expanded'); | |
| updateFloatingBar(); | |
| } else { | |
| floatingBar.classList.remove('floating-bar-expanded'); | |
| floatingBar.innerHTML = '<div id="floatingToggle" class="floating-button bg-indigo-600 text-white"><i class="fas fa-bolt"></i></div>'; | |
| document.getElementById('floatingToggle').addEventListener('click', toggleFloatingBar); | |
| } | |
| } | |
| function toggleFloatingBar() { | |
| if (floatingBar.classList.contains('floating-bar-expanded')) { | |
| floatingBar.classList.remove('floating-bar-expanded'); | |
| floatingBar.innerHTML = '<div id="floatingToggle" class="floating-button bg-indigo-600 text-white"><i class="fas fa-bolt"></i></div>'; | |
| document.getElementById('floatingToggle').addEventListener('click', toggleFloatingBar); | |
| } else { | |
| floatingBar.classList.add('floating-bar-expanded'); | |
| updateFloatingBar(); | |
| } | |
| } | |
| function updateFloatingBar() { | |
| if (!floatingBar.classList.contains('floating-bar-expanded')) return; | |
| floatingBar.innerHTML = ` | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-medium">Barre de tâches</h3> | |
| <button id="closeFloatingBar" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div id="floatingButtons" class="grid grid-cols-2 gap-2"> | |
| ${buttons.map(button => ` | |
| <div class="relative"> | |
| <button | |
| class="floating-task-btn w-full ${button.isActive ? 'bg-green-600' : 'bg-indigo-600'} text-white rounded-lg p-2 text-sm flex flex-col items-center justify-center ${button.size === 'small' ? 'btn-small' : button.size === 'medium' ? 'btn-medium' : 'btn-large'}" | |
| data-id="${button.id}" | |
| > | |
| ${button.name} | |
| <span class="text-xs mt-1">${button.interval}s</span> | |
| </button> | |
| ${button.isActive ? `<div class="click-indicator">${button.clicks}</div>` : ''} | |
| </div> | |
| `).join('')} | |
| </div> | |
| <div class="mt-3 flex space-x-2"> | |
| <button id="floatingStartAll" class="flex-1 bg-green-600 hover:bg-green-700 text-white px-2 py-1 rounded-lg text-sm"> | |
| <i class="fas fa-play mr-1"></i>Tout démarrer | |
| </button> | |
| <button id="floatingStopAll" class="flex-1 bg-red-600 hover:bg-red-700 text-white px-2 py-1 rounded-lg text-sm"> | |
| <i class="fas fa-stop mr-1"></i>Tout arrêter | |
| </button> | |
| </div> | |
| `; | |
| // Ajouter les événements | |
| document.getElementById('closeFloatingBar').addEventListener('click', toggleFloatingBar); | |
| document.getElementById('floatingStartAll').addEventListener('click', () => { | |
| buttons.forEach(button => { | |
| if (!button.isActive) { | |
| startButton(button.id); | |
| } | |
| }); | |
| }); | |
| document.getElementById('floatingStopAll').addEventListener('click', () => { | |
| buttons.forEach(button => { | |
| if (button.isActive) { | |
| stopButton(button.id); | |
| } | |
| }); | |
| }); | |
| document.querySelectorAll('.floating-task-btn').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| const buttonId = btn.dataset.id; | |
| const button = buttons.find(b => b.id === buttonId); | |
| if (button.isActive) { | |
| stopButton(buttonId); | |
| } else { | |
| startButton(buttonId); | |
| } | |
| }); | |
| }); | |
| } | |
| function showProfilesModal() { | |
| profilesModal.classList.remove('hidden'); | |
| updateProfilesList(); | |
| } | |
| function updateProfilesList() { | |
| profilesList.innerHTML = ''; | |
| const profiles = JSON.parse(localStorage.getItem('autoClickProfiles') || '{}'); | |
| for (const [name, data] of Object.entries(profiles)) { | |
| const profileElement = document.createElement('div'); | |
| profileElement.className = 'flex justify-between items-center p-2 border-b border-gray-600'; | |
| profileElement.innerHTML = ` | |
| <span>${name}</span> | |
| <span class="text-xs text-gray-400">${data.buttons.length} bouton(s)</span> | |
| `; | |
| profileElement.addEventListener('click', () => { | |
| // Sélectionner ce profil | |
| profileName.value = name; | |
| // Désélectionner les autres | |
| document.querySelectorAll('#profilesList > div').forEach(el => { | |
| el.classList.remove('bg-indigo-600'); | |
| }); | |
| profileElement.classList.add('bg-indigo-600'); | |
| }); | |
| profilesList.appendChild(profileElement); | |
| } | |
| if (Object.keys(profiles).length === 0) { | |
| profilesList.innerHTML = '<div class="p-4 text-center text-gray-400">Aucun profil sauvegardé</div>'; | |
| } | |
| } | |
| saveProfileBtn.addEventListener('click', () => { | |
| const name = profileName.value.trim(); | |
| if (!name) return; | |
| const profiles = JSON.parse(localStorage.getItem('autoClickProfiles') || '{}'); | |
| profiles[name] = { | |
| buttons: buttons, | |
| date: new Date().toISOString() | |
| }; | |
| localStorage.setItem('autoClickProfiles', JSON.stringify(profiles)); | |
| updateProfilesList(); | |
| // Afficher un message de succès | |
| alert(`Profil "${name}" sauvegardé avec succès !`); | |
| }); | |
| loadProfileBtn.addEventListener('click', () => { | |
| const name = profileName.value.trim(); | |
| if (!name) return; | |
| const profiles = JSON.parse(localStorage.getItem('autoClickProfiles') || '{}'); | |
| if (!profiles[name]) return; | |
| // Arrêter tous les boutons actifs | |
| buttons.forEach(button => { | |
| if (button.isActive) { | |
| stopButton(button.id); | |
| } | |
| }); | |
| // Charger le nouveau profil | |
| buttons = profiles[name].buttons; | |
| saveButtons(); | |
| renderButtons(); | |
| updateNextButtonOptions(); | |
| // Fermer la modal | |
| profilesModal.classList.add('hidden'); | |
| // Afficher un message de succès | |
| alert(`Profil "${name}" chargé avec succès !`); | |
| }); | |
| deleteProfileBtn.addEventListener('click', () => { | |
| const name = profileName.value.trim(); | |
| if (!name) return; | |
| if (confirm(`Êtes-vous sûr de vouloir supprimer le profil "${name}" ?`)) { | |
| const profiles = JSON.parse(localStorage.getItem('autoClickProfiles') || '{}'); | |
| delete profiles[name]; | |
| localStorage.setItem('autoClickProfiles', JSON.stringify(profiles)); | |
| updateProfilesList(); | |
| profileName.value = ''; | |
| // Afficher un message de succès | |
| alert(`Profil "${name}" supprimé avec succès !`); | |
| } | |
| }); | |
| closeProfilesModal.addEventListener('click', () => { | |
| profilesModal.classList.add('hidden'); | |
| }); | |
| function updateTutorialSteps() { | |
| tutorialSteps.forEach(step => { | |
| step.classList.remove('active'); | |
| if (parseInt(step.dataset.step) === currentTutorialStep) { | |
| step.classList.add('active'); | |
| } | |
| }); | |
| // Mettre à jour les boutons de navigation | |
| prevTutorialStep.disabled = currentTutorialStep === 1; | |
| nextTutorialStep.disabled = currentTutorialStep === totalTutorialSteps; | |
| if (currentTutorialStep === totalTutorialSteps) { | |
| nextTutorialStep.textContent = 'Terminer'; | |
| nextTutorialStep.innerHTML = 'Terminer<i class="fas fa-check ml-2"></i>'; | |
| } else { | |
| nextTutorialStep.textContent = 'Suivant'; | |
| nextTutorialStep.innerHTML = 'Suivant<i class="fas fa-arrow-right ml-2"></i>'; | |
| } | |
| } | |
| // Gérer la fermeture des modals en cliquant à l'extérieur | |
| document.addEventListener('click', (e) => { | |
| if (e.target.classList.contains('modal-overlay')) { | |
| buttonModal.classList.add('hidden'); | |
| profilesModal.classList.add('hidden'); | |
| helpModal.classList.add('hidden'); | |
| } | |
| }); | |
| </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=Chasme/auto-clic-2" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |