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