1/**
2 * @license MIT
3 * topbar 3.0.0
4 * http://buunguyen.github.io/topbar
5 * Copyright (c) 2024 Buu Nguyen
6 */
7(function (window, document) {
8 "use strict";
9
10 var canvas,
11 currentProgress,
12 showing,
13 progressTimerId = null,
14 fadeTimerId = null,
15 delayTimerId = null,
16 addEvent = function (elem, type, handler) {
17 if (elem.addEventListener) elem.addEventListener(type, handler, false);
18 else if (elem.attachEvent) elem.attachEvent("on" + type, handler);
19 else elem["on" + type] = handler;
20 },
21 options = {
22 autoRun: true,
23 barThickness: 3,
24 barColors: {
25 0: "rgba(26, 188, 156, .9)",
26 ".25": "rgba(52, 152, 219, .9)",
27 ".50": "rgba(241, 196, 15, .9)",
28 ".75": "rgba(230, 126, 34, .9)",
29 "1.0": "rgba(211, 84, 0, .9)",
30 },
31 shadowBlur: 10,
32 shadowColor: "rgba(0, 0, 0, .6)",
33 className: null,
34 },
35 repaint = function () {
36 canvas.width = window.innerWidth;
37 canvas.height = options.barThickness * 5; // need space for shadow
38
39 var ctx = canvas.getContext("2d");
40 ctx.shadowBlur = options.shadowBlur;
41 ctx.shadowColor = options.shadowColor;
42
43 var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
44 for (var stop in options.barColors)
45 lineGradient.addColorStop(stop, options.barColors[stop]);
46 ctx.lineWidth = options.barThickness;
47 ctx.beginPath();
48 ctx.moveTo(0, options.barThickness / 2);
49 ctx.lineTo(
50 Math.ceil(currentProgress * canvas.width),
51 options.barThickness / 2
52 );
53 ctx.strokeStyle = lineGradient;
54 ctx.stroke();
55 },
56 createCanvas = function () {
57 canvas = document.createElement("canvas");
58 var style = canvas.style;
59 style.position = "fixed";
60 style.top = style.left = style.right = style.margin = style.padding = 0;
61 style.zIndex = 100001;
62 style.display = "none";
63 if (options.className) canvas.classList.add(options.className);
64 addEvent(window, "resize", repaint);
65 },
66 topbar = {
67 config: function (opts) {
68 for (var key in opts)
69 if (options.hasOwnProperty(key)) options[key] = opts[key];
70 },
71 show: function (delay) {
72 if (showing) return;
73 if (delay) {
74 if (delayTimerId) return;
75 delayTimerId = setTimeout(() => topbar.show(), delay);
76 } else {
77 showing = true;
78 if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId);
79 if (!canvas) createCanvas();
80 if (!canvas.parentElement) document.body.appendChild(canvas);
81 canvas.style.opacity = 1;
82 canvas.style.display = "block";
83 topbar.progress(0);
84 if (options.autoRun) {
85 (function loop() {
86 progressTimerId = window.requestAnimationFrame(loop);
87 topbar.progress(
88 "+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
89 );
90 })();
91 }
92 }
93 },
94 progress: function (to) {
95 if (typeof to === "undefined") return currentProgress;
96 if (typeof to === "string") {
97 to =
98 (to.indexOf("+") >= 0 || to.indexOf("-") >= 0
99 ? currentProgress
100 : 0) + parseFloat(to);
101 }
102 currentProgress = to > 1 ? 1 : to;
103 repaint();
104 return currentProgress;
105 },
106 hide: function () {
107 clearTimeout(delayTimerId);
108 delayTimerId = null;
109 if (!showing) return;
110 showing = false;
111 if (progressTimerId != null) {
112 window.cancelAnimationFrame(progressTimerId);
113 progressTimerId = null;
114 }
115 (function loop() {
116 if (topbar.progress("+.1") >= 1) {
117 canvas.style.opacity -= 0.05;
118 if (canvas.style.opacity <= 0.05) {
119 canvas.style.display = "none";
120 fadeTimerId = null;
121 return;
122 }
123 }
124 fadeTimerId = window.requestAnimationFrame(loop);
125 })();
126 },
127 };
128
129 if (typeof module === "object" && typeof module.exports === "object") {
130 module.exports = topbar;
131 } else if (typeof define === "function" && define.amd) {
132 define(function () {
133 return topbar;
134 });
135 } else {
136 this.topbar = topbar;
137 }
138}.call(this, window, document));