Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: indeterminate mode? #21

Open
James-E-A opened this issue Dec 5, 2024 · 1 comment
Open

Feature request: indeterminate mode? #21

James-E-A opened this issue Dec 5, 2024 · 1 comment

Comments

@James-E-A
Copy link

I want to display a global "pending" status whenever my app gets disconnected from the server, but I hate to use the default "fake progress" mode as that's actively misleading to users, but I didn't see anything already in the code for an indeterminate progress bar.


A more recent development is the indeterminate progress bar, which is used in situations where the extent of the task is unknown or the progress of the task cannot be determined in a way that could be expressed as a percentage. This bar uses motion or some other indicator (such as a barber's pole pattern) to show that progress is taking place, rather than using the size of the filled portion to show the total amount of progress, making it more like a throbber than a progress bar.

https://en.wikipedia.org/wiki/Progress_bar#:~:text=indeterminate%20progress%20bar

@James-E-A
Copy link
Author

James-E-A commented Dec 5, 2024

draft of what that might look like

diff --git a/assets/vendor/topbar.js b/assets/vendor/topbar.js
index 4195727..6d05c15 100644
--- a/assets/vendor/topbar.js
+++ b/assets/vendor/topbar.js
@@ -40,6 +40,7 @@
     progressTimerId = null,
     fadeTimerId = null,
     delayTimerId = null,
+    throbberPeriod = 500,
     addEvent = function (elem, type, handler) {
       if (elem.addEventListener) elem.addEventListener(type, handler, false);
       else if (elem.attachEvent) elem.attachEvent("on" + type, handler);
@@ -67,16 +68,32 @@
       ctx.shadowBlur = options.shadowBlur;
       ctx.shadowColor = options.shadowColor;
 
-      var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
-      for (var stop in options.barColors)
-        lineGradient.addColorStop(stop, options.barColors[stop]);
+      var lineGradient, strokeEndX;
+      if (!isNaN(currentProgress)) {
+        // regular bar
+        lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0)
+        for (var stop in options.barColors)
+          lineGradient.addColorStop(stop, options.barColors[stop]);
+        strokeEndX = Math.ceil(currentProgress * canvas.width);
+      } else {
+        // indeterminate bar
+        var stop_, phase = (performance.now() % throbberPeriod) / throbberPeriod;
+        // FIXME this overkill triple-render is causing a bit of overhead
+        // in the canvas "stroke" and "moveTo" steps
+        lineGradient = ctx.createLinearGradient(-canvas.width, 0, 2*canvas.width, 0)
+        for (var stop in options.barColors) {
+          stop_ = (Number(stop) + phase) % 1.0;
+          lineGradient.addColorStop(stop_ / 3, options.barColors[stop]);
+          lineGradient.addColorStop((stop_ + 1) / 3, options.barColors[stop]);
+          lineGradient.addColorStop((stop_ + 2) / 3, options.barColors[stop]);
+        }
+        strokeEndX = canvas.width;
+      }
+
       ctx.lineWidth = options.barThickness;
       ctx.beginPath();
       ctx.moveTo(0, options.barThickness / 2);
-      ctx.lineTo(
-        Math.ceil(currentProgress * canvas.width),
-        options.barThickness / 2
-      );
+      ctx.lineTo(strokeEndX, options.barThickness / 2);
       ctx.strokeStyle = lineGradient;
       ctx.stroke();
     },
@@ -108,13 +125,22 @@
           canvas.style.opacity = 1;
           canvas.style.display = "block";
           topbar.progress(0);
-          if (options.autoRun) {
+          if (options.autoRun === true) {
             (function loop() {
               progressTimerId = window.requestAnimationFrame(loop);
               topbar.progress(
                 "+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
               );
             })();
+          } else if (options.autoRun === "indeterminate") {
+            currentProgress = NaN;
+            (function loop() {
+              if (isNaN(currentProgress)) {
+                progressTimerId = window.requestAnimationFrame(loop);
+                topbar.progress(currentProgress);
+              }
+              // no "else"; if the progress later gets set manually, we abort this loop
+            })();
           }
         }
       },
@@ -126,7 +152,7 @@
               ? currentProgress
               : 0) + parseFloat(to);
         }
-        currentProgress = to > 1 ? 1 : to;
+        currentProgress = Math.min(to, 1);
         repaint();
         return currentProgress;
       },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant