progress.es6.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. * @file
  3. * Progress bar.
  4. */
  5. (function($, Drupal) {
  6. /**
  7. * Theme function for the progress bar.
  8. *
  9. * @param {string} id
  10. * The id for the progress bar.
  11. *
  12. * @return {string}
  13. * The HTML for the progress bar.
  14. */
  15. Drupal.theme.progressBar = function(id) {
  16. return (
  17. `<div id="${id}" class="progress" aria-live="polite">` +
  18. '<div class="progress__label">&nbsp;</div>' +
  19. '<div class="progress__track"><div class="progress__bar"></div></div>' +
  20. '<div class="progress__percentage"></div>' +
  21. '<div class="progress__description">&nbsp;</div>' +
  22. '</div>'
  23. );
  24. };
  25. /**
  26. * A progressbar object. Initialized with the given id. Must be inserted into
  27. * the DOM afterwards through progressBar.element.
  28. *
  29. * Method is the function which will perform the HTTP request to get the
  30. * progress bar state. Either "GET" or "POST".
  31. *
  32. * @example
  33. * pb = new Drupal.ProgressBar('myProgressBar');
  34. * some_element.appendChild(pb.element);
  35. *
  36. * @constructor
  37. *
  38. * @param {string} id
  39. * The id for the progressbar.
  40. * @param {function} updateCallback
  41. * Callback to run on update.
  42. * @param {string} method
  43. * HTTP method to use.
  44. * @param {function} errorCallback
  45. * Callback to call on error.
  46. */
  47. Drupal.ProgressBar = function(id, updateCallback, method, errorCallback) {
  48. this.id = id;
  49. this.method = method || 'GET';
  50. this.updateCallback = updateCallback;
  51. this.errorCallback = errorCallback;
  52. // The WAI-ARIA setting aria-live="polite" will announce changes after
  53. // users
  54. // have completed their current activity and not interrupt the screen
  55. // reader.
  56. this.element = $(Drupal.theme('progressBar', id));
  57. };
  58. $.extend(
  59. Drupal.ProgressBar.prototype,
  60. /** @lends Drupal.ProgressBar# */ {
  61. /**
  62. * Set the percentage and status message for the progressbar.
  63. *
  64. * @param {number} percentage
  65. * The progress percentage.
  66. * @param {string} message
  67. * The message to show the user.
  68. * @param {string} label
  69. * The text for the progressbar label.
  70. */
  71. setProgress(percentage, message, label) {
  72. if (percentage >= 0 && percentage <= 100) {
  73. $(this.element)
  74. .find('div.progress__bar')
  75. .css('width', `${percentage}%`);
  76. $(this.element)
  77. .find('div.progress__percentage')
  78. .html(`${percentage}%`);
  79. }
  80. $('div.progress__description', this.element).html(message);
  81. $('div.progress__label', this.element).html(label);
  82. if (this.updateCallback) {
  83. this.updateCallback(percentage, message, this);
  84. }
  85. },
  86. /**
  87. * Start monitoring progress via Ajax.
  88. *
  89. * @param {string} uri
  90. * The URI to use for monitoring.
  91. * @param {number} delay
  92. * The delay for calling the monitoring URI.
  93. */
  94. startMonitoring(uri, delay) {
  95. this.delay = delay;
  96. this.uri = uri;
  97. this.sendPing();
  98. },
  99. /**
  100. * Stop monitoring progress via Ajax.
  101. */
  102. stopMonitoring() {
  103. clearTimeout(this.timer);
  104. // This allows monitoring to be stopped from within the callback.
  105. this.uri = null;
  106. },
  107. /**
  108. * Request progress data from server.
  109. */
  110. sendPing() {
  111. if (this.timer) {
  112. clearTimeout(this.timer);
  113. }
  114. if (this.uri) {
  115. const pb = this;
  116. // When doing a post request, you need non-null data. Otherwise a
  117. // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
  118. let uri = this.uri;
  119. if (uri.indexOf('?') === -1) {
  120. uri += '?';
  121. } else {
  122. uri += '&';
  123. }
  124. uri += '_format=json';
  125. $.ajax({
  126. type: this.method,
  127. url: uri,
  128. data: '',
  129. dataType: 'json',
  130. success(progress) {
  131. // Display errors.
  132. if (progress.status === 0) {
  133. pb.displayError(progress.data);
  134. return;
  135. }
  136. // Update display.
  137. pb.setProgress(
  138. progress.percentage,
  139. progress.message,
  140. progress.label,
  141. );
  142. // Schedule next timer.
  143. pb.timer = setTimeout(() => {
  144. pb.sendPing();
  145. }, pb.delay);
  146. },
  147. error(xmlhttp) {
  148. const e = new Drupal.AjaxError(xmlhttp, pb.uri);
  149. pb.displayError(`<pre>${e.message}</pre>`);
  150. },
  151. });
  152. }
  153. },
  154. /**
  155. * Display errors on the page.
  156. *
  157. * @param {string} string
  158. * The error message to show the user.
  159. */
  160. displayError(string) {
  161. const error = $('<div class="messages messages--error"></div>').html(
  162. string,
  163. );
  164. $(this.element)
  165. .before(error)
  166. .hide();
  167. if (this.errorCallback) {
  168. this.errorCallback(this);
  169. }
  170. },
  171. },
  172. );
  173. })(jQuery, Drupal);