Skip to content

"Timed Progress Bars": SugarCube (v2.18)#

Summary#

"Timed Progress Bars" uses the Macro.Add() function in SugarCube to introduce a new macro. Using jQuery within the definition, the new macro records arguments passed to it and creates outer and inner <div> elements with classes defined in the Story Stylesheet. Using a combination of setInterval() and setTimeout(), a timer is created based on the argument passed to the macro. The length and color of an inner <div> element is adjusted based on the remaining time each loop.

When the timer runs out, the payload of the macro is run and the length of the inner <div> element is reduced to 0.

Example#

Download

Twee Code#

:: StoryTitle
Timed Progress Bars in SugarCube

:: UserScript[script]
/*
    Macro: timedprogressbar

    Description: Show a dynamically-created "progress bar"
    that changes colors as its timer runs down.

    Original design: Akjosch (https://github.com/Akjosch)

    Arguments:
      [0]: The time to run in seconds
      [1]: The length of the progress bar in CSS units (px, em, or %)
*/
Macro.add("timedprogressbar", {
  isAsync : true,
  tags: null,
  handler: function() {
    // Filter the payload for newlines and save it for later execution
    var payload = this.payload[0].contents.replace(/\n$/, '').trim();

    // Save or generate a default duration
    var duration = (Number(this.args[0]) || 60) * 1000;

    // Save or generate a width
    var width = this.args[1] || "100%";

    // Generate a unique hash
    var hash = Math.floor(Math.random() * 0x100000000).toString(16);

    //  Create an outer ID
    var outerId = "outer_" + hash;

    // Create an inner ID
    var innerId = "inner_" + hash;

    // Create an outer div,
    // add an ID,
    // add a class,
    // change the CSS width, and
    // append to the output
    var progressbar = $("<div>")
    .attr("id", outerId)
    .addClass("progress-bar")
    .css('width', width)
    .appendTo(this.output);

    // Create an inner div,
    // add an ID,
    // add a class,
    // change the CSS width, and
    // append to the progressbar
    var progressvalue = $("<div>")
    .attr("id", innerId)
    .addClass("progress-value")
    .css('width', "100%")
    .appendTo(progressbar);

    // Create a function to convert into hexadecimal
    var toHex = function(num) {
      var res = Math.round(Number(num)).toString(16);
      return (res.length === 1 ? "0" + res : res);
    };

    // Save a reference to possible payload content
    var functionToRun = this.createShadowWrapper(
      payload
        ? function() { Wikifier.wikifyEval(payload); }
        : null
    );

    // Watch for the :passagedisplay event once
    jQuery(document).one(":passagedisplay", function() {

      // Get the current time
      var timeStarted = (new Date()).getTime();

      // Save a reference to the setInterval function
      var workFunction = setInterval(function() {

        // Check if the element is still 'connected'
        if(! progressbar.prop("isConnected") ) {

          // Navigated away from the passage
          clearInterval(workFunction);
          return;
        }

        // Figure out how much time has passed
        var timePassed = (new Date()).getTime() - timeStarted;

        // Check if the timer has run out
        if(timePassed >= duration) {

          // Reduce the inner width to 0
          progressvalue.css('width', "0");

          // Clear interval
          clearInterval(workFunction);

          // Run the inner function (if set)
          setTimeout(functionToRun, 40);
          return;
        }

        // Update the progress percentage
        var percentage = 100 - 100 * timePassed / duration;

        // Save the new color
        var color = "#"
          + toHex(Math.min(255, 510 -  5.1 * percentage))
          + toHex(Math.min(255, 5.1 * percentage)) + "00";

        // Update the background color of the inner div
        progressvalue.css("backgroundColor", color);

        // Update the inner div width
        progressvalue.css("width", (100 - 100 * timePassed / duration) + "%");

      }, 40);

    });
  },
});


:: UserStylesheet[stylesheet]
.progress-bar {
  position: relative;
  border: 1px solid #777;
  background: black;
  height: 1em;
}

.progress-value {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: #00ff00;
}



:: Start
<<timedprogressbar 5 20em>>
  <<run UI.alert("Too late!")>>
<</timedprogressbar>>

Twee Download

See Also#

Adding Functionality