progress.es6.js 4.7 KB

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