From b18bc644404e02b57635bfcc8258e85abb141146 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 13:44:46 +0200 Subject: Adding upstream version 1.1.1. Signed-off-by: Daniel Baumann --- public/js/progress-bar.js | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 public/js/progress-bar.js (limited to 'public/js/progress-bar.js') diff --git a/public/js/progress-bar.js b/public/js/progress-bar.js new file mode 100644 index 0000000..be24f1c --- /dev/null +++ b/public/js/progress-bar.js @@ -0,0 +1,110 @@ +(function (Icinga) { + + "use strict"; + + class ProgressBar extends Icinga.EventListener { + constructor(icinga) + { + super(icinga); + + /** + * Frame update threshold. If it reaches zero, the view is updated + * + * Currently, only every third frame is updated. + * + * @type {number} + */ + this.frameUpdateThreshold = 3; + + /** + * Threshold at which animations get smoothed out (in milliseconds) + * + * @type {number} + */ + this.smoothUpdateThreshold = 250; + + this.on('rendered', '#main > .container', this.onRendered, this); + } + + onRendered(event) + { + const _this = event.data.self; + const container = event.target; + + container.querySelectorAll('[data-animate-progress]').forEach(progress => { + const frequency = ( + (Number(progress.dataset.endTime) - Number(progress.dataset.startTime) + ) * 1000) / progress.parentElement.offsetWidth; + + _this.updateProgress( + now => _this.animateProgress(progress, now), frequency); + }); + } + + animateProgress(progress, now) + { + if (! progress.isConnected) { + return false; // Exit early if the node is removed from the DOM + } + + const durationScale = 100; + + const startTime = Number(progress.dataset.startTime); + const endTime = Number(progress.dataset.endTime); + const duration = endTime - startTime; + const end = new Date(endTime * 1000.0); + + let leftNow = durationScale * (1 - (end - now) / (duration * 1000.0)); + if (leftNow > durationScale) { + leftNow = durationScale; + } else if (leftNow < 0) { + leftNow = 0; + } + + const switchAfter = Number(progress.dataset.switchAfter); + if (! isNaN(switchAfter)) { + const switchClass = progress.dataset.switchClass; + const switchAt = new Date((startTime * 1000.0) + (switchAfter * 1000.0)); + if (now < switchAt) { + progress.classList.add(switchClass); + } else if (progress.classList.contains(switchClass)) { + progress.classList.remove(switchClass); + } + } + + const bar = progress.querySelector(':scope > .bar'); + bar.style.width = leftNow + '%'; + + return leftNow !== durationScale; + } + + updateProgress(callback, frequency, now = null) + { + if (now === null) { + now = new Date(); + } + + if (! callback(now)) { + return; + } + + if (frequency < this.smoothUpdateThreshold) { + let counter = this.frameUpdateThreshold; + const onNextFrame = timeSinceOrigin => { + if (--counter === 0) { + this.updateProgress(callback, frequency, new Date(performance.timeOrigin + timeSinceOrigin)); + } else { + requestAnimationFrame(onNextFrame); + } + }; + requestAnimationFrame(onNextFrame); + } else { + setTimeout(() => this.updateProgress(callback, frequency), frequency); + } + } + } + + Icinga.Behaviors = Icinga.Behaviors || {}; + + Icinga.Behaviors.ProgressBar = ProgressBar; +})(Icinga); -- cgit v1.2.3