class queuePanel extends panelObj{ constructor(client, panelDocument){ super(client, "Media Queue", "/panel/queue", panelDocument); //Store releative scale of items in seconds, defaulting to 30 minute chunks this.scale = 30 * 60; } docSwitch(){ //Get queue container this.queueContainer = this.panelDocument.querySelector('#queue'); //If we have an existing time marker if(this.timeMarker != null){ //Clear it out this.timeMarker.remove(); this.timeMarker = null; } //Render out the queue this.renderQueue(); } closer(){ //Clear any remaining timers clearTimeout(this.renderTimeMarker); } renderQueue(date = new Date()){ //Clear out queue container this.queueContainer.innerHTML = ''; //Render out time scale this.renderQueueScale(date); for(let entry of this.client.queue){ //Create entry div const entryDiv = document.createElement('div'); entryDiv.classList.add('queue-entry'); //Create entry title const entryTitle = document.createElement('a'); entryTitle.textContent = entry[1].title; entryTitle.href = entry[1].url; //Append entry elements entryDiv.append(entryTitle); //Append entry this.queueContainer.append(entryDiv); } } renderTimeMarker(date = new Date()){ //Pull start of day epoch from given date const dayEpoch = structuredClone(date).setHours(0,0,0,0); //Get difference to get time since the start of the current day in seconds const curTime = date.getTime() - dayEpoch; //Get time in day as a float between 0 and 1 const timeFloat = curTime / 86400000; //Get queue markers const markers = this.panelDocument.querySelectorAll('span.queue-marker'); //If the marker is null for some reason if(markers[0] == null){ //Try again in a second since the user probably just popped the panel or something :P (smackTimer.bind(this))(); return; } //Get marker position range const range = [markers[0].offsetTop, markers[markers.length - 1].offsetTop] //Get maximum position relative to the range itself const offsetMax = range[1] - range[0]; //Get marker position relative to parent const markerPosition = (offsetMax * timeFloat) + range[0]; //if we need to make the time marker if(this.timeMarker == null){ //Create time marker this.timeMarker = document.createElement('span'); //Add time marker class this.timeMarker.id = 'time-marker'; //Append time marker this.queueContainer.appendChild(this.timeMarker); } //Set time marker position this.timeMarker.style.top = `${markerPosition}px`; (smackTimer.bind(this))(); function smackTimer(){ //Clear update timer clearTimeout(this.timeMarkerTimer); //Set timer to update marker every second this.timeMarkerTimer = setTimeout(this.renderTimeMarker.bind(this), 1000); } } renderQueueScale(inputDate = new Date()){ //Make sure we don't modify the date we're handed const date = structuredClone(inputDate); //Zero out date to midnight date.setHours(0,0,0,0); //Store epoch of current date at midnight for later user const dateEpoch = date.getTime(); //while we've counted less than the amount of time in the day, count up by scale for(let time = 0; time <= 86400; time += this.scale){ //Get index of current chunk by dividing time by scale const index = time / this.scale; //Set time by scale, we could do this against this.scale and date.getTime(), but this seemed cleaner :P date.setTime(dateEpoch + (time * 1000)) //Create marker span const markerSpan = document.createElement('div'); markerSpan.classList.add('queue-marker'); //Create marker line (unfortunately
tags don't seem to play nice with parents who have display:flex) const marker = document.createElement('span'); marker.classList.add('queue-marker'); //If it's even/zero if(index % 2 == 0){ const markerLabel = document.createElement('p'); //If scale is over a minute then we don't need to display seconds const seconds = this.scale > 60 ? '' : `:${('0' + date.getSeconds()).slice(-2)}` //If we're counting AM if(date.getHours() < 12){ //Display as AM markerLabel.textContent = `${('0'+date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}${seconds}AM` //If we're cointing noon }else if(date.getHours() == 12){ //display as noon markerLabel.textContent = `${('0'+date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}${seconds}PM` //if we're counting pm }else{ //display as pm markerLabel.textContent = `${('0'+(date.getHours() - 12)).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}${seconds}PM` } //Add marker label to marker span markerSpan.appendChild(markerLabel); } //Append marker to marker span markerSpan.appendChild(marker); //Append marker span to queue container this.queueContainer.appendChild(markerSpan); } //Easiest way to wait for DOM to do it's thing is to: //fires before next frame requestAnimationFrame(()=>{ //fires before next-next frame (after next frame) requestAnimationFrame(()=>{ //render the time marker this.renderTimeMarker(inputDate); }); }); } }