bec63d535acb4569150a8ecd51149aa9cb2f09bf
[yaffs-website] / web / core / misc / progress.es6.js
1 /**
2  * @file
3  * Progress bar.
4  */
5
6 (function ($, Drupal) {
7   /**
8    * Theme function for the progress bar.
9    *
10    * @param {string} id
11    *   The id for the progress bar.
12    *
13    * @return {string}
14    *   The HTML for the progress bar.
15    */
16   Drupal.theme.progressBar = function (id) {
17     return `<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
53     // The WAI-ARIA setting aria-live="polite" will announce changes after
54     // users
55     // have completed their current activity and not interrupt the screen
56     // reader.
57     this.element = $(Drupal.theme('progressBar', id));
58   };
59
60   $.extend(Drupal.ProgressBar.prototype, /** @lends Drupal.ProgressBar# */{
61
62     /**
63      * Set the percentage and status message for the progressbar.
64      *
65      * @param {number} percentage
66      *   The progress percentage.
67      * @param {string} message
68      *   The message to show the user.
69      * @param {string} label
70      *   The text for the progressbar label.
71      */
72     setProgress(percentage, message, label) {
73       if (percentage >= 0 && percentage <= 100) {
74         $(this.element).find('div.progress__bar').css('width', `${percentage}%`);
75         $(this.element).find('div.progress__percentage').html(`${percentage}%`);
76       }
77       $('div.progress__description', this.element).html(message);
78       $('div.progress__label', this.element).html(label);
79       if (this.updateCallback) {
80         this.updateCallback(percentage, message, this);
81       }
82     },
83
84     /**
85      * Start monitoring progress via Ajax.
86      *
87      * @param {string} uri
88      *   The URI to use for monitoring.
89      * @param {number} delay
90      *   The delay for calling the monitoring URI.
91      */
92     startMonitoring(uri, delay) {
93       this.delay = delay;
94       this.uri = uri;
95       this.sendPing();
96     },
97
98     /**
99      * Stop monitoring progress via Ajax.
100      */
101     stopMonitoring() {
102       clearTimeout(this.timer);
103       // This allows monitoring to be stopped from within the callback.
104       this.uri = null;
105     },
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         }
122         else {
123           uri += '&';
124         }
125         uri += '_format=json';
126         $.ajax({
127           type: this.method,
128           url: uri,
129           data: '',
130           dataType: 'json',
131           success(progress) {
132             // Display errors.
133             if (progress.status === 0) {
134               pb.displayError(progress.data);
135               return;
136             }
137             // Update display.
138             pb.setProgress(progress.percentage, progress.message, progress.label);
139             // Schedule next timer.
140             pb.timer = setTimeout(() => {
141               pb.sendPing();
142             }, pb.delay);
143           },
144           error(xmlhttp) {
145             const e = new Drupal.AjaxError(xmlhttp, pb.uri);
146             pb.displayError(`<pre>${e.message}</pre>`);
147           },
148         });
149       }
150     },
151
152     /**
153      * Display errors on the page.
154      *
155      * @param {string} string
156      *   The error message to show the user.
157      */
158     displayError(string) {
159       const error = $('<div class="messages messages--error"></div>').html(string);
160       $(this.element).before(error).hide();
161
162       if (this.errorCallback) {
163         this.errorCallback(this);
164       }
165     },
166   });
167 }(jQuery, Drupal));