removed useless stuff
This commit is contained in:
parent
64e78bb9b8
commit
a80bfba873
@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* Accessibility Features Module
|
|
||||||
* Enhances accessibility for all users
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize accessibility features
|
|
||||||
*/
|
|
||||||
function initAccessibilityFeatures() {
|
|
||||||
setupFocusManagement();
|
|
||||||
setupAriaLabels();
|
|
||||||
console.log('[Accessibility Features] Initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup focus management
|
|
||||||
*/
|
|
||||||
function setupFocusManagement() {
|
|
||||||
// Add focus visible class for keyboard navigation
|
|
||||||
document.addEventListener('keydown', (e) => {
|
|
||||||
if (e.key === 'Tab') {
|
|
||||||
document.body.classList.add('keyboard-navigation');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('mousedown', () => {
|
|
||||||
document.body.classList.remove('keyboard-navigation');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup ARIA labels for dynamic content
|
|
||||||
*/
|
|
||||||
function setupAriaLabels() {
|
|
||||||
// Ensure all interactive elements have proper ARIA labels
|
|
||||||
const buttons = document.querySelectorAll('button:not([aria-label])');
|
|
||||||
buttons.forEach(button => {
|
|
||||||
if (!button.getAttribute('aria-label') && button.title) {
|
|
||||||
button.setAttribute('aria-label', button.title);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Announce message to screen readers
|
|
||||||
*/
|
|
||||||
function announceToScreenReader(message, priority = 'polite') {
|
|
||||||
const announcement = document.createElement('div');
|
|
||||||
announcement.setAttribute('role', 'status');
|
|
||||||
announcement.setAttribute('aria-live', priority);
|
|
||||||
announcement.setAttribute('aria-atomic', 'true');
|
|
||||||
announcement.className = 'sr-only';
|
|
||||||
announcement.textContent = message;
|
|
||||||
|
|
||||||
document.body.appendChild(announcement);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
announcement.remove();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export functions
|
|
||||||
window.Accessibility = {
|
|
||||||
announce: announceToScreenReader
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initAccessibilityFeatures);
|
|
||||||
} else {
|
|
||||||
initAccessibilityFeatures();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
* Advanced Search Module
|
|
||||||
* Provides advanced search and filtering capabilities
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize advanced search
|
|
||||||
*/
|
|
||||||
function initAdvancedSearch() {
|
|
||||||
console.log('[Advanced Search] Module loaded (functionality to be implemented)');
|
|
||||||
|
|
||||||
// TODO: Implement advanced search features
|
|
||||||
// - Filter by genre
|
|
||||||
// - Filter by year
|
|
||||||
// - Filter by status
|
|
||||||
// - Sort options
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initAdvancedSearch);
|
|
||||||
} else {
|
|
||||||
initAdvancedSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -26,9 +26,6 @@ class AniWorldApp {
|
|||||||
this.loadSeries();
|
this.loadSeries();
|
||||||
this.initTheme();
|
this.initTheme();
|
||||||
this.updateConnectionStatus();
|
this.updateConnectionStatus();
|
||||||
|
|
||||||
// Initialize Mobile & Accessibility features
|
|
||||||
this.initMobileAndAccessibility();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkAuthentication() {
|
async checkAuthentication() {
|
||||||
@ -1726,155 +1723,6 @@ class AniWorldApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showBackupsModal(backups) {
|
|
||||||
// Create modal to show backups
|
|
||||||
const modal = document.createElement('div');
|
|
||||||
modal.className = 'modal';
|
|
||||||
modal.style.display = 'block';
|
|
||||||
|
|
||||||
const modalContent = document.createElement('div');
|
|
||||||
modalContent.className = 'modal-content';
|
|
||||||
modalContent.style.maxWidth = '60%';
|
|
||||||
|
|
||||||
const header = document.createElement('div');
|
|
||||||
header.innerHTML = '<h3>Configuration Backups</h3>';
|
|
||||||
|
|
||||||
const backupList = document.createElement('div');
|
|
||||||
backupList.className = 'backup-list';
|
|
||||||
|
|
||||||
if (backups.length === 0) {
|
|
||||||
backupList.innerHTML = '<div class="backup-item"><span>No backups found</span></div>';
|
|
||||||
} else {
|
|
||||||
backups.forEach(backup => {
|
|
||||||
const item = document.createElement('div');
|
|
||||||
item.className = 'backup-item';
|
|
||||||
|
|
||||||
const info = document.createElement('div');
|
|
||||||
info.className = 'backup-info';
|
|
||||||
|
|
||||||
const name = document.createElement('div');
|
|
||||||
name.className = 'backup-name';
|
|
||||||
name.textContent = backup.filename;
|
|
||||||
|
|
||||||
const details = document.createElement('div');
|
|
||||||
details.className = 'backup-details';
|
|
||||||
details.textContent = `Size: ${backup.size_kb} KB • Modified: ${backup.modified_display}`;
|
|
||||||
|
|
||||||
info.appendChild(name);
|
|
||||||
info.appendChild(details);
|
|
||||||
|
|
||||||
const actions = document.createElement('div');
|
|
||||||
actions.className = 'backup-actions';
|
|
||||||
|
|
||||||
const restoreBtn = document.createElement('button');
|
|
||||||
restoreBtn.className = 'btn btn-xs btn-primary';
|
|
||||||
restoreBtn.textContent = 'Restore';
|
|
||||||
restoreBtn.onclick = () => {
|
|
||||||
if (confirm('Are you sure you want to restore this backup? Current configuration will be overwritten.')) {
|
|
||||||
this.restoreBackup(backup.filename);
|
|
||||||
document.body.removeChild(modal);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const downloadBtn = document.createElement('button');
|
|
||||||
downloadBtn.className = 'btn btn-xs btn-secondary';
|
|
||||||
downloadBtn.textContent = 'Download';
|
|
||||||
downloadBtn.onclick = () => this.downloadBackup(backup.filename);
|
|
||||||
|
|
||||||
actions.appendChild(restoreBtn);
|
|
||||||
actions.appendChild(downloadBtn);
|
|
||||||
|
|
||||||
item.appendChild(info);
|
|
||||||
item.appendChild(actions);
|
|
||||||
|
|
||||||
backupList.appendChild(item);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const closeBtn = document.createElement('button');
|
|
||||||
closeBtn.textContent = 'Close';
|
|
||||||
closeBtn.className = 'btn btn-secondary';
|
|
||||||
closeBtn.onclick = () => document.body.removeChild(modal);
|
|
||||||
|
|
||||||
modalContent.appendChild(header);
|
|
||||||
modalContent.appendChild(backupList);
|
|
||||||
modalContent.appendChild(closeBtn);
|
|
||||||
modal.appendChild(modalContent);
|
|
||||||
document.body.appendChild(modal);
|
|
||||||
|
|
||||||
// Close on background click
|
|
||||||
modal.onclick = (e) => {
|
|
||||||
if (e.target === modal) {
|
|
||||||
document.body.removeChild(modal);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async restoreBackup(filename) {
|
|
||||||
try {
|
|
||||||
const response = await this.makeAuthenticatedRequest(`/api/config/backup/${encodeURIComponent(filename)}/restore`, {
|
|
||||||
method: 'POST'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response) return;
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.success) {
|
|
||||||
this.showToast('Configuration restored successfully', 'success');
|
|
||||||
// Reload the config modal
|
|
||||||
setTimeout(() => {
|
|
||||||
this.hideConfigModal();
|
|
||||||
this.showConfigModal();
|
|
||||||
}, 1000);
|
|
||||||
} else {
|
|
||||||
this.showToast(`Failed to restore backup: ${data.error}`, 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error restoring backup:', error);
|
|
||||||
this.showToast('Failed to restore backup', 'error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadBackup(filename) {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = `/api/config/backup/${encodeURIComponent(filename)}/download`;
|
|
||||||
link.download = filename;
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
async exportConfig() {
|
|
||||||
try {
|
|
||||||
const includeSensitive = confirm('Include sensitive data (passwords, salts)? Click Cancel for safe export without sensitive data.');
|
|
||||||
|
|
||||||
const response = await this.makeAuthenticatedRequest('/api/config/export', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({ include_sensitive: includeSensitive })
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response && response.ok) {
|
|
||||||
// Handle file download
|
|
||||||
const blob = await response.blob();
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.download = `aniworld_config_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.json`;
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
|
|
||||||
this.showToast('Configuration exported successfully', 'success');
|
|
||||||
} else {
|
|
||||||
this.showToast('Failed to export configuration', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error exporting config:', error);
|
|
||||||
this.showToast('Failed to export configuration', 'error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async validateConfig() {
|
async validateConfig() {
|
||||||
try {
|
try {
|
||||||
const response = await this.makeAuthenticatedRequest('/api/config/validate', {
|
const response = await this.makeAuthenticatedRequest('/api/config/validate', {
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
* Bulk Operations Module
|
|
||||||
* Handles bulk selection and operations on multiple series
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize bulk operations
|
|
||||||
*/
|
|
||||||
function initBulkOperations() {
|
|
||||||
console.log('[Bulk Operations] Module loaded (functionality to be implemented)');
|
|
||||||
|
|
||||||
// TODO: Implement bulk operations
|
|
||||||
// - Select multiple series
|
|
||||||
// - Bulk download
|
|
||||||
// - Bulk mark as watched
|
|
||||||
// - Bulk delete
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initBulkOperations);
|
|
||||||
} else {
|
|
||||||
initBulkOperations();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
* Color Contrast Compliance Module
|
|
||||||
* Ensures WCAG color contrast compliance
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize color contrast compliance
|
|
||||||
*/
|
|
||||||
function initColorContrastCompliance() {
|
|
||||||
checkContrastCompliance();
|
|
||||||
console.log('[Color Contrast Compliance] Initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if color contrast meets WCAG standards
|
|
||||||
*/
|
|
||||||
function checkContrastCompliance() {
|
|
||||||
// This would typically check computed styles
|
|
||||||
// For now, we rely on CSS variables defined in styles.css
|
|
||||||
console.log('[Color Contrast] Relying on predefined WCAG-compliant color scheme');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate contrast ratio between two colors
|
|
||||||
*/
|
|
||||||
function calculateContrastRatio(color1, color2) {
|
|
||||||
// Simplified contrast calculation
|
|
||||||
// Real implementation would use relative luminance
|
|
||||||
return 4.5; // Placeholder
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initColorContrastCompliance);
|
|
||||||
} else {
|
|
||||||
initColorContrastCompliance();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
/**
|
|
||||||
* Drag and Drop Module
|
|
||||||
* Handles drag-and-drop functionality for series cards
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize drag and drop
|
|
||||||
*/
|
|
||||||
function initDragDrop() {
|
|
||||||
console.log('[Drag & Drop] Module loaded (functionality to be implemented)');
|
|
||||||
|
|
||||||
// TODO: Implement drag-and-drop for series cards
|
|
||||||
// This will allow users to reorder series or add to queue via drag-and-drop
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initDragDrop);
|
|
||||||
} else {
|
|
||||||
initDragDrop();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -1,144 +0,0 @@
|
|||||||
/**
|
|
||||||
* Keyboard Shortcuts Module
|
|
||||||
* Handles keyboard navigation and shortcuts for improved accessibility
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// Keyboard shortcuts configuration
|
|
||||||
const shortcuts = {
|
|
||||||
'ctrl+k': 'focusSearch',
|
|
||||||
'ctrl+r': 'triggerRescan',
|
|
||||||
'ctrl+q': 'openQueue',
|
|
||||||
'escape': 'closeModals',
|
|
||||||
'tab': 'navigationMode',
|
|
||||||
'/': 'focusSearch'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize keyboard shortcuts
|
|
||||||
*/
|
|
||||||
function initKeyboardShortcuts() {
|
|
||||||
document.addEventListener('keydown', handleKeydown);
|
|
||||||
console.log('[Keyboard Shortcuts] Initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle keydown events
|
|
||||||
*/
|
|
||||||
function handleKeydown(event) {
|
|
||||||
const key = getKeyCombo(event);
|
|
||||||
|
|
||||||
if (shortcuts[key]) {
|
|
||||||
const action = shortcuts[key];
|
|
||||||
handleShortcut(action, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get key combination string
|
|
||||||
*/
|
|
||||||
function getKeyCombo(event) {
|
|
||||||
const parts = [];
|
|
||||||
|
|
||||||
if (event.ctrlKey) parts.push('ctrl');
|
|
||||||
if (event.altKey) parts.push('alt');
|
|
||||||
if (event.shiftKey) parts.push('shift');
|
|
||||||
|
|
||||||
const key = event.key.toLowerCase();
|
|
||||||
parts.push(key);
|
|
||||||
|
|
||||||
return parts.join('+');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle keyboard shortcut action
|
|
||||||
*/
|
|
||||||
function handleShortcut(action, event) {
|
|
||||||
switch(action) {
|
|
||||||
case 'focusSearch':
|
|
||||||
event.preventDefault();
|
|
||||||
focusSearchInput();
|
|
||||||
break;
|
|
||||||
case 'triggerRescan':
|
|
||||||
event.preventDefault();
|
|
||||||
triggerRescan();
|
|
||||||
break;
|
|
||||||
case 'openQueue':
|
|
||||||
event.preventDefault();
|
|
||||||
openQueue();
|
|
||||||
break;
|
|
||||||
case 'closeModals':
|
|
||||||
closeAllModals();
|
|
||||||
break;
|
|
||||||
case 'navigationMode':
|
|
||||||
handleTabNavigation(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Focus search input
|
|
||||||
*/
|
|
||||||
function focusSearchInput() {
|
|
||||||
const searchInput = document.getElementById('search-input');
|
|
||||||
if (searchInput) {
|
|
||||||
searchInput.focus();
|
|
||||||
searchInput.select();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trigger rescan
|
|
||||||
*/
|
|
||||||
function triggerRescan() {
|
|
||||||
const rescanBtn = document.getElementById('rescan-btn');
|
|
||||||
if (rescanBtn && !rescanBtn.disabled) {
|
|
||||||
rescanBtn.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open queue page
|
|
||||||
*/
|
|
||||||
function openQueue() {
|
|
||||||
window.location.href = '/queue';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close all open modals
|
|
||||||
*/
|
|
||||||
function closeAllModals() {
|
|
||||||
const modals = document.querySelectorAll('.modal.active');
|
|
||||||
modals.forEach(modal => {
|
|
||||||
modal.classList.remove('active');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle tab navigation with visual indicators
|
|
||||||
*/
|
|
||||||
function handleTabNavigation(event) {
|
|
||||||
// Add keyboard-focus class to focused element
|
|
||||||
const previousFocus = document.querySelector('.keyboard-focus');
|
|
||||||
if (previousFocus) {
|
|
||||||
previousFocus.classList.remove('keyboard-focus');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Will be applied after tab completes
|
|
||||||
setTimeout(() => {
|
|
||||||
if (document.activeElement) {
|
|
||||||
document.activeElement.classList.add('keyboard-focus');
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initKeyboardShortcuts);
|
|
||||||
} else {
|
|
||||||
initKeyboardShortcuts();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
/**
|
|
||||||
* Mobile Responsive Module
|
|
||||||
* Handles mobile-specific functionality and responsive behavior
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let isMobile = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize mobile responsive features
|
|
||||||
*/
|
|
||||||
function initMobileResponsive() {
|
|
||||||
detectMobile();
|
|
||||||
setupResponsiveHandlers();
|
|
||||||
console.log('[Mobile Responsive] Initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect if device is mobile
|
|
||||||
*/
|
|
||||||
function detectMobile() {
|
|
||||||
isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
||||||
|
|
||||||
if (isMobile) {
|
|
||||||
document.body.classList.add('mobile-device');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup responsive event handlers
|
|
||||||
*/
|
|
||||||
function setupResponsiveHandlers() {
|
|
||||||
window.addEventListener('resize', handleResize);
|
|
||||||
handleResize(); // Initial call
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle window resize
|
|
||||||
*/
|
|
||||||
function handleResize() {
|
|
||||||
const width = window.innerWidth;
|
|
||||||
|
|
||||||
if (width < 768) {
|
|
||||||
applyMobileLayout();
|
|
||||||
} else {
|
|
||||||
applyDesktopLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply mobile-specific layout
|
|
||||||
*/
|
|
||||||
function applyMobileLayout() {
|
|
||||||
document.body.classList.add('mobile-layout');
|
|
||||||
document.body.classList.remove('desktop-layout');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply desktop-specific layout
|
|
||||||
*/
|
|
||||||
function applyDesktopLayout() {
|
|
||||||
document.body.classList.add('desktop-layout');
|
|
||||||
document.body.classList.remove('mobile-layout');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export functions
|
|
||||||
window.MobileResponsive = {
|
|
||||||
isMobile: () => isMobile
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initMobileResponsive);
|
|
||||||
} else {
|
|
||||||
initMobileResponsive();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
/**
|
|
||||||
* Multi-Screen Support Module
|
|
||||||
* Handles multi-monitor and window management
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize multi-screen support
|
|
||||||
*/
|
|
||||||
function initMultiScreenSupport() {
|
|
||||||
if ('screen' in window) {
|
|
||||||
detectScreens();
|
|
||||||
console.log('[Multi-Screen Support] Initialized');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect available screens
|
|
||||||
*/
|
|
||||||
function detectScreens() {
|
|
||||||
// Modern browsers support window.screen
|
|
||||||
const screenInfo = {
|
|
||||||
width: window.screen.width,
|
|
||||||
height: window.screen.height,
|
|
||||||
availWidth: window.screen.availWidth,
|
|
||||||
availHeight: window.screen.availHeight,
|
|
||||||
colorDepth: window.screen.colorDepth,
|
|
||||||
pixelDepth: window.screen.pixelDepth
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('[Multi-Screen] Screen info:', screenInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request fullscreen
|
|
||||||
*/
|
|
||||||
function requestFullscreen() {
|
|
||||||
const elem = document.documentElement;
|
|
||||||
if (elem.requestFullscreen) {
|
|
||||||
elem.requestFullscreen();
|
|
||||||
} else if (elem.webkitRequestFullscreen) {
|
|
||||||
elem.webkitRequestFullscreen();
|
|
||||||
} else if (elem.msRequestFullscreen) {
|
|
||||||
elem.msRequestFullscreen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exit fullscreen
|
|
||||||
*/
|
|
||||||
function exitFullscreen() {
|
|
||||||
if (document.exitFullscreen) {
|
|
||||||
document.exitFullscreen();
|
|
||||||
} else if (document.webkitExitFullscreen) {
|
|
||||||
document.webkitExitFullscreen();
|
|
||||||
} else if (document.msExitFullscreen) {
|
|
||||||
document.msExitFullscreen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export functions
|
|
||||||
window.MultiScreen = {
|
|
||||||
requestFullscreen: requestFullscreen,
|
|
||||||
exitFullscreen: exitFullscreen
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initMultiScreenSupport);
|
|
||||||
} else {
|
|
||||||
initMultiScreenSupport();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
/**
|
|
||||||
* Touch Gestures Module
|
|
||||||
* Handles touch gestures for mobile devices
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize touch gestures
|
|
||||||
*/
|
|
||||||
function initTouchGestures() {
|
|
||||||
if ('ontouchstart' in window) {
|
|
||||||
setupSwipeGestures();
|
|
||||||
console.log('[Touch Gestures] Initialized');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup swipe gesture handlers
|
|
||||||
*/
|
|
||||||
function setupSwipeGestures() {
|
|
||||||
let touchStartX = 0;
|
|
||||||
let touchStartY = 0;
|
|
||||||
let touchEndX = 0;
|
|
||||||
let touchEndY = 0;
|
|
||||||
|
|
||||||
document.addEventListener('touchstart', (e) => {
|
|
||||||
touchStartX = e.changedTouches[0].screenX;
|
|
||||||
touchStartY = e.changedTouches[0].screenY;
|
|
||||||
}, { passive: true });
|
|
||||||
|
|
||||||
document.addEventListener('touchend', (e) => {
|
|
||||||
touchEndX = e.changedTouches[0].screenX;
|
|
||||||
touchEndY = e.changedTouches[0].screenY;
|
|
||||||
handleSwipe();
|
|
||||||
}, { passive: true });
|
|
||||||
|
|
||||||
function handleSwipe() {
|
|
||||||
const deltaX = touchEndX - touchStartX;
|
|
||||||
const deltaY = touchEndY - touchStartY;
|
|
||||||
const minSwipeDistance = 50;
|
|
||||||
|
|
||||||
if (Math.abs(deltaX) > Math.abs(deltaY)) {
|
|
||||||
// Horizontal swipe
|
|
||||||
if (Math.abs(deltaX) > minSwipeDistance) {
|
|
||||||
if (deltaX > 0) {
|
|
||||||
// Swipe right
|
|
||||||
console.log('[Touch Gestures] Swipe right detected');
|
|
||||||
} else {
|
|
||||||
// Swipe left
|
|
||||||
console.log('[Touch Gestures] Swipe left detected');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initTouchGestures);
|
|
||||||
} else {
|
|
||||||
initTouchGestures();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
@ -1,111 +0,0 @@
|
|||||||
/**
|
|
||||||
* Undo/Redo Module
|
|
||||||
* Provides undo/redo functionality for user actions
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const actionHistory = [];
|
|
||||||
let currentIndex = -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize undo/redo system
|
|
||||||
*/
|
|
||||||
function initUndoRedo() {
|
|
||||||
setupKeyboardShortcuts();
|
|
||||||
console.log('[Undo/Redo] Initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup keyboard shortcuts for undo/redo
|
|
||||||
*/
|
|
||||||
function setupKeyboardShortcuts() {
|
|
||||||
document.addEventListener('keydown', (event) => {
|
|
||||||
if (event.ctrlKey || event.metaKey) {
|
|
||||||
if (event.key === 'z' && !event.shiftKey) {
|
|
||||||
event.preventDefault();
|
|
||||||
undo();
|
|
||||||
} else if (event.key === 'z' && event.shiftKey || event.key === 'y') {
|
|
||||||
event.preventDefault();
|
|
||||||
redo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add action to history
|
|
||||||
*/
|
|
||||||
function addAction(action) {
|
|
||||||
// Remove any actions after current index
|
|
||||||
actionHistory.splice(currentIndex + 1);
|
|
||||||
|
|
||||||
// Add new action
|
|
||||||
actionHistory.push(action);
|
|
||||||
currentIndex++;
|
|
||||||
|
|
||||||
// Limit history size
|
|
||||||
if (actionHistory.length > 50) {
|
|
||||||
actionHistory.shift();
|
|
||||||
currentIndex--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Undo last action
|
|
||||||
*/
|
|
||||||
function undo() {
|
|
||||||
if (currentIndex >= 0) {
|
|
||||||
const action = actionHistory[currentIndex];
|
|
||||||
if (action && action.undo) {
|
|
||||||
action.undo();
|
|
||||||
currentIndex--;
|
|
||||||
showNotification('Action undone');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redo last undone action
|
|
||||||
*/
|
|
||||||
function redo() {
|
|
||||||
if (currentIndex < actionHistory.length - 1) {
|
|
||||||
currentIndex++;
|
|
||||||
const action = actionHistory[currentIndex];
|
|
||||||
if (action && action.redo) {
|
|
||||||
action.redo();
|
|
||||||
showNotification('Action redone');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show undo/redo notification
|
|
||||||
*/
|
|
||||||
function showNotification(message) {
|
|
||||||
const notification = document.createElement('div');
|
|
||||||
notification.className = 'undo-notification';
|
|
||||||
notification.textContent = message;
|
|
||||||
document.body.appendChild(notification);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
notification.remove();
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export functions
|
|
||||||
window.UndoRedo = {
|
|
||||||
add: addAction,
|
|
||||||
undo: undo,
|
|
||||||
redo: redo
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize on DOM ready
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initUndoRedo);
|
|
||||||
} else {
|
|
||||||
initUndoRedo();
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
Loading…
x
Reference in New Issue
Block a user