/
RoditelevVV
/
web-static-labs
Обзор
Документация
Войти
/
RoditelevVV
/
web-static-labs
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
html/lab5/task6/script.js
391 строка
14 KB
karpov
finish lab3, lab4
12 мар 2026, 08:19
12 мар 2026, 08:19
74cd197
Код
Авторство
О чём код?
class PasswordGenerator { constructor() { // Наборы символов this.charSets = { digits: '0123456789', lowercase: 'abcdefghijklmnopqrstuvwxyz', uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', special: '!@#$%^&*()_+-=[]{}|;:,.<>?' }; this.history = JSON.parse(localStorage.getItem('passwordHistory')) || []; this.initializeElements(); this.setupEventListeners(); this.updateHistoryDisplay(); } initializeElements() { // Элементы настроек this.passwordLength = document.getElementById('passwordLength'); this.lengthValue = document.getElementById('lengthValue'); this.useDigits = document.getElementById('useDigits'); this.useLowercase = document.getElementById('useLowercase'); this.useUppercase = document.getElementById('useUppercase'); this.useSpecial = document.getElementById('useSpecial'); // Элементы результата this.generateBtn = document.getElementById('generateBtn'); this.passwordOutput = document.getElementById('passwordOutput'); this.copyBtn = document.getElementById('copyBtn'); // Элементы сложности this.strengthText = document.getElementById('strengthText'); this.strengthFill = document.getElementById('strengthFill'); // Элементы истории this.passwordHistory = document.getElementById('passwordHistory'); this.clearHistoryBtn = document.getElementById('clearHistoryBtn'); } setupEventListeners() { // Слайдер длины this.passwordLength.addEventListener('input', () => { this.lengthValue.textContent = this.passwordLength.value; }); // Кнопка генерации this.generateBtn.addEventListener('click', () => { this.generatePassword(); }); // Кнопка копирования this.copyBtn.addEventListener('click', () => { this.copyToClipboard(); }); // Кнопка очистки истории this.clearHistoryBtn.addEventListener('click', () => { this.clearHistory(); }); // Генерация при изменении настроек (опционально) [this.useDigits, this.useLowercase, this.useUppercase, this.useSpecial].forEach(checkbox => { checkbox.addEventListener('change', () => { this.validateCheckboxes(); }); }); } validateCheckboxes() { const checkboxes = [this.useDigits, this.useLowercase, this.useUppercase, this.useSpecial]; const checkedCount = checkboxes.filter(checkbox => checkbox.checked).length; if (checkedCount === 0) { // Если ни один чекбокс не выбран, автоматически выбираем цифры this.useDigits.checked = true; } } generatePassword() { const length = parseInt(this.passwordLength.value); const selectedChars = this.getSelectedCharacterSet(); if (selectedChars.length === 0) { this.showError('Выберите хотя бы один тип символов'); return; } let password = ''; // Гарантируем, что в пароле будет хотя бы по одному символу из каждого выбранного набора const guaranteedChars = this.getGuaranteedCharacters(); password += guaranteedChars; // Заполняем оставшуюся длину случайными символами for (let i = password.length; i < length; i++) { const randomIndex = Math.floor(Math.random() * selectedChars.length); password += selectedChars[randomIndex]; } // Перемешиваем пароль для случайного порядка символов password = this.shuffleString(password); this.displayPassword(password); this.updateStrengthIndicator(password); this.addToHistory(password); } getSelectedCharacterSet() { let chars = ''; if (this.useDigits.checked) { chars += this.charSets.digits; } if (this.useLowercase.checked) { chars += this.charSets.lowercase; } if (this.useUppercase.checked) { chars += this.charSets.uppercase; } if (this.useSpecial.checked) { chars += this.charSets.special; } return chars; } getGuaranteedCharacters() { let guaranteed = ''; if (this.useDigits.checked) { const randomIndex = Math.floor(Math.random() * this.charSets.digits.length); guaranteed += this.charSets.digits[randomIndex]; } if (this.useLowercase.checked) { const randomIndex = Math.floor(Math.random() * this.charSets.lowercase.length); guaranteed += this.charSets.lowercase[randomIndex]; } if (this.useUppercase.checked) { const randomIndex = Math.floor(Math.random() * this.charSets.uppercase.length); guaranteed += this.charSets.uppercase[randomIndex]; } if (this.useSpecial.checked) { const randomIndex = Math.floor(Math.random() * this.charSets.special.length); guaranteed += this.charSets.special[randomIndex]; } return guaranteed; } shuffleString(string) { const array = string.split(''); for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array.join(''); } displayPassword(password) { this.passwordOutput.textContent = password; this.passwordOutput.classList.add('updated'); // Активируем кнопку копирования this.copyBtn.disabled = false; setTimeout(() => { this.passwordOutput.classList.remove('updated'); }, 300); } updateStrengthIndicator(password) { let strength = 0; const length = password.length; // Оценка на основе длины if (length >= 32) strength += 40; else if (length >= 24) strength += 30; else if (length >= 16) strength += 20; else if (length >= 12) strength += 15; else if (length >= 8) strength += 10; else strength += 5; // Оценка на основе разнообразия символов const hasDigits = /\d/.test(password); const hasLowercase = /[a-z]/.test(password); const hasUppercase = /[A-Z]/.test(password); const hasSpecial = /[^a-zA-Z0-9]/.test(password); const charTypeCount = [hasDigits, hasLowercase, hasUppercase, hasSpecial].filter(Boolean).length; strength += charTypeCount * 15; // Определяем уровень сложности let strengthLevel, strengthClass; if (strength >= 80) { strengthLevel = 'Очень надежный'; strengthClass = 'strength-strong'; } else if (strength >= 60) { strengthLevel = 'Надежный'; strengthClass = 'strength-good'; } else if (strength >= 40) { strengthLevel = 'Средний'; strengthClass = 'strength-fair'; } else { strengthLevel = 'Слабый'; strengthClass = 'strength-weak'; } this.strengthText.textContent = strengthLevel; this.strengthFill.className = 'strength-fill ' + strengthClass; } async copyToClipboard() { const password = this.passwordOutput.textContent; if (!password || password === 'Нажмите "Сгенерировать пароль"') { this.showError('Нет пароля для копирования'); return; } try { await navigator.clipboard.writeText(password); this.showNotification('Пароль скопирован в буфер обмена!', 'success'); } catch (err) { // Fallback для старых браузеров const textArea = document.createElement('textarea'); textArea.value = password; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); this.showNotification('Пароль скопирован в буфер обмена!', 'success'); } catch (fallbackErr) { this.showError('Не удалось скопировать пароль'); } document.body.removeChild(textArea); } } addToHistory(password) { const historyItem = { password: password, timestamp: new Date().toLocaleString('ru-RU'), length: password.length }; this.history.unshift(historyItem); // Ограничиваем историю 10 последними паролями if (this.history.length > 10) { this.history.pop(); } this.saveHistory(); this.updateHistoryDisplay(); } updateHistoryDisplay() { this.passwordHistory.innerHTML = ''; if (this.history.length === 0) { this.passwordHistory.innerHTML = '<div class="empty-history">История паролей пуста</div>'; return; } this.history.forEach((item, index) => { const historyItem = document.createElement('div'); historyItem.className = 'history-item'; historyItem.innerHTML = ` <div> <div class="history-password">${item.password}</div> <small style="color: #7f8c8d;">${item.timestamp} • ${item.length} симв.</small> </div> <button class="history-copy" data-index="${index}"> 📋 Копировать </button> `; this.passwordHistory.appendChild(historyItem); }); // Назначаем обработчики для кнопок копирования в истории this.passwordHistory.querySelectorAll('.history-copy').forEach(btn => { btn.addEventListener('click', (e) => { const index = e.target.dataset.index; this.copyFromHistory(index); }); }); } async copyFromHistory(index) { const password = this.history[index].password; try { await navigator.clipboard.writeText(password); this.showNotification('Пароль скопирован из истории!', 'success'); } catch (err) { this.showError('Не удалось скопировать пароль'); } } clearHistory() { if (this.history.length === 0) return; if (confirm('Очистить историю паролей?')) { this.history = []; this.saveHistory(); this.updateHistoryDisplay(); this.showNotification('История очищена', 'info'); } } saveHistory() { localStorage.setItem('passwordHistory', JSON.stringify(this.history)); } showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; notification.style.cssText = ` position: fixed; top: 20px; right: 20px; padding: 15px 20px; border-radius: 8px; color: white; font-weight: 500; z-index: 1000; animation: slideIn 0.3s ease-out; max-width: 300px; `; if (type === 'success') { notification.style.background = 'linear-gradient(135deg, #00b09b, #96c93d)'; } else if (type === 'error') { notification.style.background = 'linear-gradient(135deg, #ff416c, #ff4b2b)'; } else { notification.style.background = 'linear-gradient(135deg, #3498db, #2980b9)'; } document.body.appendChild(notification); setTimeout(() => { notification.style.animation = 'slideOut 0.3s ease-in'; setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 300); }, 3000); // Добавляем стили для анимаций если их нет if (!document.querySelector('#notification-styles')) { const style = document.createElement('style'); style.id = 'notification-styles'; style.textContent = ` @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes slideOut { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 0; } } `; document.head.appendChild(style); } } showError(message) { this.showNotification(message, 'error'); } } // Инициализация генератора паролей при загрузке страницы document.addEventListener('DOMContentLoaded', () => { new PasswordGenerator(); });