ProgressUI-Module

Reusable progress UI module

Dit script moet niet direct worden geïnstalleerd - het is een bibliotheek voor andere scripts om op te nemen met de meta-richtlijn // @require https://update.greasyfork.org/scripts/530526/1558038/ProgressUI-Module.js

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name        ProgressUI Module
// @namespace   Violentmonkey Scripts
// @description Reusable progress UI module
// @version     0.7
// @author      maanimis
// @run-at      document-idle
// @license     MIT
// ==/UserScript==

(function () {
'use strict';

function _extends() {
  return _extends = Object.assign ? Object.assign.bind() : function (n) {
    for (var e = 1; e < arguments.length; e++) {
      var t = arguments[e];
      for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
    }
    return n;
  }, _extends.apply(null, arguments);
}

const DEFAULT_THEMES = {
  light: {
    background: '#f8f8f8',
    text: '#333333',
    border: '#e0e0e0',
    progressBg: '#e0e0e0',
    progressFill: '#4CAF50',
    shadow: 'rgba(0,0,0,0.2)'
  },
  dark: {
    background: '#2a2a2a',
    text: '#ffffff',
    border: '#444444',
    progressBg: '#444444',
    progressFill: '#4CAF50',
    shadow: 'rgba(0,0,0,0.5)'
  }
};
class ProgressUI {
  constructor(config = {}) {
    this.config = this.validateConfig(config);
    this.elements = this.createUIElements();
    this.applyStyles();
    this.attachToDOM();
  }
  update(message, percent) {
    if (!this.isMounted) return false;
    if (message) {
      this.elements.status.textContent = message;
    }
    if (typeof percent === 'number') {
      const clamped = Math.max(0, Math.min(100, percent));
      this.elements.progressBar.style.width = `${clamped}%`;
      this.elements.percentText.textContent = `${Math.round(clamped)}%`;
    }
    return true;
  }
  scheduleCleanup(delay = 3000, fade = true) {
    window.clearTimeout(this.removalTimeout);
    this.removalTimeout = window.setTimeout(() => this.remove(fade), delay);
  }
  remove(fade = true) {
    if (!this.isMounted) return;
    if (fade) {
      this.elements.container.style.opacity = '0';
      window.setTimeout(() => this.detachFromDOM(), 300);
    } else {
      this.detachFromDOM();
    }
  }
  get isMounted() {
    return document.body.contains(this.elements.container);
  }
  static showQuick(message, config = {}) {
    var _config$closable, _config$duration, _config$percent;
    const instance = new ProgressUI(_extends({}, config, {
      closable: (_config$closable = config.closable) != null ? _config$closable : false,
      duration: (_config$duration = config.duration) != null ? _config$duration : 3000
    }));
    instance.update(message, (_config$percent = config.percent) != null ? _config$percent : 100);
    instance.scheduleCleanup(config.duration, true);
    return instance;
  }
  validateConfig(config) {
    var _config$position, _config$width, _config$theme, _config$title, _config$closable2, _config$colors, _config$duration2;
    return {
      position: (_config$position = config.position) != null ? _config$position : 'top-right',
      width: (_config$width = config.width) != null ? _config$width : '300px',
      theme: (_config$theme = config.theme) != null ? _config$theme : 'light',
      title: (_config$title = config.title) != null ? _config$title : '',
      closable: (_config$closable2 = config.closable) != null ? _config$closable2 : true,
      colors: (_config$colors = config.colors) != null ? _config$colors : {},
      duration: (_config$duration2 = config.duration) != null ? _config$duration2 : 3000
    };
  }
  createUIElements() {
    const container = document.createElement('div');
    const status = document.createElement('div');
    const progressBar = document.createElement('div');
    const percentText = document.createElement('div');
    const progressBarContainer = document.createElement('div');

    // Set up the DOM structure
    progressBarContainer.appendChild(progressBar);
    container.appendChild(status);
    container.appendChild(progressBarContainer);
    container.appendChild(percentText);

    // Add classes for easier styling (optional)
    container.classList.add('progress-ui-container');
    status.classList.add('progress-ui-status');
    progressBarContainer.classList.add('progress-ui-bar-container');
    progressBar.classList.add('progress-ui-bar');
    percentText.classList.add('progress-ui-percent');
    return {
      container,
      status,
      progressBar,
      percentText
    };
  }
  applyStyles() {
    const colors = this.getThemeColors();

    // Container styles
    Object.assign(this.elements.container.style, _extends({
      position: 'fixed',
      zIndex: '9999'
    }, this.getPositionStyles(), {
      backgroundColor: colors.background,
      color: colors.text,
      padding: '15px',
      borderRadius: '5px',
      boxShadow: `0 0 10px ${colors.shadow}`,
      width: this.config.width,
      fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
      transition: 'opacity 0.3s ease'
    }));

    // Status element
    Object.assign(this.elements.status.style, {
      marginBottom: '10px',
      fontSize: '14px',
      fontWeight: '500',
      whiteSpace: 'nowrap',
      overflow: 'hidden',
      textOverflow: 'ellipsis'
    });

    // Progress bar container
    Object.assign(this.elements.progressBar.parentElement.style, {
      width: '100%',
      backgroundColor: colors.progressBg,
      borderRadius: '4px',
      height: '10px',
      overflow: 'hidden'
    });

    // Progress bar
    Object.assign(this.elements.progressBar.style, {
      height: '100%',
      width: '0%',
      backgroundColor: colors.progressFill,
      transition: 'width 0.3s'
    });

    // Percentage text
    Object.assign(this.elements.percentText.style, {
      textAlign: 'right',
      marginTop: '5px',
      fontSize: '12px',
      fontWeight: '600'
    });
    this.addOptionalElements();
  }
  getPositionStyles() {
    const positionStyles = {};
    switch (this.config.position) {
      case 'top-left':
        positionStyles.top = '20px';
        positionStyles.left = '20px';
        break;
      case 'top-center':
        positionStyles.top = '20px';
        positionStyles.left = '50%';
        positionStyles.transform = 'translateX(-50%)';
        break;
      case 'bottom-left':
        positionStyles.bottom = '20px';
        positionStyles.left = '20px';
        break;
      case 'bottom-right':
        positionStyles.bottom = '20px';
        positionStyles.right = '20px';
        break;
      case 'bottom-center':
        positionStyles.bottom = '20px';
        positionStyles.left = '50%';
        positionStyles.transform = 'translateX(-50%)';
        break;
      case 'center':
        positionStyles.top = '50%';
        positionStyles.left = '50%';
        positionStyles.transform = 'translate(-50%, -50%)';
        break;
      default:
        // top-right
        positionStyles.top = '20px';
        positionStyles.right = '20px';
    }
    return positionStyles;
  }
  getThemeColors() {
    const baseTheme = this.config.theme === 'custom' ? DEFAULT_THEMES.light : DEFAULT_THEMES[this.config.theme];
    return _extends({}, baseTheme, this.config.colors);
  }
  addOptionalElements() {
    if (this.config.title) {
      const title = document.createElement('div');
      title.textContent = this.config.title;
      Object.assign(title.style, {
        marginBottom: '10px',
        fontSize: '16px',
        fontWeight: 'bold',
        paddingRight: '15px'
      });
      this.elements.container.prepend(title);
    }
    if (this.config.closable) {
      const closeButton = document.createElement('div');
      closeButton.innerHTML = '×';
      Object.assign(closeButton.style, {
        position: 'absolute',
        top: '5px',
        right: '8px',
        fontSize: '18px',
        fontWeight: 'bold',
        cursor: 'pointer',
        opacity: '0.6'
      });
      closeButton.addEventListener('click', () => this.remove());
      this.elements.container.appendChild(closeButton);
    }
  }
  attachToDOM() {
    document.querySelectorAll('.progress-ui-container').forEach(el => el.remove());
    document.body.appendChild(this.elements.container);
  }
  detachFromDOM() {
    if (this.isMounted) {
      document.body.removeChild(this.elements.container);
    }
  }
}
const globalContext = window;
globalContext.ProgressUI = ProgressUI;

// const globalContext =
//   typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;

})();