Refactored/Beautified existing playlist managment UI code.

This commit is contained in:
rainbow napkin 2025-04-04 06:10:32 -04:00
parent c3781d6259
commit c8c59feb7f
2 changed files with 238 additions and 201 deletions

View file

@ -81,6 +81,12 @@ div.dynamic-container, div.nested-dynamic-container{
margin: 0.5em 0; margin: 0.5em 0;
} }
button i{
/* Yeah I don't need event.target returning icons, thanks babe */
/* Granted most buttons should just hold the icon class themselves, some buttons with multiple icons in need this :P */
pointer-events: none;
}
/* Navbar */ /* Navbar */
#navbar{ #navbar{
display: flex; display: flex;

View file

@ -80,238 +80,269 @@ class playlistManager{
//For every playlist sent down from the server //For every playlist sent down from the server
for(let playlistIndex in data){ for(let playlistIndex in data){
//Get playlist from data //Get playlist from data
const playlist = data[playlistIndex]; this.playlist = data[playlistIndex];
//Create a new playlist div //Create a new playlist div
const playlistDiv = document.createElement('div'); this.playlistDiv = document.createElement('div');
//Set it's class //Set it's class
playlistDiv.classList.add('queue-playlist-div'); this.playlistDiv.classList.add('queue-playlist-div');
//Set playlist div dataset //Set playlist div dataset
playlistDiv.dataset.name = playlist.name; this.playlistDiv.dataset.name = this.playlist.name;
//Create span to hold playlist entry line contents //Create span to hold playlist entry line contents
const playlistSpan = document.createElement('span'); this.playlistSpan = document.createElement('span');
//Set classes //Set classes
playlistSpan.classList.add('queue-playlist-span'); this.playlistSpan.classList.add('queue-playlist-span');
//If this isn't our first rodeo //If this isn't our first rodeo
if(playlistIndex != 0){ if(this.playlistIndex != 0){
//make note //make note
playlistSpan.classList.add('not-first'); this.playlistSpan.classList.add('not-first');
} }
//pre-render and keep this so we can use it later //Render out playlist entry contents
const mediaContainer = renderMedia(); this.renderLabels();
this.renderControls();
this.renderMedia();
//Append items to playlist entry line //Append entry items to playlist entry line
playlistSpan.appendChild((renderLabels.bind(this))()); this.playlistSpan.appendChild(this.playlistLabels);
playlistSpan.appendChild((renderControls.bind(this))()); this.playlistSpan.appendChild(this.playlistControls);
//Append items to playlist div //Append entry line and contents to playlist div
playlistDiv.appendChild(playlistSpan); this.playlistDiv.appendChild(this.playlistSpan);
playlistDiv.appendChild(mediaContainer); this.playlistDiv.appendChild(this.mediaContainer);
//Append current playlist div to the channel playlists div //Append current playlist div to the channel playlists div
this.channelPlaylistDiv.appendChild(playlistDiv); this.channelPlaylistDiv.appendChild(this.playlistDiv);
}
//aux rendering functions }
function renderLabels(){
//Create playlist label span
const playlistLabels = document.createElement('span');
//Set it's class
playlistLabels.classList.add('queue-playlist-labels-span');
//create playlist title span //aux rendering functions
const playlistTitleSpan = document.createElement('span'); renderLabels(){
//Set class //Create playlist label span
playlistTitleSpan.classList.add('queue-playlist-title-span', 'interactive'); this.playlistLabels = document.createElement('span');
//Set it's class
this.playlistLabels.classList.add('queue-playlist-labels-span');
//Create playlist title caret //create playlist title span
const playlistTitleCaret = document.createElement('i'); this.playlistTitleSpan = document.createElement('span');
//Set class //Set class
playlistTitleCaret.classList.add('bi-caret-right-fill'); this.playlistTitleSpan.classList.add('queue-playlist-title-span', 'interactive');
//Create playlist title label //Create playlist title caret
const playlistTitle = document.createElement('p'); this.playlistTitleCaret = document.createElement('i');
//Set it's class //Set class
playlistTitle.classList.add('queue-playlist-title'); this.playlistTitleCaret.classList.add('bi-caret-right-fill');
//Unescape Sanatized Enteties and safely inject as plaintext
playlistTitle.innerText = utils.unescapeEntities(playlist.name);
//Construct playlist title span //Create playlist title label
playlistTitleSpan.appendChild(playlistTitleCaret); this.playlistTitle = document.createElement('p');
playlistTitleSpan.appendChild(playlistTitle); //Set it's class
this.playlistTitle.classList.add('queue-playlist-title');
//Unescape Sanatized Enteties and safely inject as plaintext
this.playlistTitle.innerText = utils.unescapeEntities(this.playlist.name);
//Create playlist count label //Construct playlist title span
const playlistCount = document.createElement('p'); this.playlistTitleSpan.appendChild(this.playlistTitleCaret);
//Set it's class this.playlistTitleSpan.appendChild(this.playlistTitle);
playlistCount.classList.add('queue-playlist-count');
//List video count
playlistCount.innerText = `Count: ${playlist.media.length}`;
//Append items to playlist labels span //Create playlist count label
playlistLabels.appendChild(playlistTitleSpan); this.playlistCount = document.createElement('p');
playlistLabels.appendChild(playlistCount); //Set it's class
this.playlistCount.classList.add('queue-playlist-count');
//List video count
this.playlistCount.innerText = `Count: ${this.playlist.media.length}`;
//Define input listeners //Append items to playlist labels span
playlistTitleSpan.addEventListener('click', toggleMedia.bind(this)); this.playlistLabels.appendChild(this.playlistTitleSpan);
this.playlistLabels.appendChild(this.playlistCount);
//return playlistLabels //Define input listeners
return playlistLabels; this.playlistTitleSpan.addEventListener('click', toggleMedia.bind(this));
function toggleMedia(){ //I'd rather make this a class function but it's probably cleaner to not have to parent crawl
//If the div is hidden function toggleMedia(){
if(mediaContainer.style.display == 'none'){ //If the div is hidden
//Light up the button if(this.mediaContainer.style.display == 'none'){
playlistTitleSpan.classList.add('positive'); //Light up the button
//Flip the caret this.playlistTitleSpan.classList.add('positive');
playlistTitleCaret.classList.replace('bi-caret-right-fill', 'bi-caret-down-fill'); //Flip the caret
//Show the div this.playlistTitleCaret.classList.replace('bi-caret-right-fill', 'bi-caret-down-fill');
mediaContainer.style.display = ''; //Show the div
}else{ this.mediaContainer.style.display = '';
//Unlight the button }else{
playlistTitleSpan.classList.remove('positive'); //Unlight the button
//Flip the caret this.playlistTitleSpan.classList.remove('positive');
playlistTitleCaret.classList.replace('bi-caret-down-fill', 'bi-caret-right-fill'); //Flip the caret
//Hide the div this.playlistTitleCaret.classList.replace('bi-caret-down-fill', 'bi-caret-right-fill');
mediaContainer.style.display = 'none'; //Hide the div
} this.mediaContainer.style.display = 'none';
}
}
function renderControls(){
//Create playlist control span
const playlistControls = document.createElement('span');
//Set it's class
playlistControls.classList.add('queue-playlist-control-span');
//Create queue all button
const playlistQueueRandomButton = document.createElement('button');
//Set it's classes
playlistQueueRandomButton.classList.add('queue-playlist-queue-random-button', 'queue-playlist-control');
//Inject text content
playlistQueueRandomButton.textContent = 'Random';
//Set title
playlistQueueRandomButton.title = 'Queue Random Item from Playlist';
//Create queue all button
const playlistQueueAllButton = document.createElement('button');
//Set it's classes
playlistQueueAllButton.classList.add('queue-playlist-queue-all-button', 'queue-playlist-control');
//Inject text content
playlistQueueAllButton.textContent = 'All';
//Set title
playlistQueueAllButton.title = 'Queue Entire Playlist';
//Create add from URL button
const playlistAddURLButton = document.createElement('button');
//Set it's classes
playlistAddURLButton.classList.add('queue-playlist-add-url-button', 'queue-playlist-control', 'positive-button');
//Set Tile
playlistAddURLButton.title = 'Add To Playlist From URL'
//Create playlist icons (we're using two so we're putting them inside the button :P)
const playlistAddIcon = document.createElement('i');
const playlistLinkIcon = document.createElement('i');
//set classes
playlistAddIcon.classList.add('bi-plus-lg');
playlistLinkIcon.classList.add('bi-link-45deg');
playlistAddURLButton.appendChild(playlistAddIcon);
playlistAddURLButton.appendChild(playlistLinkIcon);
//Create default titles button
const playlistDefaultTitlesButton = document.createElement('button');
//Set classes
playlistDefaultTitlesButton.classList.add('queue-playlist-add-url-button', 'queue-playlist-control', 'bi-tags-fill', 'positive-button');
//Set title
playlistDefaultTitlesButton.title = 'Change Default Titles'
//Create rename button
const playlistRenameButton = document.createElement('button');
//Set it's classes
playlistRenameButton.classList.add('queue-playlist-add-url-button', 'queue-playlist-control', 'bi-input-cursor-text', 'positive-button');
//Set title
playlistRenameButton.title = 'Rename Playlist'
//Create delete button
const playlistDeleteButton = document.createElement('button');
//Set it's classes
playlistDeleteButton.classList.add('queue-playlist-delete-button', 'queue-playlist-control', 'danger-button', 'bi-trash-fill');
//Set title
playlistDeleteButton.title = 'Delete Playlist'
//Append items to playlist control span
playlistControls.appendChild(playlistQueueRandomButton);
playlistControls.appendChild(playlistQueueAllButton);
playlistControls.appendChild(playlistAddURLButton);
playlistControls.appendChild(playlistDefaultTitlesButton);
playlistControls.appendChild(playlistRenameButton);
playlistControls.appendChild(playlistDeleteButton);
//Define input event listeners
playlistAddURLButton.addEventListener('click', (event)=>{new addURLPopup(event, playlist.name, this.client, this.queuePanel.ownerDoc)});
playlistDefaultTitlesButton.addEventListener('click', (event)=>{new defaultTitlesPopup(event, playlist.name, playlist.defaultTitles, this.client, this.queuePanel.ownerDoc)});
playlistRenameButton.addEventListener('click', (event)=>{new renamePopup(event, playlist.name, this.client, this.queuePanel.ownerDoc)});
playlistQueueAllButton.addEventListener('click', queueAll);
playlistDeleteButton.addEventListener('click', deletePlaylist);
return playlistControls;
}
function renderMedia(){
//Create media container div
const mediaContainer = document.createElement('div');
//Set classes
mediaContainer.classList.add('queue-playlist-media-container-div');
//Auto-hide media container
mediaContainer.style.display = 'none';
for(let mediaIndex in playlist.media){
//Grab media object from playlist
const media = playlist.media[mediaIndex];
//Create media div
const mediaDiv = document.createElement('div');
//Set class
mediaDiv.classList.add('queue-playlist-media-div');
//If this isn't our first rodeo
if(mediaIndex != 0){
mediaDiv.classList.add('not-first');
}
//Create media title
const mediaTitle = document.createElement('p');
//Set class
mediaTitle.classList.add('queue-playlist-media-title');
//Inject text content
mediaTitle.innerText = utils.unescapeEntities(media.title);
//Append items to media div
mediaDiv.appendChild(mediaTitle);
//Append media div to media container
mediaContainer.appendChild(mediaDiv);
}
//return media container
return mediaContainer;
}
//playlist control functions
function queueAll(){
client.socket.emit('queueChannelPlaylist', {playlist: playlist.name});
}
function deletePlaylist(){
client.socket.emit('deleteChannelPlaylist', {playlist: playlist.name});
} }
} }
} }
renderControls(){
//Create playlist control span
this.playlistControls = document.createElement('span');
//Set it's class
this.playlistControls.classList.add('queue-playlist-control-span');
//Set dataset
this.playlistControls.dataset['playlist'] = this.playlist.name;
//Create queue all button
this.playlistQueueRandomButton = document.createElement('button');
//Set it's classes
this.playlistQueueRandomButton.classList.add('queue-playlist-queue-random-button', 'queue-playlist-control');
//Inject text content
this.playlistQueueRandomButton.textContent = 'Random';
//Set title
this.playlistQueueRandomButton.title = 'Queue Random Item from Playlist';
//Create queue all button
this.playlistQueueAllButton = document.createElement('button');
//Set it's classes
this.playlistQueueAllButton.classList.add('queue-playlist-queue-all-button', 'queue-playlist-control');
//Inject text content
this.playlistQueueAllButton.textContent = 'All';
//Set title
this.playlistQueueAllButton.title = 'Queue Entire Playlist';
//Create add from URL button
this.playlistAddURLButton = document.createElement('button');
//Set it's classes
this.playlistAddURLButton.classList.add('queue-playlist-add-url-button', 'queue-playlist-control', 'positive-button');
//Set Tile
this.playlistAddURLButton.title = 'Add To Playlist From URL'
//Create playlist icons (we're using two so we're putting them inside the button :P)
this.playlistAddIcon = document.createElement('i');
this.playlistLinkIcon = document.createElement('i');
//set classes
this.playlistAddIcon.classList.add('bi-plus-lg');
this.playlistLinkIcon.classList.add('bi-link-45deg');
this.playlistAddURLButton.appendChild(this.playlistAddIcon);
this.playlistAddURLButton.appendChild(this.playlistLinkIcon);
//Create default titles button
this.playlistDefaultTitlesButton = document.createElement('button');
//Set classes
this.playlistDefaultTitlesButton.classList.add('queue-playlist-add-url-button', 'queue-playlist-control', 'bi-tags-fill', 'positive-button');
//Set title
this.playlistDefaultTitlesButton.title = 'Change Default Titles'
//Set dataset
this.playlistDefaultTitlesButton.dataset['titles'] = JSON.stringify(this.playlist.defaultTitles);
//Create rename button
this.playlistRenameButton = document.createElement('button');
//Set it's classes
this.playlistRenameButton.classList.add('queue-playlist-add-url-button', 'queue-playlist-control', 'bi-input-cursor-text', 'positive-button');
//Set title
this.playlistRenameButton.title = 'Rename Playlist'
//Create delete button
this.playlistDeleteButton = document.createElement('button');
//Set it's classes
this.playlistDeleteButton.classList.add('queue-playlist-delete-button', 'queue-playlist-control', 'danger-button', 'bi-trash-fill');
//Set title
this.playlistDeleteButton.title = 'Delete Playlist'
//Append items to playlist control span
this.playlistControls.appendChild(this.playlistQueueRandomButton);
this.playlistControls.appendChild(this.playlistQueueAllButton);
this.playlistControls.appendChild(this.playlistAddURLButton);
this.playlistControls.appendChild(this.playlistDefaultTitlesButton);
this.playlistControls.appendChild(this.playlistRenameButton);
this.playlistControls.appendChild(this.playlistDeleteButton);
//Define input event listeners
this.playlistAddURLButton.addEventListener('click', this.addURL.bind(this));
this.playlistDefaultTitlesButton.addEventListener('click', this.editDefaultTitles.bind(this));
this.playlistRenameButton.addEventListener('click', this.renamePlaylist.bind(this));
this.playlistQueueAllButton.addEventListener('click', this.queueAll.bind(this));
this.playlistDeleteButton.addEventListener('click', this.deletePlaylist.bind(this));
}
renderMedia(){
//Create media container div
this.mediaContainer = document.createElement('div');
//Set classes
this.mediaContainer.classList.add('queue-playlist-media-container-div');
//Auto-hide media container
this.mediaContainer.style.display = 'none';
for(let mediaIndex in this.playlist.media){
//Grab media object from playlist
const media = this.playlist.media[mediaIndex];
//Create media div
const mediaDiv = document.createElement('div');
//Set class
mediaDiv.classList.add('queue-playlist-media-div');
//If this isn't our first rodeo
if(mediaIndex != 0){
mediaDiv.classList.add('not-first');
}
//Create media title
const mediaTitle = document.createElement('p');
//Set class
mediaTitle.classList.add('queue-playlist-media-title');
//Inject text content
mediaTitle.innerText = utils.unescapeEntities(media.title);
//Append items to media div
mediaDiv.appendChild(mediaTitle);
//Append media div to media container
this.mediaContainer.appendChild(mediaDiv);
}
//return media container
this.mediaContainer;
}
addURL(event){
new addURLPopup(
event,
event.target.parentNode.dataset['playlist'],
this.client,
this.queuePanel.ownerDoc
);
}
//playlist control functions
editDefaultTitles(event){
new defaultTitlesPopup(
event,
event.target.parentNode.dataset['playlist'],
JSON.parse(event.target.dataset['titles']),
this.client,
this.queuePanel.ownerDoc
);
}
renamePlaylist(event){
new renamePopup(
event,
event.target.parentNode.dataset['playlist'],
this.client,
this.queuePanel.ownerDoc
);
}
queueAll(event){
client.socket.emit('queueChannelPlaylist', {playlist: event.target.parentNode.dataset['playlist']});
}
deletePlaylist(event){
client.socket.emit('deleteChannelPlaylist', {playlist: event.target.parentNode.dataset['playlist']});
}
} }
class newPlaylistPopup{ class newPlaylistPopup{