1"use strict"; 2/** 3 * 4 * @param {string|HTMLElement} mountElement conteneur 5 * @param {int} spinnerSize taille du spinner en pixels 6 * @param {int} maxValue valeur maximale 7 * @param {string} [unit] unité bytes|numeric 8 * @constructor 9 */ 10function Spinner(mountElement,spinnerSize,maxValue,unit) 11{ 12 this.initialize=function() 13 { 14 this.setUnit(unit||"numeric"); 15 this.spinnerSize=spinnerSize; 16 this.maxValue=maxValue; 17 this.mountElement= mountElement; 18 if(typeof this.mountElement==="string") this.mountElement = document.querySelector(this.mountElement); 19 20 // Geometry 21 this.spinnerDashWidth=Math.ceil(this.spinnerSize/15); 22 this.spinnerRadius=(this.spinnerSize-this.spinnerDashWidth)/2; 23 this.spinnerOffset=this.spinnerRadius+this.spinnerDashWidth/2; 24 this.spinnerLabelFontSize=Math.round(this.spinnerRadius/2); 25 this.timeStarted=new Date().getTime(); 26 // DOM Elements 27 this.spinnerContainer=null; 28 this.spinner = null; 29 this.circle = null; 30 this.spinnerBackground = null; 31 this.spinnerForeground = null; 32 this.spinnerLabel = null; 33 this.spinnerTitle=null; 34 this.spinnerStatus = null; 35 this.spinnerTimeLeft = null; 36 // Stats 37 this.seconds_elapsed=0; 38 this.progress_per_second=0; 39 this.remaining_progress=0; 40 this.seconds_remaining=0; 41 this.currentValue=0; 42 43 this.stopAnimationTimeout=null; 44 this.hideTimeout=null; 45 46 this.initDisplay(); 47 }; 48 this.mount=function() 49 { 50 if(this.mountElement) 51 { 52 this.mountElement.appendChild(this.spinnerContainer); 53 } 54 }; 55 this.buildDomElements = function() 56 { 57 this.spinnerContainer = document.createElement("div"); 58 this.spinnerContainer.setAttribute("class","spinner-container"); 59 60 this.spinner = document.createElement("div"); 61 this.spinner.setAttribute("class","spinner"); 62 63 this.circle = document.createElementNS('http://www.w3.org/2000/svg',"svg"); 64 this.circle.setAttribute("class","x-circle"); 65 66 this.spinnerBackground = document.createElementNS('http://www.w3.org/2000/svg',"circle"); 67 this.spinnerBackground.setAttribute("class","x-background"); 68 this.spinnerBackground.setAttribute("fill","transparent"); 69 70 this.spinnerForeground = document.createElementNS('http://www.w3.org/2000/svg',"circle"); 71 this.spinnerForeground.setAttribute("class","x-foreground"); 72 this.spinnerForeground.setAttribute("fill","transparent"); 73 74 this.spinnerLabel = document.createElementNS('http://www.w3.org/2000/svg',"text"); 75 this.spinnerLabel.setAttribute("class","x-label"); 76 this.spinnerLabel.setAttribute("x","50%"); 77 this.spinnerLabel.setAttribute("y","50%"); 78 this.spinnerLabel.setAttribute("fill","black"); 79 this.spinnerLabel.setAttribute("text-anchor","middle"); 80 81 this.spinnerError = document.createElementNS('http://www.w3.org/2000/svg',"image"); 82 this.spinnerError.setAttribute("class","x-error-icon"); 83 this.spinnerError.setAttribute("x","50%"); 84 this.spinnerError.setAttribute("y","50%"); 85 this.spinnerError.setAttribute("width","32"); 86 this.spinnerError.setAttribute("height","32"); 87 this.spinnerError.setAttribute("transform","translate(-16,-16)"); 88 this.spinnerError.setAttribute("href","/src/images/icons/svg/close.svg"); 89 this.spinnerError.textContent="!"; 90 91 92 this.spinnerTitle = document.createElement("div"); 93 this.spinnerTitle.setAttribute("class","x-title"); 94 95 this.spinnerStatus = document.createElement("div"); 96 this.spinnerStatus.setAttribute("class","x-status"); 97 98 this.spinnerTimeLeft = document.createElement("div"); 99 this.spinnerTimeLeft.setAttribute("class","x-timeleft"); 100 101 this.circle.appendChild(this.spinnerBackground); 102 this.circle.appendChild(this.spinnerForeground); 103 this.circle.appendChild(this.spinnerLabel); 104 this.circle.appendChild(this.spinnerError); 105 this.spinner.appendChild(this.circle); 106 this.spinnerContainer.appendChild(this.spinner); 107 this.spinnerContainer.appendChild(this.spinnerTitle); 108 this.spinnerContainer.appendChild(this.spinnerStatus); 109 this.spinnerContainer.appendChild(this.spinnerTimeLeft); 110 }; 111 this.initDisplay=function() 112 { 113 this.buildDomElements(); 114 this.circle.setAttribute("height",this.spinnerSize.toString()); 115 this.circle.setAttribute("width",this.spinnerSize.toString()); 116 this.circle.setAttribute("viewBox","0 0 "+this.spinnerSize.toString()+" "+this.spinnerSize.toString()); 117
118 this.spinnerBackground.setAttribute("r",this.spinnerRadius); 119 this.spinnerBackground.setAttribute("cx",this.spinnerOffset); 120 this.spinnerBackground.setAttribute("cy",this.spinnerOffset); 121 this.spinnerBackground.style.strokeDashoffset=this.getCirconf(); 122 this.spinnerBackground.style.strokeDasharray=0; 123 this.spinnerBackground.style.strokeWidth=this.spinnerDashWidth; 124 125 this.spinnerForeground.setAttribute("r",this.spinnerRadius); 126 this.spinnerForeground.setAttribute("cx",this.spinnerOffset); 127 this.spinnerForeground.setAttribute("cy",this.spinnerOffset); 128 this.spinnerForeground.style.strokeDashoffset=this.getCirconf(); 129 this.spinnerForeground.style.strokeDasharray=this.getCirconf(); 130 this.spinnerForeground.style.strokeWidth=this.spinnerDashWidth; 131 132 this.spinnerLabel.style.fontSize=this.spinnerLabelFontSize+"px"; 133 this.spinnerLabel.setAttribute("y",Math.round((this.spinnerSize+this.spinnerLabelFontSize-this.spinnerDashWidth)/2).toString()); 134 this.mount(); 135 }; 136 /** 137 * 138 * @param {int|undefined} currentValue 139 * @param {int|undefined} [maxValue] 140 * @param [title] 141 * @param [unit] 142 */ 143 this.updateSpinner = function(currentValue,maxValue,title,unit) 144 { 145 if(typeof title==="undefined") title=""; 146 this.startAnimation(); 147 if(typeof maxValue!=="undefined") this.maxValue=maxValue; 148 this.currentValue=currentValue; 149 this.spinnerForeground.style.strokeDashoffset=this.pctToDashOffset(this.getProgressAsPct()); 150 this.computeProgressStats(); 151 this.updateLabel(this.getProgressAsPct()); 152 if(title!==null) this.setTitle(title); 153 if(unit!==undefined) this.setUnit(unit); 154 this.updateStatus(); 155 this.updateTimeLeft(); 156 if(this.maxValue===this.currentValue) 157 { 158 this.stopAnimationTimeout = setTimeout(function(){this.stopAnimation();}.bind(this),3000); 159 } 160 }; 161 this.computeProgressStats=function() 162 { 163 this.seconds_elapsed = (new Date().getTime() - this.timeStarted)/1000; 164 this.progress_per_second = this.seconds_elapsed ? this.currentValue / this.seconds_elapsed : 0 ; 165 this.remaining_progress = this.maxValue - this.currentValue; 166 this.seconds_remaining = this.seconds_elapsed ? this.remaining_progress / this.progress_per_second : Infinity; 167 }; 168 this.setUnit=function(unit) 169 { 170 this.unit=unit; 171 }; 172 this.setLabel=function(string) 173 { 174 this.spinnerLabel.textContent=string; 175 }; 176 this.setTitle=function(string) 177 { 178 this.spinnerTitle.innerHTML=string; 179 }; 180 this.setStatus=function(string) 181 { 182 this.spinnerStatus.innerHTML=string; 183 this.setHasError(false); 184 }; 185 this.setTimeLeft=function(string) 186 { 187 if(string==="" || string ===null) string=" "; 188 this.spinnerTimeLeft.innerHTML=string; 189 }; 190 this.updateLabel=function(pctTransfered) 191 { 192 this.setLabel(Math.round(pctTransfered)+"%"); 193 }; 194 this.updateStatus=function() 195 { 196 this.setStatus(this.formatValue(this.currentValue)+" / "+this.formatValue(this.maxValue)); 197 }; 198 this.formatValue=function(value) 199 { 200 if(this.unit==="bytes") return this.formatBytes(value); 201 else if(this.unit==="numeric") return Math.round(value); 202 else return Math.round(value); 203 }; 204 this.formatBytes=function(bytes) 205 { 206 if(bytes === 0) return '0 B'; 207 var k = 1024,dm = 0,sizes = ['B', 'Ko', 'Mo', 'Go', 'To', 'Po', 'Eo', 'Zo', 'Yo'],i = Math.floor(Math.log(bytes) / Math.log(k)); 208 return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; 209 }; 210 this.setError=function(errorMessage) 211 { 212 this.setLabel(""); 213 this.stopAnimation(); 214 this.setStatus(errorMessage); 215 this.setHasError(true); 216 }; 217 this.setHasError=function(bool) 218 { 219 if(bool) this.spinnerContainer.classList.add("x-error"); 220 else this.spinnerContainer.classList.remove("x-error"); 221 }; 222 this.updateTimeLeft=function() 223 { 224 this.setTimeLeft(this.secondsFormat(this.seconds_remaining)); 225 }; 226 this.getCirconf=function() 227 { 228 return 2*Math.PI*this.spinnerRadius; 229 }; 230 this.pctToDashOffset=function(pct) 231 { 232 var circonf=this.getCirconf(); 233 var offset = circonf-(circonf*pct/100); 234 // pour que le cercle bleu soit toujours visible on assure une petite marge. 235 if(circonf-offset<1) offset=circonf-1; 236 return Math.round(offset); 237 }; 238 this.secondsFormat=function(time) 239 { 240 if(!isFinite(time)) return ""; 241 if(time>0) 242 { 243 var hrs = Math.floor(time / 3600); 244 var mins = Math.floor((time % 3600) / 60); 245 var secs = Math.floor(time % 60); 246 var ret = "⏱ "; 247 if(hrs > 0 && isFinite(hrs)) ret += "" + hrs + " h " + (mins < 10 ? "0" : ""); 248 if(hrs>0 || (mins>0 && isFinite(mins))) ret += "" + mins + " m " + (secs < 10 ? "0" : ""); 249 ret += "" + secs + " s"; 250 return ret; 251 } 252 else return ""; 253 }; 254 this.getProgressAsPct=function() 255 { 256 if(this.maxValue>0) return this.currentValue/this.maxValue*100; 257 else return 0; 258 }; 259 this.startAnimation=function() 260 { 261 if(this.spinner.classList) 262 { 263 this.spinner.classList.add("x-animated"); 264 } 265 }; 266 this.stopAnimation=function() 267 { 268 if(this.spinner.classList) 269 { 270 this.spinner.classList.remove("x-animated"); 271 } 272 }; 273 this.hide=function() 274 { 275 this.spinnerContainer.style.opacity=0; 276 this.hideTimeout = setTimeout(function(){this.spinnerContainer.style.display="none";}.bind(this),1000); 277 }; 278 this.show=function() 279 { 280 this.spinnerContainer.style.opacity=0; 281 this.spinnerContainer.style.display=""; 282 this.spinnerContainer.style.opacity=1; 283 }; 284 this.destroy=function() 285 { 286 if(this.spinnerContainer && this.spinnerContainer.parentNode) this.spinnerContainer.parentNode.removeChild(this.spinnerContainer); 287 if(this.stopAnimationTimeout) clearTimeout(this.stopAnimationTimeout); 288 if(this.hideTimeout) clearTimeout(this.hideTimeout); 289 this.spinner=null; 290 }; 291 this.initialize(); 292} 293 294function SpinnerSimulator(fileSize,minIncr,maxIncr,spinner,interval) 295{ 296 this.fileSize=fileSize; 297 this.transferedSize=0; 298 this.minIncr=minIncr; 299 this.maxIncr=maxIncr; 300 this.interval=interval; 301 this.spinner=spinner; 302 this.getRandomArbitrary=function(min, max) 303 { 304 return Math.round(Math.random() * (max - min) + min); 305 }; 306 this.simulateUpload=function() 307 { 308 this.spinner.updateSpinner(this.transferedSize,this.fileSize,"Téléchargement en cours..."); 309 var interval = setInterval(function() 310 { 311 if(this.transferedSize<this.fileSize) this.transferedSize+=this.getRandomArbitrary(this.minIncr,this.maxIncr); 312 else this.transferedSize=this.fileSize; 313 if(this.transferedSize>=this.fileSize) 314 { 315 this.transferedSize=this.fileSize; 316 clearInterval(interval); 317 } 318 this.spinner.updateSpinner(this.transferedSize,this.fileSize,"Téléchargement en cours..."); 319 320 }.bind(this),this.interval); 321 }; 322}
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.