1class Countdown360{constructor(element,options={}){this.element=element;this.settings={radius:15.5,strokeStyle:"#477050",strokeWidth:undefined,fillStyle:"#8ac575",fontColor:"#477050",fontFamily:"sans-serif",fontSize:undefined,fontWeight:700,autostart:true,seconds:10,label:["second","seconds"],startOverAfterAdding:true,smooth:false,onComplete:()=>{},...options};if(!this.settings.fontSize){this.settings.fontSize=this.settings.radius/1.2}if(!this.settings.strokeWidth){this.settings.strokeWidth=this.settings.radius/4}this._init()}getTimeRemaining(){return this._secondsLeft(this.getElapsedTime())}getElapsedTime(){return Math.round(((new Date).getTime()-this.startedAt.getTime())/1e3)}extendTimer(value){const seconds=parseInt(value);const secondsElapsed=Math.round(((new Date).getTime()-this.startedAt.getTime())/1e3);if(this._secondsLeft(secondsElapsed)+seconds<=this.settings.seconds){this.startedAt.setSeconds(this.startedAt.getSeconds()+parseInt(value))}}addSeconds(value){const secondsElapsed=Math.round(((new Date).getTime()-this.startedAt.getTime())/1e3);if(this.settings.startOverAfterAdding){this.settings.seconds=this._secondsLeft(secondsElapsed)+parseInt(value);this.start()}else{this.settings.seconds+=parseInt(value)}}start(){this.startedAt=new Date;this._drawCountdownShape(Math.PI*3.5,true);this._drawCountdownLabel(0);const timerInterval=this.settings.smooth?16:1e3;this.interval=setInterval(()=>this._draw(),timerInterval)}stop(callback){clearInterval(this.interval);if(callback){callback()}}_init(){this.settings.width=this.settings.radius*2+this.settings.strokeWidth*2;this.settings.height=this.settings.width;this.settings.arcX=this.settings.radius+this.settings.strokeWidth;this.settings.arcY=this.settings.arcX;this._initPen(this._getCanvas());if(this.settings.autostart){this.start()}}_getCanvas(){const canvas=document.createElement("canvas");canvas.id=`countdown360_${this.element.id}`;canvas.width=this.settings.width;canvas.height=this.settings.height;const ariaText=document.createElement("span");ariaText.id="countdown-text";ariaText.setAttribute("role","status");ariaText.setAttribute("aria-live","assertive");canvas.appendChild(ariaText);this.element.insertBefore(canvas,this.element.firstChild);return canvas}_initPen(canvas){this.pen=canvas.getContext("2d");this.pen.lineWidth=this.settings.strokeWidth;this.pen.strokeStyle=this.settings.strokeStyle;this.pen.fillStyle=this.settings.fillStyle;this.pen.textAlign="center";this.pen.textBaseline="middle";this.ariaText=canvas.querySelector("#countdown-text");this._clearRect()}_clearRect(){this.pen.clearRect(0,0,this.settings.width,this.settings.height)}_secondsLeft(secondsElapsed){return this.settings.seconds-secondsElapsed}_drawCountdownLabel(secondsElapsed){const secondsLeft=this._secondsLeft(secondsElapsed);this.ariaText.textContent=secondsLeft;this.pen.font=`${this.settings.fontWeight} ${this.settings.fontSize}px ${this.settings.fontFamily}`;const label=secondsLeft===1?this.settings.label[0]:this.settings.label[1];const drawLabel=this.settings.label&&this.settings.label.length===2;const x=this.settings.width/2;const y=drawLabel?this.settings.height/2-this.settings.fontSize/6.2:this.settings.height/2;this.pen.fillStyle=this.settings.fillStyle;this.pen.fillText(secondsLeft+1,x,y);this.pen.fillStyle=this.settings.fontColor;this.pen.fillText(secondsLeft,x,y);if(drawLabel){this.pen.font=`normal small-caps ${this.settings.fontSize/3}px ${this.settings.fontFamily}`;this.pen.fillText(label,this.settings.width/2,this.settings.height/2+this.settings.fontSize/2.2)}}_drawCountdownShape(endAngle,drawStroke){this.pen.fillStyle=this.settings.fillStyle;this.pen.beginPath();this.pen.arc(this.settings.arcX,this.settings.arcY,this.settings.radius,Math.PI*1.5,endAngle,false);this.pen.fill();if(drawStroke){this.pen.stroke()}}_draw(){const millisElapsed=(new Date).getTime()-this.startedAt.getTime();const secondsElapsed=Math.floor(millisElapsed/1e3);const endAngle=Math.PI*3.5-Math.PI*2/(this.settings.seconds*1e3)*millisElapsed;this._clearRect();this._drawCountdownShape(Math.PI*3.5,false);if(secondsElapsed<this.settings.seconds){this._drawCountdownShape(endAngle,true);this._drawCountdownLabel(secondsElapsed)}else{this._drawCountdownLabel(this.settings.seconds);this.stop();this.settings.onComplete()}}}window.Countdown360=Countdown360;
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.