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);