UNPKG

infusion

Version:

Infusion is an application framework for developing flexible stuff with JavaScript

270 lines (243 loc) 10.4 kB
/* Copyright The Infusion copyright holders See the AUTHORS.md file at the top-level directory of this distribution and at https://github.com/fluid-project/infusion/raw/main/AUTHORS.md. Licensed under the Educational Community License (ECL), Version 2.0 or the New BSD license. You may not use this file except in compliance with one these Licenses. You may obtain a copy of the ECL 2.0 License and BSD License at https://github.com/fluid-project/infusion/raw/main/Infusion-LICENSE.txt */ "use strict"; fluid.registerNamespace("fluid.progress"); fluid.progress.animateDisplay = function (elm, animation, defaultAnimation, callback) { animation = (animation) ? animation : defaultAnimation; elm.animate(animation.params, animation.duration, callback); }; fluid.progress.animateProgress = function (elm, width, speed) { // de-queue any left over animations elm.queue("fx", []); elm.animate({ width: width, queue: false }, speed); }; /** * Shows the progress bar if is currently hidden. * * @param {fluid.progress} that - an instance of `fluid.progress` * @param {Object} animation - (optional) a custom animation used when showing the progress bar */ fluid.progress.showProgress = function (that, animation) { var firer = that.events.onProgressBegin.fire; if (animation === false) { that.displayElement.show(); firer(); } else { fluid.progress.animateDisplay(that.displayElement, animation, that.options.showAnimation, firer); } }; /** * Hides the progress bar if it is visible. * * @param {fluid.progress} that - an instance of `fluid.progress` * @param {Number} delay - the amount of time to wait before hiding * @param {Object} animation - (optional) a custom animation used when hiding the progress bar */ fluid.progress.hideProgress = function (that, delay, animation) { if (delay) { // use a setTimeout to delay the hide for n millis, note use of recursion setTimeout(function () { fluid.progress.hideProgress(that, 0, animation); }, delay); } else { var firer = that.events.afterProgressHidden.fire; if (animation === false) { that.displayElement.hide(); firer(); } else { fluid.progress.animateDisplay(that.displayElement, animation, that.options.hideAnimation, firer); } } }; fluid.progress.updateWidth = function (that, newWidth, dontAnimate) { var currWidth = that.indicator.width(); var direction = that.options.animate; if ((newWidth > currWidth) && (direction === "both" || direction === "forward") && !dontAnimate) { fluid.progress.animateProgress(that.indicator, newWidth, that.options.speed); } else if ((newWidth < currWidth) && (direction === "both" || direction === "backward") && !dontAnimate) { fluid.progress.animateProgress(that.indicator, newWidth, that.options.speed); } else { that.indicator.width(newWidth); } }; fluid.progress.percentToPixels = function (that, percent) { // progress does not support percents over 100, also all numbers are rounded to integers return Math.round((Math.min(percent, 100) * that.progressBar.innerWidth()) / 100); }; fluid.progress.refreshRelativeWidth = function (that) { var pixels = Math.max(fluid.progress.percentToPixels(that, parseFloat(that.storedPercent)), that.options.minWidth); fluid.progress.updateWidth(that, pixels, true); }; fluid.progress.initARIA = function (ariaElement, ariaBusyText) { ariaElement.attr("role", "progressbar"); ariaElement.attr("aria-valuemin", "0"); ariaElement.attr("aria-valuemax", "100"); ariaElement.attr("aria-valuenow", "0"); // Empty value for ariaBusyText will default to aria-valuenow. if (ariaBusyText) { ariaElement.attr("aria-valuetext", ""); } ariaElement.attr("aria-busy", "false"); }; fluid.progress.updateARIA = function (that, percent) { var str = that.options.strings; var busy = percent < 100 && percent > 0; that.ariaElement.attr("aria-busy", busy); that.ariaElement.attr("aria-valuenow", percent); // Empty value for ariaBusyText will default to aria-valuenow. if (str.ariaBusyText) { if (busy) { var busyString = fluid.stringTemplate(str.ariaBusyText, {percentComplete : percent}); that.ariaElement.attr("aria-valuetext", busyString); } else if (percent === 100) { // FLUID-2936: JAWS doesn't currently read the "Progress is complete" message to the user, even though we set it here. that.ariaElement.attr("aria-valuetext", str.ariaDoneText); } } }; fluid.progress.updateText = function (label, value) { label.html(value); }; fluid.progress.repositionIndicator = function (that) { that.indicator.css("top", that.progressBar.position().top) .css("left", 0) .height(that.progressBar.height()); fluid.progress.refreshRelativeWidth(that); }; /** * Updates the state of the progress bar. * This will automatically show the progress bar if it is currently hidden. * Percentage is specified as a decimal value, but will be automatically converted if needed. * * @param {fluid.progress} that - an instance of `fluid.progress` * @param {Number|String} percent - the current percentage, specified as a "float-ish" value * @param {String} labelText - the value to set for the label; this can be an HTML string * @param {Object} animationForShow - (optional) the animation to use when showing the progress bar if it is hidden */ fluid.progress.updateProgress = function (that, percent, labelText, animationForShow) { // show progress before updating, jQuery will handle the case if the object is already displayed fluid.progress.showProgress(that, animationForShow); if (percent !== null) { that.storedPercent = percent; var pixels = Math.max(fluid.progress.percentToPixels(that, parseFloat(percent)), that.options.minWidth); fluid.progress.updateWidth(that, pixels); } if (fluid.isValue(labelText)) { var text = fluid.stringTemplate(labelText, {percentComplete: percent}); fluid.progress.updateText(that.label, text); } // update ARIA if (that.ariaElement) { fluid.progress.updateARIA(that, percent); } }; fluid.progress.hideElement = function (element, shouldHide) { element.toggle(!shouldHide); }; /** * Instantiates a new Progress component. * * @param {jQuery|Selector|Element} container - the DOM element in which the Uploader lives * @param {Object} options - (optional) configuration options for the component. */ fluid.defaults("fluid.progress", { gradeNames: ["fluid.viewComponent"], members: { displayElement: "{that}.dom.displayElement", progressBar: "{that}.dom.progressBar", label: "{that}.dom.label", indicator: "{that}.dom.indicator", ariaElement: "{that}.dom.ariaElement", storedPercent: 0 }, events: { onProgressBegin: null, afterProgressHidden: null }, listeners: { onCreate: [ { "this": "{that}.dom.indicator", method: "width", args: "{that}.options.minWidth" }, { funcName: "fluid.progress.hideElement", args: ["{that}.dom.displayElement", "{that}.options.initiallyHidden"] }, { funcName: "fluid.progress.initARIA", args: ["{that}.ariaElement", "{that}.options.strings.ariaBusyText"] }], onProgressBegin: { func: "{that}.options.showAnimation.onProgressBegin" }, afterProgressHidden: { func: "{that}.options.hideAnimation.afterProgressHidden" } }, invokers: { // Shows the progress bar if is currently hidden. show: { funcName: "fluid.progress.showProgress", args: ["{that}", "{arguments}.0"] }, // Hides the progress bar if it is visible. hide: { funcName: "fluid.progress.hideProgress", args: ["{that}", "{arguments}.0", "{arguments}.1"] }, // Updates the state of the progress bar. update: { funcName: "fluid.progress.updateProgress", args: ["{that}", "{arguments}.0", "{arguments}.1", "{arguments}.2"] }, refreshView: { funcName: "fluid.progress.repositionIndicator", args: "{that}" } }, selectors: { displayElement: ".flc-progress", // required, the element that gets displayed when progress is displayed, could be the indicator or bar or some larger outer wrapper as in an overlay effect progressBar: ".flc-progress-bar", //required indicator: ".flc-progress-indicator", //required label: ".flc-progress-label", //optional ariaElement: ".flc-progress-bar" // usually required, except in cases where there are more than one progressor for the same data such as a total and a sub-total }, strings: { //Empty value for ariaBusyText will default to aria-valuenow. ariaBusyText: "Progress is %percentComplete percent complete", ariaDoneText: "Progress is complete." }, // progress display and hide animations, use the jQuery animation primatives, set to false to use no animation // animations must be symetrical (if you hide with width, you'd better show with width) or you get odd effects // see jQuery docs about animations to customize showAnimation: { params: { opacity: "show" }, duration: "slow", onProgressBegin: fluid.identity }, // equivalent of $().fadeIn("slow") hideAnimation: { params: { opacity: "hide" }, duration: "slow", afterProgressHidden: fluid.identity }, // equivalent of $().fadeOut("slow") minWidth: 5, // 0 length indicators can look broken if there is a long pause between updates delay: 0, // the amount to delay the fade out of the progress speed: 200, // default speed for animations, pretty fast animate: "forward", // suppport "forward", "backward", and "both", any other value is no animation either way initiallyHidden: true, // supports progress indicators which may always be present updatePosition: false });