SmartApp.js

DOM Magic, Simplified!

SmartApp.js is an enhanced vanilla JavaScript plugin designed for DOM manipulation, UI controls, event handling, security features, and audio management. It provides efficient methods to interact with UI elements, handle class modifications, execute panel actions, play sounds, and more.

Pro Tip: SmartApp.js is designed with security in mind, featuring built-in sanitization for class names, selectors, and data attributes.

Installation

Include the SmartApp.js script in your HTML file:

<script src="path/to/smartApp.js"></script>

Initialize the plugin:

document.addEventListener('DOMContentLoaded', function() {
appDOM.checkActiveStyles().debug(true);
});

Configuration

SmartApp.js comes with a flexible configuration system:

const config = {
debug: false,
focusDelay: 200,
defaultSoundPath: 'media/sound/',
maxClassNameLength: 50,
maxSelectorLength: 255,
fullscreenConfirmMessage: 'Do you want to enter fullscreen mode?',
selectors: {
    actionButtons: '[data-action]'
},
sound: {
    preload: false,
    volume: 1.0,
    fadeIn: false,
    fadeInDuration: 500
}
};
Important: Security limits like maxClassNameLength and maxSelectorLength help prevent DoS attacks.

Core Features

Style Management

// Reset all styles
appDOM.resetStyle();

// Check active styles
appDOM.checkActiveStyles();

Class Manipulation

// Programmatic Methods
// Toggle class
appDOM.toggleClass('html', 'nav-function-hidden');
appDOM.toggleClass('.my-element', 'active');

// Toggle Replace (swap one class for another)
appDOM.toggleReplace('.my-element', 'btn-default', 'btn-primary');
appDOM.toggleReplace('#myButton', null, 'active'); // Just add without removing

// Toggle Swap (toggle class on specific target)
appDOM.toggleSwap('html', 'nav-function-top');
appDOM.toggleSwap('.drawer', 'active');

// Chain multiple actions
appDOM
  .toggleClass('html', 'nav-function-hidden')
  .toggleReplace('#myButton', 'btn-default', 'btn-primary')
  .toggleSwap('.drawer', 'active');

// Using data attributes
<button data-action="toggle" data-class="dark-mode">Toggle Dark Mode</button>
<button data-action="toggle-replace" data-target=".btn" data-removeclass="btn-default" data-addclass="btn-primary">Update Button</button>
<button data-action="toggle-swap" data-target=".drawer" data-toggleclass="active">Toggle Drawer</button>

Security Features

Class Name Sanitization

// Sanitizes class names to prevent XSS
const sanitizedClass = security.sanitizeClassName(className);

// Only allows valid characters: a-z, A-Z, 0-9, -, _
// Removes invalid characters
// Enforces maximum length

Selector Sanitization

// Prevents CSS injection attacks
const sanitizedSelector = security.sanitizeSelector(selector);

// Blocks dangerous patterns:
// - HTML tags
// - javascript: URLs
// - data: URLs
// - Expression functions
// - Timing functions
Important: All inputs are automatically sanitized to prevent XSS and injection attacks.

Theme Management

SmartApp.js includes a built-in theme management system that handles light and dark themes:

Theme Controls

// Toggle theme programmatically
appDOM.toggleTheme();

// Using data attributes
<button data-action="toggle-theme">Toggle Theme</button>

// Check current theme
const currentTheme = document.documentElement.getAttribute('data-bs-theme');

// Theme is automatically saved to localStorage and restored on page load
// Supports Bootstrap's data-bs-theme attribute
// Toggles between 'light' and 'dark' modes
Pro Tip: Theme preferences are automatically persisted across sessions using localStorage.

Event Handlers

Available Actions

// Theme toggling
<button data-action="toggle-theme">Toggle Theme</button>

// Toggle class
<button data-action="toggle" data-class="active">Toggle</button>

// Replace class
<button data-action="toggle-replace" 
    data-target="#element"
    data-removeclass="hidden"
    data-addclass="visible">Show Element</button>

// Swap class
<button data-action="toggle-swap"
    data-target="#drawer"
    data-toggleclass="open">Toggle Drawer</button>

// Programmatic usage
// Theme
appDOM.toggleTheme();

// Class manipulation
appDOM.toggleClass('html', 'nav-function-hidden');
appDOM.toggleReplace('.button', 'btn-default', 'btn-primary');
appDOM.toggleSwap('.drawer', 'active');

// Method chaining
appDOM
    .toggleTheme()
    .toggleClass('html', 'nav-function-hidden')
    .toggleSwap('.drawer', 'active');
Pro Tip: All methods support chaining and include built-in error handling and logging.

Panel Actions

Available Panel Controls

// Panel action methods
handlers.panelActions.collapse(element);
handlers.panelActions.fullscreen(element);
handlers.panelActions.close(element);

// Example usage
document.querySelector('.panel-collapse-btn').addEventListener('click', function() {
handlers.panelActions.collapse(this);
});

// Using data attributes
<button data-action="panel-collapse">Collapse</button>
<button data-action="panel-fullscreen">Fullscreen</button>
<button data-action="panel-close">Close</button>
Pro Tip: Panel actions automatically handle tooltips and transitions.

Fullscreen Mode

Fullscreen Controls

// Fullscreen methods
fullscreenHandler.enter();
fullscreenHandler.exit();
fullscreenHandler.isFullscreen();

// Example usage
document.querySelector('.fullscreen-btn').addEventListener('click', function() {
handlers.appFullscreen();
});

Audio Features

Sound Management

// Play sound
<button data-action="playsound" data-soundfile="click.mp3">Play Sound</button>

// Pause sound
<button data-action="pausesound">Pause Sound</button>

// Preload sound
appDOM.preloadSound('background.mp3');

// Play and pause sounds programmatically
handlers.playSound(element);
handlers.pauseSound(element);
Note: Sound files are automatically cached for better performance.

Utilities

Debounce Function

const debouncedFunction = utils.debounce(() => {
// Your code here
}, 300);

Element Validation

if (utils.validateElement(element, 'Button')) {
// Element exists, proceed
}

Color Extraction

SmartApp.js includes a powerful color extraction system that automatically extracts Bootstrap colors and theme variables. This feature is particularly useful for dynamic theme switching and color management.

Color Map Structure

window.colorMap = {
    // Bootstrap category colors (primary, danger, success, warning, info)
    primary: {
        50: { 
            hex: "#e6f1fe", 
            rgb: "rgb(230, 241, 254)",
            rgba: function(opacity) { return "rgba(230, 241, 254, " + opacity + ")"; },
            values: "230, 241, 254"
        },
        100: { 
            hex: "#cce3fd", 
            rgb: "rgb(204, 227, 253)",
            rgba: function(opacity) { return "rgba(204, 227, 253, " + opacity + ")"; },
            values: "204, 227, 253"
        },
        // ... more shades up to 900
    },
    // ... other categories

    // Bootstrap theme variables
    bootstrapVars: {
        bodyBg: { 
            hex: "#ffffff", 
            rgb: "rgb(255, 255, 255)",
            rgba: function(opacity) { return "rgba(255, 255, 255, " + opacity + ")"; },
            values: "255, 255, 255" 
        },
        bodyColor: { 
            hex: "#212529", 
            rgb: "rgb(33, 37, 41)",
            rgba: function(opacity) { return "rgba(33, 37, 41, " + opacity + ")"; },
            values: "33, 37, 41"
        },
        // ... other variables
    }
};

Automatic Color Extraction

Colors are automatically extracted in these scenarios:

  • On initial page load
  • When theme is toggled between light and dark modes
  • When manually calling the extraction function
// Manual color extraction
utils.extractColors();

// Listen for color extraction completion
window.addEventListener('colorMapReady', () => {
    console.log('Colors extracted:', window.colorMap);
});

Using Extracted Colors

// Access primary color at different shades
const primaryLight = window.colorMap.primary[100].hex;
const primaryMain = window.colorMap.primary[500].hex;
const primaryDark = window.colorMap.primary[900].hex;

// Access theme variables
const bodyBg = window.colorMap.bootstrapVars.bodyBg.hex;
const bodyColor = window.colorMap.bootstrapVars.bodyColor.hex;

// Use colors with opacity (rgba)
const primaryWithOpacity = window.colorMap.primary[500].rgba(0.7); // 70% opacity
const bgWithOpacity = window.colorMap.bootstrapVars.bodyBg.rgba(0.3); // 30% opacity

// Use in CSS properties
element.style.backgroundColor = window.colorMap.primary[500].hex;
element.style.color = window.colorMap.bootstrapVars.bodyColor.hex;
element.style.boxShadow = "0 5px 15px " + window.colorMap.primary[500].rgba(0.5);
Pro Tip: Use the rgba() function for elements that need transparency. It accepts a single parameter for opacity between 0 and 1.

Usage with Libraries like ApexCharts

// Example usage with chart libraries
const chartOptions = {
    colors: [window.colorMap.primary[500].hex],
    grid: {
        borderColor: window.colorMap.bootstrapVars.bodyColor.rgba(0.2) // 20% opacity
    },
    tooltip: {
        style: {
            backgroundColor: window.colorMap.bootstrapVars.bodyBg.rgba(0.9)
        }
    }
};
Pro Tip: The color extraction system automatically updates when switching themes, ensuring your dynamic color applications stay in sync with the current theme.
Note: Color extraction relies on Bootstrap classes being properly loaded. Ensure Bootstrap CSS is loaded before attempting to extract colors.

Debugging

Logger Functions

// Enable debug mode
appDOM.debug(true);

// Logger outputs
logger.log('Info message');
logger.error('Error message');
logger.warn('Warning message');
logger.group('Group name');
logger.groupEnd();

// Logging methods
appDOM.log('This is a log message');
appDOM.warn('This is a warning');
appDOM.error('This is an error');
Pro Tip: Debug messages are prefixed with [AppDOM] for easy identification in the console.

Troubleshooting

Common Issues:
  • Class manipulation doesn't work?
    Ensure the target element exists before calling appDOM.addClass().
  • No sound is playing?
    Check if the file path is correct and ensure browser autoplay permissions allow playback.
  • Panel actions not responding?
    Verify that the data attributes are correctly set and the elements exist in the DOM.
  • Security restrictions blocking actions?
    Check the console for security warnings and ensure your selectors and class names meet the security requirements.