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