diff --git a/www/css/global.css b/www/css/global.css index 267de1f..3698b6f 100644 --- a/www/css/global.css +++ b/www/css/global.css @@ -81,6 +81,12 @@ div.dynamic-container, div.nested-dynamic-container{ 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{ display: flex; diff --git a/www/js/channel/panels/queuePanel/playlistManager.js b/www/js/channel/panels/queuePanel/playlistManager.js index 6349857..9480f9b 100644 --- a/www/js/channel/panels/queuePanel/playlistManager.js +++ b/www/js/channel/panels/queuePanel/playlistManager.js @@ -80,238 +80,269 @@ class playlistManager{ //For every playlist sent down from the server for(let playlistIndex in data){ //Get playlist from data - const playlist = data[playlistIndex]; + this.playlist = data[playlistIndex]; //Create a new playlist div - const playlistDiv = document.createElement('div'); + this.playlistDiv = document.createElement('div'); //Set it's class - playlistDiv.classList.add('queue-playlist-div'); + this.playlistDiv.classList.add('queue-playlist-div'); //Set playlist div dataset - playlistDiv.dataset.name = playlist.name; + this.playlistDiv.dataset.name = this.playlist.name; //Create span to hold playlist entry line contents - const playlistSpan = document.createElement('span'); + this.playlistSpan = document.createElement('span'); //Set classes - playlistSpan.classList.add('queue-playlist-span'); + this.playlistSpan.classList.add('queue-playlist-span'); //If this isn't our first rodeo - if(playlistIndex != 0){ + if(this.playlistIndex != 0){ //make note - playlistSpan.classList.add('not-first'); + this.playlistSpan.classList.add('not-first'); } - //pre-render and keep this so we can use it later - const mediaContainer = renderMedia(); + //Render out playlist entry contents + this.renderLabels(); + this.renderControls(); + this.renderMedia(); - //Append items to playlist entry line - playlistSpan.appendChild((renderLabels.bind(this))()); - playlistSpan.appendChild((renderControls.bind(this))()); + //Append entry items to playlist entry line + this.playlistSpan.appendChild(this.playlistLabels); + this.playlistSpan.appendChild(this.playlistControls); - //Append items to playlist div - playlistDiv.appendChild(playlistSpan); - playlistDiv.appendChild(mediaContainer); + //Append entry line and contents to playlist div + this.playlistDiv.appendChild(this.playlistSpan); + this.playlistDiv.appendChild(this.mediaContainer); //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 - const playlistTitleSpan = document.createElement('span'); - //Set class - playlistTitleSpan.classList.add('queue-playlist-title-span', 'interactive'); + //aux rendering functions + renderLabels(){ + //Create playlist label span + this.playlistLabels = document.createElement('span'); + //Set it's class + this.playlistLabels.classList.add('queue-playlist-labels-span'); - //Create playlist title caret - const playlistTitleCaret = document.createElement('i'); - //Set class - playlistTitleCaret.classList.add('bi-caret-right-fill'); + //create playlist title span + this.playlistTitleSpan = document.createElement('span'); + //Set class + this.playlistTitleSpan.classList.add('queue-playlist-title-span', 'interactive'); - //Create playlist title label - const playlistTitle = document.createElement('p'); - //Set it's class - playlistTitle.classList.add('queue-playlist-title'); - //Unescape Sanatized Enteties and safely inject as plaintext - playlistTitle.innerText = utils.unescapeEntities(playlist.name); + //Create playlist title caret + this.playlistTitleCaret = document.createElement('i'); + //Set class + this.playlistTitleCaret.classList.add('bi-caret-right-fill'); - //Construct playlist title span - playlistTitleSpan.appendChild(playlistTitleCaret); - playlistTitleSpan.appendChild(playlistTitle); + //Create playlist title label + this.playlistTitle = document.createElement('p'); + //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 - const playlistCount = document.createElement('p'); - //Set it's class - playlistCount.classList.add('queue-playlist-count'); - //List video count - playlistCount.innerText = `Count: ${playlist.media.length}`; + //Construct playlist title span + this.playlistTitleSpan.appendChild(this.playlistTitleCaret); + this.playlistTitleSpan.appendChild(this.playlistTitle); - //Append items to playlist labels span - playlistLabels.appendChild(playlistTitleSpan); - playlistLabels.appendChild(playlistCount); + //Create playlist count label + this.playlistCount = document.createElement('p'); + //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 - playlistTitleSpan.addEventListener('click', toggleMedia.bind(this)); + //Append items to playlist labels span + this.playlistLabels.appendChild(this.playlistTitleSpan); + this.playlistLabels.appendChild(this.playlistCount); - //return playlistLabels - return playlistLabels; + //Define input listeners + this.playlistTitleSpan.addEventListener('click', toggleMedia.bind(this)); - function toggleMedia(){ - //If the div is hidden - if(mediaContainer.style.display == 'none'){ - //Light up the button - playlistTitleSpan.classList.add('positive'); - //Flip the caret - playlistTitleCaret.classList.replace('bi-caret-right-fill', 'bi-caret-down-fill'); - //Show the div - mediaContainer.style.display = ''; - }else{ - //Unlight the button - playlistTitleSpan.classList.remove('positive'); - //Flip the caret - playlistTitleCaret.classList.replace('bi-caret-down-fill', 'bi-caret-right-fill'); - //Hide the div - 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}); + //I'd rather make this a class function but it's probably cleaner to not have to parent crawl + function toggleMedia(){ + //If the div is hidden + if(this.mediaContainer.style.display == 'none'){ + //Light up the button + this.playlistTitleSpan.classList.add('positive'); + //Flip the caret + this.playlistTitleCaret.classList.replace('bi-caret-right-fill', 'bi-caret-down-fill'); + //Show the div + this.mediaContainer.style.display = ''; + }else{ + //Unlight the button + this.playlistTitleSpan.classList.remove('positive'); + //Flip the caret + this.playlistTitleCaret.classList.replace('bi-caret-down-fill', 'bi-caret-right-fill'); + //Hide the div + this.mediaContainer.style.display = 'none'; } } } + 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{