Chris@0: /**
Chris@0: * @file
Chris@0: * Progress bar.
Chris@0: */
Chris@0:
Chris@17: (function($, Drupal) {
Chris@0: /**
Chris@0: * Theme function for the progress bar.
Chris@0: *
Chris@0: * @param {string} id
Chris@0: * The id for the progress bar.
Chris@0: *
Chris@0: * @return {string}
Chris@0: * The HTML for the progress bar.
Chris@0: */
Chris@17: Drupal.theme.progressBar = function(id) {
Chris@17: return (
Chris@17: `
` +
Chris@0: '
' +
Chris@0: '
' +
Chris@0: '
' +
Chris@0: '
' +
Chris@17: '
'
Chris@17: );
Chris@0: };
Chris@0:
Chris@0: /**
Chris@0: * A progressbar object. Initialized with the given id. Must be inserted into
Chris@0: * the DOM afterwards through progressBar.element.
Chris@0: *
Chris@0: * Method is the function which will perform the HTTP request to get the
Chris@0: * progress bar state. Either "GET" or "POST".
Chris@0: *
Chris@0: * @example
Chris@0: * pb = new Drupal.ProgressBar('myProgressBar');
Chris@0: * some_element.appendChild(pb.element);
Chris@0: *
Chris@0: * @constructor
Chris@0: *
Chris@0: * @param {string} id
Chris@0: * The id for the progressbar.
Chris@0: * @param {function} updateCallback
Chris@0: * Callback to run on update.
Chris@0: * @param {string} method
Chris@0: * HTTP method to use.
Chris@0: * @param {function} errorCallback
Chris@0: * Callback to call on error.
Chris@0: */
Chris@17: Drupal.ProgressBar = function(id, updateCallback, method, errorCallback) {
Chris@0: this.id = id;
Chris@0: this.method = method || 'GET';
Chris@0: this.updateCallback = updateCallback;
Chris@0: this.errorCallback = errorCallback;
Chris@0:
Chris@0: // The WAI-ARIA setting aria-live="polite" will announce changes after
Chris@0: // users
Chris@0: // have completed their current activity and not interrupt the screen
Chris@0: // reader.
Chris@0: this.element = $(Drupal.theme('progressBar', id));
Chris@0: };
Chris@0:
Chris@17: $.extend(
Chris@17: Drupal.ProgressBar.prototype,
Chris@17: /** @lends Drupal.ProgressBar# */ {
Chris@17: /**
Chris@17: * Set the percentage and status message for the progressbar.
Chris@17: *
Chris@17: * @param {number} percentage
Chris@17: * The progress percentage.
Chris@17: * @param {string} message
Chris@17: * The message to show the user.
Chris@17: * @param {string} label
Chris@17: * The text for the progressbar label.
Chris@17: */
Chris@17: setProgress(percentage, message, label) {
Chris@17: if (percentage >= 0 && percentage <= 100) {
Chris@17: $(this.element)
Chris@17: .find('div.progress__bar')
Chris@17: .css('width', `${percentage}%`);
Chris@17: $(this.element)
Chris@17: .find('div.progress__percentage')
Chris@17: .html(`${percentage}%`);
Chris@17: }
Chris@17: $('div.progress__description', this.element).html(message);
Chris@17: $('div.progress__label', this.element).html(label);
Chris@17: if (this.updateCallback) {
Chris@17: this.updateCallback(percentage, message, this);
Chris@17: }
Chris@17: },
Chris@0:
Chris@17: /**
Chris@17: * Start monitoring progress via Ajax.
Chris@17: *
Chris@17: * @param {string} uri
Chris@17: * The URI to use for monitoring.
Chris@17: * @param {number} delay
Chris@17: * The delay for calling the monitoring URI.
Chris@17: */
Chris@17: startMonitoring(uri, delay) {
Chris@17: this.delay = delay;
Chris@17: this.uri = uri;
Chris@17: this.sendPing();
Chris@17: },
Chris@17:
Chris@17: /**
Chris@17: * Stop monitoring progress via Ajax.
Chris@17: */
Chris@17: stopMonitoring() {
Chris@17: clearTimeout(this.timer);
Chris@17: // This allows monitoring to be stopped from within the callback.
Chris@17: this.uri = null;
Chris@17: },
Chris@17:
Chris@17: /**
Chris@17: * Request progress data from server.
Chris@17: */
Chris@17: sendPing() {
Chris@17: if (this.timer) {
Chris@17: clearTimeout(this.timer);
Chris@17: }
Chris@17: if (this.uri) {
Chris@17: const pb = this;
Chris@17: // When doing a post request, you need non-null data. Otherwise a
Chris@17: // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
Chris@17: let uri = this.uri;
Chris@17: if (uri.indexOf('?') === -1) {
Chris@17: uri += '?';
Chris@17: } else {
Chris@17: uri += '&';
Chris@17: }
Chris@17: uri += '_format=json';
Chris@17: $.ajax({
Chris@17: type: this.method,
Chris@17: url: uri,
Chris@17: data: '',
Chris@17: dataType: 'json',
Chris@17: success(progress) {
Chris@17: // Display errors.
Chris@17: if (progress.status === 0) {
Chris@17: pb.displayError(progress.data);
Chris@17: return;
Chris@17: }
Chris@17: // Update display.
Chris@17: pb.setProgress(
Chris@17: progress.percentage,
Chris@17: progress.message,
Chris@17: progress.label,
Chris@17: );
Chris@17: // Schedule next timer.
Chris@17: pb.timer = setTimeout(() => {
Chris@17: pb.sendPing();
Chris@17: }, pb.delay);
Chris@17: },
Chris@17: error(xmlhttp) {
Chris@17: const e = new Drupal.AjaxError(xmlhttp, pb.uri);
Chris@17: pb.displayError(`${e.message}
`);
Chris@17: },
Chris@17: });
Chris@17: }
Chris@17: },
Chris@17:
Chris@17: /**
Chris@17: * Display errors on the page.
Chris@17: *
Chris@17: * @param {string} string
Chris@17: * The error message to show the user.
Chris@17: */
Chris@17: displayError(string) {
Chris@17: const error = $('').html(
Chris@17: string,
Chris@17: );
Chris@17: $(this.element)
Chris@17: .before(error)
Chris@17: .hide();
Chris@17:
Chris@17: if (this.errorCallback) {
Chris@17: this.errorCallback(this);
Chris@17: }
Chris@17: },
Chris@0: },
Chris@17: );
Chris@17: })(jQuery, Drupal);