From 7224a2f51e175666f8c52f46300e2562c1bb7fd4 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Tue, 14 Sep 2021 20:56:43 +0300 Subject: [PATCH 01/31] createElement func general function creates element and gives it class,atrributes and children --- scripts/index.new.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index c3a39c8e..8787a3d1 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -79,7 +79,20 @@ function createPlaylistElement({ id, name, songs }) { * @param {Object} eventListeners - the event listeners on the element */ function createElement(tagName, children = [], classes = [], attributes = {}, eventListeners = {}) { - // Your code here + const el = document.createElement(tagName); + // Children + for(const child of children) { + el.append(child); + } + // Classes + for(const cls of classes) { + el.classList.add(cls); + } + // Attributes + for (const attr in attributes) { + el.setAttribute(attr, attributes[attr]); + } + return el; } /** From eba6338899b7d1cf738ef2af6a2d2895602e6988 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:22:30 +0300 Subject: [PATCH 02/31] createSongElement added createSongElement( func. and 2 support functions: findSong secToDur --- scripts/index.new.js | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index 8787a3d1..8128c388 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -1,3 +1,17 @@ +/*support functions */ +function findSong(id,mPlayer=player){ + for(let song of mPlayer.songs){ + if (song.id===id){ + return song; + } + } + throw "ID not found"; +} + +function secToDur(sec){ + return((Math.floor(sec/60))<10? "0": "")+`${Math.floor(sec/60)}:` +((sec%60)<10? "0": "")+`${sec%60}` +} + /** * Plays a song from the player. * Playing a song means changing the visual indication of the currently playing song. @@ -47,13 +61,14 @@ function handleAddSongEvent(event) { * Creates a song DOM element based on a song object. */ function createSongElement({ id, title, album, artist, duration, coverArt }) { - const children = [] - const classes = [] - const attrs = {} - const eventListeners = {} - return createElement("div", children, classes, attrs, eventListeners) + const nameEl=createElement("span", [title],["song-name"]); + const albumEl=createElement("span",[album],["album-name"]) + const artistEl = createElement("span", [artist],["artist"]); + const durationEl = createElement("span", ["" + secToDur(duration)] ,["duration", "short-duration"], {onclick: `console.log('${duration}')`}); + const imgEl = createElement("img", [] ,["album-art"], {src: coverArt}); + return createElement("div", [nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl, imgEl],["song"],{id:id+"song", onclick: `playSong(${id})` }); } - +console.log(createSongElement(player.songs[0])) /** * Creates a playlist DOM element based on a playlist object. */ From d9ef536d0bfccc390568320bcf24ba76ba486bac Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:27:30 +0300 Subject: [PATCH 03/31] createPlaylistElement added createPlaylistElement func. and support function - playlistDuration. --- scripts/index.new.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index 8128c388..acfbb70f 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -12,6 +12,14 @@ function secToDur(sec){ return((Math.floor(sec/60))<10? "0": "")+`${Math.floor(sec/60)}:` +((sec%60)<10? "0": "")+`${sec%60}` } +function playlistDuration(id) { + let plDuration=0; + for(let songID of findPlaylist(id).songs){ + plDuration+=(findSong(songID).duration); + } + return (plDuration); +} + /** * Plays a song from the player. * Playing a song means changing the visual indication of the currently playing song. @@ -73,11 +81,10 @@ console.log(createSongElement(player.songs[0])) * Creates a playlist DOM element based on a playlist object. */ function createPlaylistElement({ id, name, songs }) { - const children = [] - const classes = [] - const attrs = {} - const eventListeners = {} - return createElement("div", children, classes, attrs, eventListeners) + const nameEl=createElement("span", [name,":"],["playlist-name"]); + const quantityEl=createElement("span",[songs.length],["num-of-song"]) + const attrs = {id:id+"pl"} + return createElement("div", [nameEl,"Number Of Songs:",quantityEl,"Playlist Duration:",secToDur(playlistDuration(id))], ["playlist"],attrs) } /** From 5a4ed7302453101a9c8ac13a96b388a36094450b Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:33:15 +0300 Subject: [PATCH 04/31] generateSongs & generatePlaylists functions that append songs and playlist in there place on the html(webpage) --- scripts/index.new.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index acfbb70f..1ad6f725 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -120,15 +120,21 @@ function createElement(tagName, children = [], classes = [], attributes = {}, ev /** * Inserts all songs in the player as DOM elements into the songs list. */ -function generateSongs() { - // Your code here +const songEl=document.getElementById("songs") +function generateSongs(player) { + for(song of player.songs){ + songEl.append(createSongElement(song)); + } } /** * Inserts all playlists in the player as DOM elements into the playlists list. */ -function generatePlaylists() { - // Your code here +const playListEl=document.getElementById("playlists") +function generatePlaylists(player) { + for(playlist of player.playlists){ + playListEl.append(createPlaylistElement(playlist)); + } } // Creating the page structure From 946bc806d0983ab98ca13fd48426ddfea666f633 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:37:43 +0300 Subject: [PATCH 05/31] added playsong func. this func. change the class of the song that is currently played. and in the css file it gives this class visable diffrent. the player could play only one song at a time. --- scripts/index.new.js | 16 +++++++++++++--- style.css | 28 +++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index 1ad6f725..87c9b6b5 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -26,9 +26,19 @@ function playlistDuration(id) { * * @param {Number} songId - the ID of the song to play */ -function playSong(songId) { - // Your code here -} + let lastSongPlayed; + function playSong(songId) { + try{ + lastSongPlayed.classList.remove("now-playing"); + }finally{ + const songElement=document.getElementById(songId+"song") + const song=findSong(songId); + songElement.classList.add("now-playing"); + setTimeout(()=>songElement.classList.remove("now-playing"),song.duration*1000); + setTimeout(()=>playSong(player.songs[(player.songs.indexOf(song)+1)].id),song.duration*1000); + lastSongPlayed=songElement; + } + } /** * Removes a song from the player, and updates the DOM to match. diff --git a/style.css b/style.css index f4645fe9..6a803a8a 100644 --- a/style.css +++ b/style.css @@ -1 +1,27 @@ -/* Your code here */ +body{ + text-align: center; + font-size: 200%; + background-image: url("https://www.freepik.com/free-photo/abstract-smoke-wallpaper-background-desktop_17581093.htm#page=1&query=Background&position=9"); + background-color: #b9992d; + } + + .album-art{ + border-radius: 50%; + display: block; + margin-left: auto; + margin-right: auto; + margin-bottom: 5%; + margin-top: 2%; + width: 25%; + border: 3px solid rgb(26, 167, 136); + padding: 2px; + align-items: center; + } + + .now-playing{ + background-color: rgb(5, 58, 58); + + } + span{ + margin-right: 2%; + } \ No newline at end of file From c7b8105a53f995fd0361e0601c97fa8b5ae79ddb Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:41:17 +0300 Subject: [PATCH 06/31] findPlaylist added findPlaylist support function --- scripts/index.new.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/index.new.js b/scripts/index.new.js index 87c9b6b5..fe9694d7 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -8,6 +8,15 @@ function findSong(id,mPlayer=player){ throw "ID not found"; } +function findPlaylist(id,mPlayer=player){ + for(let Playlist of mPlayer.playlists){ + if (Playlist.id===id){ + return Playlist; + } + } + throw "ID not found"; +} + function secToDur(sec){ return((Math.floor(sec/60))<10? "0": "")+`${Math.floor(sec/60)}:` +((sec%60)<10? "0": "")+`${sec%60}` } From 4a0aec5a24a297608ff67546067570e5f6122b2e Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:41:46 +0300 Subject: [PATCH 07/31] genarateing songs and playlists --- scripts/index.new.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index fe9694d7..83e268c4 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -157,8 +157,8 @@ function generatePlaylists(player) { } // Creating the page structure -generateSongs() -generatePlaylists() +generateSongs(player) +generatePlaylists(player) // Making the add-song-button actually do something document.getElementById("add-button").addEventListener("click", handleAddSongEvent) From bc413ac0065b74a4e49ba43fca168a17aaf09c18 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:45:13 +0300 Subject: [PATCH 08/31] addSong added addSong func. and support func. generateSongId --- scripts/index.new.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index 83e268c4..0e886243 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -17,6 +17,12 @@ function findPlaylist(id,mPlayer=player){ throw "ID not found"; } +let newSongId=10; +function generateSongId(){ + newSongId+=1; + return newSongId; +} + function secToDur(sec){ return((Math.floor(sec/60))<10? "0": "")+`${Math.floor(sec/60)}:` +((sec%60)<10? "0": "")+`${sec%60}` } @@ -61,8 +67,16 @@ function removeSong(songId) { /** * Adds a song to the player, and updates the DOM to match. */ -function addSong({ title, album, artist, duration, coverArt }) { - // Your code here + function addSong({ title, album, artist, duration, coverArt }) { + player.songs.push({ + id: generateSongId(), + title: title, + album: album, + artist: artist, + duration: duration, + coverArt: coverArt + }) + songEl.append(createSongElement(player.songs[player.songs.length-1])); } /** From 244988f4eb534902cfa2c164ff407d30a51e5eb8 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:54:56 +0300 Subject: [PATCH 09/31] handleAddSongEvent func. that operats the addSong button --- index.new.html | 10 +++++----- scripts/index.new.js | 9 ++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/index.new.html b/index.new.html index eba39f17..b5bafb19 100644 --- a/index.new.html +++ b/index.new.html @@ -13,11 +13,11 @@

Awesome Player!!!

Add a new song

- - - - - + + + + +
diff --git a/scripts/index.new.js b/scripts/index.new.js index 0e886243..8a65a7c0 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -95,7 +95,12 @@ function handleSongClickEvent(event) { * @param {MouseEvent} event - the click event */ function handleAddSongEvent(event) { - // Your code here + let title=document.getElementById("title").value + ,album=document.getElementById("album").value + ,artist=document.getElementById("artist").value + ,duration=document.getElementById("duration").value + ,coverArt=document.getElementById("cover-art").value + addSong({title,album,artist,duration,coverArt}) } /** @@ -109,7 +114,6 @@ function createSongElement({ id, title, album, artist, duration, coverArt }) { const imgEl = createElement("img", [] ,["album-art"], {src: coverArt}); return createElement("div", [nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl, imgEl],["song"],{id:id+"song", onclick: `playSong(${id})` }); } -console.log(createSongElement(player.songs[0])) /** * Creates a playlist DOM element based on a playlist object. */ @@ -173,6 +177,5 @@ function generatePlaylists(player) { // Creating the page structure generateSongs(player) generatePlaylists(player) - // Making the add-song-button actually do something document.getElementById("add-button").addEventListener("click", handleAddSongEvent) From c5a6fc9cfab68b401d69f33c8cbd15aa05d39d21 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:14:43 +0300 Subject: [PATCH 10/31] added play&delete buttons --- scripts/index.new.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index 8a65a7c0..b8cee122 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -112,7 +112,9 @@ function createSongElement({ id, title, album, artist, duration, coverArt }) { const artistEl = createElement("span", [artist],["artist"]); const durationEl = createElement("span", ["" + secToDur(duration)] ,["duration", "short-duration"], {onclick: `console.log('${duration}')`}); const imgEl = createElement("img", [] ,["album-art"], {src: coverArt}); - return createElement("div", [nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl, imgEl],["song"],{id:id+"song", onclick: `playSong(${id})` }); + const playEl = createElement("button",["▶"],["button"],{id:"playButton"}); + const deleteEl = createElement("button",["❌"],["button"],{id:"deleteButton"}); + return createElement("div", [nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl, imgEl,playEl,deleteEl],["song"],{id:id+"song", onclick: `playSong(${id})` }); } /** * Creates a playlist DOM element based on a playlist object. @@ -179,3 +181,4 @@ generateSongs(player) generatePlaylists(player) // Making the add-song-button actually do something document.getElementById("add-button").addEventListener("click", handleAddSongEvent) + From dea8403670dbe432f1801f18a7584c712dad2e3a Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:15:59 +0300 Subject: [PATCH 11/31] added removeSong func. Deletes from the player and removes from DOM --- scripts/index.new.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index b8cee122..ee8124e3 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -61,7 +61,11 @@ function playlistDuration(id) { * @param {Number} songId - the ID of the song to remove */ function removeSong(songId) { - // Your code here + player.songs.splice(player.songs.indexOf(findSong(songId)),1); + for(let playlist of player.playlists){ + playlist.songs.splice(playlist.songs.indexOf(songId),1) + } + document.getElementById(songId+"song").remove(); } /** From 24603b1e95059b6f616b051dcc7e8a12488512c6 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:23:18 +0300 Subject: [PATCH 12/31] fixed duration and added checkDurationInput --- scripts/index.new.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index ee8124e3..79857dfc 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -27,6 +27,20 @@ function secToDur(sec){ return((Math.floor(sec/60))<10? "0": "")+`${Math.floor(sec/60)}:` +((sec%60)<10? "0": "")+`${sec%60}` } +function durationToSeconds(duration){ + checkDurationInput(duration) + return((parseInt(duration[0])*10)+parseInt(duration[1]))*60 + +parseInt(duration[3]*10)+parseInt(duration[4]) +} + +function checkDurationInput(duration){ // checks digits(maximum is 59:59/minimum is 00:00),:,length. + if(0<=parseInt(duration[0])&&parseInt(duration[0])<6&&0<=parseInt(duration[1])&&parseInt(duration[1])<=9 + &&duration[2]===":"&&0<=parseInt(duration[3])&&parseInt(duration[3])<6&&0<=parseInt(duration[4]) + &&parseInt(duration[4])<=9&&duration.length===5){ + return true + }else throw 'Duration is not in the correct format...This is the format-"mm:ss" (for example 03:13)' +} + function playlistDuration(id) { let plDuration=0; for(let songID of findPlaylist(id).songs){ @@ -72,12 +86,13 @@ function removeSong(songId) { * Adds a song to the player, and updates the DOM to match. */ function addSong({ title, album, artist, duration, coverArt }) { + checkDurationInput(duration) player.songs.push({ id: generateSongId(), title: title, album: album, artist: artist, - duration: duration, + duration: durationToSeconds(duration), coverArt: coverArt }) songEl.append(createSongElement(player.songs[player.songs.length-1])); From 2533fb31b36401711a81aa06fc1908b95dc2aa5f Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 15 Sep 2021 12:01:50 +0300 Subject: [PATCH 13/31] eventListener for play and delete buttons **need to be rewritten** (working) --- scripts/index.new.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index 79857dfc..888d5bad 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -113,13 +113,18 @@ function handleSongClickEvent(event) { * * @param {MouseEvent} event - the click event */ -function handleAddSongEvent(event) { +function handleAddSongEvent(event) { // works-need to be written better let title=document.getElementById("title").value ,album=document.getElementById("album").value ,artist=document.getElementById("artist").value ,duration=document.getElementById("duration").value ,coverArt=document.getElementById("cover-art").value addSong({title,album,artist,duration,coverArt}) + document.getElementById("title").value=null; + document.getElementById("album").value=null; + document.getElementById("artist").value=null; + document.getElementById("duration").value=null; + document.getElementById("cover-art").value=null; } /** @@ -131,9 +136,9 @@ function createSongElement({ id, title, album, artist, duration, coverArt }) { const artistEl = createElement("span", [artist],["artist"]); const durationEl = createElement("span", ["" + secToDur(duration)] ,["duration", "short-duration"], {onclick: `console.log('${duration}')`}); const imgEl = createElement("img", [] ,["album-art"], {src: coverArt}); - const playEl = createElement("button",["▶"],["button"],{id:"playButton"}); - const deleteEl = createElement("button",["❌"],["button"],{id:"deleteButton"}); - return createElement("div", [nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl, imgEl,playEl,deleteEl],["song"],{id:id+"song", onclick: `playSong(${id})` }); + const playEl = createElement("button",["▶"],["play-button"],{id:"playButton"}); + const deleteEl = createElement("button",["❌"],["remove-button"],{id:"deleteButton"}); + return createElement("div", [nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl, imgEl,playEl,deleteEl],["song"],{id:id+"song"}); } /** * Creates a playlist DOM element based on a playlist object. @@ -201,3 +206,12 @@ generatePlaylists(player) // Making the add-song-button actually do something document.getElementById("add-button").addEventListener("click", handleAddSongEvent) +//Making the play and delete buttons actually do something +document.getElementById("songs").addEventListener("click" , function(event) { // works-need to be written better + if (event.target.className != "remove-button"){ + if(event.target.className !="play-button")return; + } + let song = event.target.closest(".song"); + if(event.target.className === "remove-button") removeSong(parseInt(song.id.substring(0,1))) + if(event.target.className ==="play-button") playSong(parseInt(song.id.substring(0,1))) +}); From db30bfb48a4e8f307b95757007cb1f97d15100f0 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Thu, 16 Sep 2021 21:48:00 +0300 Subject: [PATCH 14/31] updatePlaylist func. used after removing songs --- index.new.html | 14 +++----------- scripts/index.new.js | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/index.new.html b/index.new.html index b5bafb19..ec1380a1 100644 --- a/index.new.html +++ b/index.new.html @@ -45,17 +45,9 @@

Songs

Playlists

-
- -
+
diff --git a/scripts/index.new.js b/scripts/index.new.js index 888d5bad..d99cd458 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -49,6 +49,14 @@ function playlistDuration(id) { return (plDuration); } +function updatePlaylist(){ + const list = document.getElementById("playListList"); + while (list.hasChildNodes()) { + list.removeChild(list.firstChild); + } + generatePlaylists(player); +} + /** * Plays a song from the player. * Playing a song means changing the visual indication of the currently playing song. @@ -80,6 +88,7 @@ function removeSong(songId) { playlist.songs.splice(playlist.songs.indexOf(songId),1) } document.getElementById(songId+"song").remove(); + updatePlaylist(); } /** @@ -147,7 +156,7 @@ function createPlaylistElement({ id, name, songs }) { const nameEl=createElement("span", [name,":"],["playlist-name"]); const quantityEl=createElement("span",[songs.length],["num-of-song"]) const attrs = {id:id+"pl"} - return createElement("div", [nameEl,"Number Of Songs:",quantityEl,"Playlist Duration:",secToDur(playlistDuration(id))], ["playlist"],attrs) + return createElement("li", [nameEl,"Number Of Songs:",quantityEl,"Playlist Duration:",secToDur(playlistDuration(id))], ["playlist"],attrs) } /** @@ -193,7 +202,7 @@ function generateSongs(player) { /** * Inserts all playlists in the player as DOM elements into the playlists list. */ -const playListEl=document.getElementById("playlists") +const playListEl=document.getElementById("playListList") function generatePlaylists(player) { for(playlist of player.playlists){ playListEl.append(createPlaylistElement(playlist)); @@ -215,3 +224,6 @@ document.getElementById("songs").addEventListener("click" , function(event) { if(event.target.className === "remove-button") removeSong(parseInt(song.id.substring(0,1))) if(event.target.className ==="play-button") playSong(parseInt(song.id.substring(0,1))) }); + + +// generatePlaylists(player) \ No newline at end of file From aed83cb4c910baf2cab528b97729f3b7876c0c9c Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Thu, 16 Sep 2021 22:20:06 +0300 Subject: [PATCH 15/31] fixed bug-deleteing wrong songs from playlist becuse that indexof returns -1 if it doesn't find the song in the playlist, but splice does delete songs for -1 valew(from the end) --- scripts/index.new.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index d99cd458..15fd264b 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -83,9 +83,10 @@ function updatePlaylist(){ * @param {Number} songId - the ID of the song to remove */ function removeSong(songId) { - player.songs.splice(player.songs.indexOf(findSong(songId)),1); + console.log(player.songs.splice(player.songs.indexOf(findSong(songId)),1)); for(let playlist of player.playlists){ - playlist.songs.splice(playlist.songs.indexOf(songId),1) + const songIndex=playlist.songs.indexOf(songId); + songIndex>=0? playlist.songs.splice(songIndex,1) :songId; } document.getElementById(songId+"song").remove(); updatePlaylist(); From 15727bdf7c2684529f6ad6251195b75efc123b1b Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Thu, 16 Sep 2021 22:30:34 +0300 Subject: [PATCH 16/31] Presents the song sorted by title(A-Z) use support func. sortByTitle --- scripts/index.new.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index 15fd264b..a4bf1f61 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -57,6 +57,17 @@ function updatePlaylist(){ generatePlaylists(player); } +function sortByTitle(a, b) { + let titleA = a.title.toUpperCase(); + let titleB = b.title.toUpperCase(); + if (titleA < titleB) { + return -1; + } + if (titleA > titleB) { + return 1; + } +} + /** * Plays a song from the player. * Playing a song means changing the visual indication of the currently playing song. @@ -195,7 +206,7 @@ function createElement(tagName, children = [], classes = [], attributes = {}, ev */ const songEl=document.getElementById("songs") function generateSongs(player) { - for(song of player.songs){ + for(song of player.songs.sort(sortByTitle)){ songEl.append(createSongElement(song)); } } From 22a4e43dfbbc490aaae00e969689a371bd66d8e6 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Thu, 16 Sep 2021 23:31:36 +0300 Subject: [PATCH 17/31] moved the code into the tempate func. --- scripts/index.new.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index a4bf1f61..0bd82f40 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -125,8 +125,13 @@ function removeSong(songId) { * * @param {MouseEvent} event - the click event */ -function handleSongClickEvent(event) { - // Your code here +function handleSongClickEvent(event) { // works-need to be written better + if (event.target.className != "remove-button"){ + if(event.target.className !="play-button")return; + } + let song = event.target.closest(".song"); + if(event.target.className === "remove-button") removeSong(parseInt(song.id.substring(0,1))) + if(event.target.className ==="play-button") playSong(parseInt(song.id.substring(0,1))) } /** @@ -228,14 +233,7 @@ generatePlaylists(player) document.getElementById("add-button").addEventListener("click", handleAddSongEvent) //Making the play and delete buttons actually do something -document.getElementById("songs").addEventListener("click" , function(event) { // works-need to be written better - if (event.target.className != "remove-button"){ - if(event.target.className !="play-button")return; - } - let song = event.target.closest(".song"); - if(event.target.className === "remove-button") removeSong(parseInt(song.id.substring(0,1))) - if(event.target.className ==="play-button") playSong(parseInt(song.id.substring(0,1))) -}); +document.getElementById("songs").addEventListener("click" ,handleSongClickEvent ); // generatePlaylists(player) \ No newline at end of file From 6254de126df836e66275cbaa7ef33a756af6cc7d Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Fri, 17 Sep 2021 13:00:52 +0300 Subject: [PATCH 18/31] putting all text inside element seprated the text from the image and buttons --- scripts/index.new.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/index.new.js b/scripts/index.new.js index 0bd82f40..294d0f8c 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -108,8 +108,9 @@ function removeSong(songId) { */ function addSong({ title, album, artist, duration, coverArt }) { checkDurationInput(duration) + newId=generateSongId(); player.songs.push({ - id: generateSongId(), + id: newId, title: title, album: album, artist: artist, @@ -117,6 +118,9 @@ function removeSong(songId) { coverArt: coverArt }) songEl.append(createSongElement(player.songs[player.songs.length-1])); + let placeAfterThisSong=player.songs.sort(sortByTitle)[(player.songs.indexOf(findSong(newId))-1)].id; + (document.getElementById(newId+"song")).after(document.getElementById(placeAfterThisSong+"song")) + } /** @@ -157,14 +161,15 @@ function handleAddSongEvent(event) { // works-need to * Creates a song DOM element based on a song object. */ function createSongElement({ id, title, album, artist, duration, coverArt }) { - const nameEl=createElement("span", [title],["song-name"]); - const albumEl=createElement("span",[album],["album-name"]) + const nameEl = createElement("span", [title],["song-name"]); + const albumEl = createElement("span",[album],["album-name"]) const artistEl = createElement("span", [artist],["artist"]); const durationEl = createElement("span", ["" + secToDur(duration)] ,["duration", "short-duration"], {onclick: `console.log('${duration}')`}); - const imgEl = createElement("img", [] ,["album-art"], {src: coverArt}); const playEl = createElement("button",["▶"],["play-button"],{id:"playButton"}); const deleteEl = createElement("button",["❌"],["remove-button"],{id:"deleteButton"}); - return createElement("div", [nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl, imgEl,playEl,deleteEl],["song"],{id:id+"song"}); + const imgEl = createElement("img", [] ,["album-art"], {src: coverArt}); + const textEl = createElement("div",[nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl],["text"]) + return createElement("div", [imgEl,playEl,deleteEl,textEl],["song"],{id:id+"song"}); } /** * Creates a playlist DOM element based on a playlist object. @@ -236,4 +241,3 @@ document.getElementById("add-button").addEventListener("click", handleAddSongEve document.getElementById("songs").addEventListener("click" ,handleSongClickEvent ); -// generatePlaylists(player) \ No newline at end of file From 7c1bb5f1abbeb84f8431d22448119d0714d796e1 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Fri, 17 Sep 2021 13:01:14 +0300 Subject: [PATCH 19/31] added style --- style.css | 131 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 108 insertions(+), 23 deletions(-) diff --git a/style.css b/style.css index 6a803a8a..e1496c70 100644 --- a/style.css +++ b/style.css @@ -1,27 +1,112 @@ + +*, *:before, *:after { + box-sizing: border-box; + } body{ text-align: center; - font-size: 200%; - background-image: url("https://www.freepik.com/free-photo/abstract-smoke-wallpaper-background-desktop_17581093.htm#page=1&query=Background&position=9"); - background-color: #b9992d; + font-size: 100%; + background-image: url(./images/photo-1507838153414-b4b713384a76.jfif); + background-repeat: no-repeat; + background-size: cover; + background-color: #d4cfbf; + margin: 0,0,0,0; } + +.album-art{ + border-radius: 50%; + display: block; + margin-left: auto; + margin-right: auto; + margin-bottom: 0; + margin-top: 2%; + width: 50%; + border: 2px solid rgba(84, 87, 87, 0.329); + padding: 2px; + align-items: center; + size: 5px; +} + + +.short-duration{ + color: greenyellow; +} +.duration{ + color: indianred; +} + +span{ + margin-right: 0; +} +.text{ + -webkit-animation: moving 11s infinite; + animation: moving 11s infinite; +} +@keyframes moving { + from {transform: translateX(0%);} + to {transform: translateX(110%);} +} +h2{ + display: none; +} +.song{ + position: relative; + width: 390px; + padding: 10px 40px; + border: 1px transparent; + border-radius: 15px; + background: transparent 50%; + overflow: hidden; + align-self: center; + margin-left: 34%; + } + #inputs{ + display: flex; + flex-direction: column; + align-items:center; + justify-content : space-around; + + } + input{ + width: 50%; + padding:5px; + margin: 5px; + border-radius:15px; + border:0; + box-shadow:4px 4px 10px rgba(0, 0, 0, 0.514); + height:50px; + background-color: transparent; + color: rgb(20, 2, 70); - .album-art{ - border-radius: 50%; - display: block; - margin-left: auto; - margin-right: auto; - margin-bottom: 5%; - margin-top: 2%; - width: 25%; - border: 3px solid rgb(26, 167, 136); - padding: 2px; - align-items: center; - } - - .now-playing{ - background-color: rgb(5, 58, 58); - - } - span{ - margin-right: 2%; - } \ No newline at end of file +} +input:hover { + background-color: #634d4d2f; + border: 10px solid rgba(134, 129, 129, 0); + } + +::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ + color: rgba(8, 0, 0, 0.418); + font-weight: bold; + } + #add-button { + + /* remove default behavior */ + appearance:none; + -webkit-appearance:none; + + /* usual styles */ + padding:10px; + border:none; + background-color:#3f51b585; + color:#fff; + font-weight:600; + border-radius:5px; + width: 50%; + + } + #add-button:hover{ + background-color:#3f51b5; + + } + .now-playing{ + background-color: rgba(61, 199, 199, 0.315); +} \ No newline at end of file From 5ea29858c85f8d7be10d25e983f0c36c22e68d94 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Fri, 17 Sep 2021 13:01:47 +0300 Subject: [PATCH 20/31] backround --- images/photo-1507838153414-b4b713384a76.jfif | Bin 0 -> 85139 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/photo-1507838153414-b4b713384a76.jfif diff --git a/images/photo-1507838153414-b4b713384a76.jfif b/images/photo-1507838153414-b4b713384a76.jfif new file mode 100644 index 0000000000000000000000000000000000000000..0dc4e6660d1230e04a8b6f2d96249b7ea2aa2c0e GIT binary patch literal 85139 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 J-X9u&|Jg>%N7n!V literal 0 HcmV?d00001 From c674fe340944dc5fa20233e6d2cab6fd5fa21f70 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Fri, 17 Sep 2021 13:02:05 +0300 Subject: [PATCH 21/31] added class --- index.new.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.new.html b/index.new.html index ec1380a1..10de2709 100644 --- a/index.new.html +++ b/index.new.html @@ -13,11 +13,11 @@

Awesome Player!!!

Add a new song

- - - - - + + + + +
From 6260c662ad97249c7b3e18b4657a19a854b017eb Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Fri, 17 Sep 2021 15:22:03 +0300 Subject: [PATCH 22/31] first changes --- index.new.html | 60 +++++++++++++------------ scripts/index.new.js | 21 ++++++++- style.css | 103 +++++++++++++++++++++++++------------------ 3 files changed, 111 insertions(+), 73 deletions(-) diff --git a/index.new.html b/index.new.html index 10de2709..db9e00a3 100644 --- a/index.new.html +++ b/index.new.html @@ -11,43 +11,45 @@

Awesome Player!!!

-

Add a new song

-
- +

Add a new song

+
+ - +
- + +
-
-

Songs

-
- +
--> +
+
+
+

Playlists

+
    + +
- -
-

Playlists

-
    - -
diff --git a/scripts/index.new.js b/scripts/index.new.js index 294d0f8c..bd735a74 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -38,7 +38,10 @@ function checkDurationInput(duration){ // checks digits(maximum is 59:59/minim &&duration[2]===":"&&0<=parseInt(duration[3])&&parseInt(duration[3])<6&&0<=parseInt(duration[4]) &&parseInt(duration[4])<=9&&duration.length===5){ return true - }else throw 'Duration is not in the correct format...This is the format-"mm:ss" (for example 03:13)' + }else { + alert ('Duration is not in the correct format...This is the format-"mm:ss" (for example 03:13)') + throw 'Duration is not in the correct format...This is the format-"mm:ss" (for example 03:13)' + } } function playlistDuration(id) { @@ -155,6 +158,7 @@ function handleAddSongEvent(event) { // works-need to document.getElementById("artist").value=null; document.getElementById("duration").value=null; document.getElementById("cover-art").value=null; + toggleAddSection(); } /** @@ -241,3 +245,18 @@ document.getElementById("add-button").addEventListener("click", handleAddSongEve document.getElementById("songs").addEventListener("click" ,handleSongClickEvent ); +//making add section slide. +let inputs = document.getElementById('inputs'); +let cancelButton = document.getElementById('cancel-button'); +let addButton = document.getElementById('add-button'); +let content = document.getElementById('content-section'); +let titleElem = document.getElementById('add-sec-headline'); +titleElem.onclick = toggleAddSection; +cancelButton.onclick = toggleAddSection; + +function toggleAddSection() { + inputs.classList.toggle("open"); + addButton.classList.toggle("open"); + cancelButton.classList.toggle("open"); + content.classList.toggle("close"); +}; \ No newline at end of file diff --git a/style.css b/style.css index e1496c70..d3a55799 100644 --- a/style.css +++ b/style.css @@ -7,7 +7,8 @@ body{ font-size: 100%; background-image: url(./images/photo-1507838153414-b4b713384a76.jfif); background-repeat: no-repeat; - background-size: cover; + background-blend-mode:soft-light; + background-size:cover; background-color: #d4cfbf; margin: 0,0,0,0; } @@ -57,56 +58,72 @@ h2{ background: transparent 50%; overflow: hidden; align-self: center; - margin-left: 34%; - } - #inputs{ - display: flex; - flex-direction: column; - align-items:center; - justify-content : space-around; +} - } - input{ - width: 50%; - padding:5px; - margin: 5px; - border-radius:15px; - border:0; - box-shadow:4px 4px 10px rgba(0, 0, 0, 0.514); - height:50px; - background-color: transparent; - color: rgb(20, 2, 70); - +input{ + width: 50%; + padding:5px; + margin: 5px; + border-radius:15px; + border:0; + box-shadow:4px 4px 10px rgba(0, 0, 0, 0.514); + height:50px; + background-color:rgba(255, 228, 196, 0.493); + color: rgb(20, 2, 70); + } input:hover { background-color: #634d4d2f; border: 10px solid rgba(134, 129, 129, 0); - } +} + + ::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ - color: rgba(8, 0, 0, 0.418); + color: rgba(8, 0, 0, 0.562); font-weight: bold; - } - #add-button { +} +.add-section-buttons{ + padding:10px; + border:none; + background-color:#3f51b585; + color:#fff; + font-weight:600; + border-radius:5px; + width: 50%; + align-items:center; + margin-left: 25%; + margin-bottom: 2px; +} +.add-section-buttons:hover{ + background-color:#3f51b5; +} +#add-sec-headline{ + display: block; +} +.inputs{ + display: none; +} +.open{ + display: flex; + flex-direction: column; + align-items:center; + justify-content : space-around; +} +.close{ + display: none; +} - /* remove default behavior */ - appearance:none; - -webkit-appearance:none; - - /* usual styles */ - padding:10px; - border:none; - background-color:#3f51b585; - color:#fff; - font-weight:600; - border-radius:5px; - width: 50%; - - } - #add-button:hover{ - background-color:#3f51b5; +#add-sec-headline:hover{ + color: rgb(96, 240, 240); +} +#songs{ + display: flex; + flex-flow: row wrap; + align-items:center; - } - .now-playing{ - background-color: rgba(61, 199, 199, 0.315); + justify-content : space-around; +} +.now-playing{ + background-color: rgba(61, 199, 199, 0.315); } \ No newline at end of file From 40b0cab563c5c314524e8828b1880358b6c89e63 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Sat, 18 Sep 2021 20:54:01 +0300 Subject: [PATCH 23/31] Delete index.html --- index.html | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 index.html diff --git a/index.html b/index.html deleted file mode 100644 index c55fb482..00000000 --- a/index.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - Awesome MP3 Player - - - - - - -
- -
-
- -
- - From dc538ceaaf939fa9762fcb07b44e88c6d5c48ac3 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Sat, 18 Sep 2021 20:55:28 +0300 Subject: [PATCH 24/31] Delete index.js --- scripts/index.js | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 scripts/index.js diff --git a/scripts/index.js b/scripts/index.js deleted file mode 100644 index 6842c794..00000000 --- a/scripts/index.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Plays a song from the player. - * Playing a song means changing the visual indication of the currently playing song. - * - * @param {String} songId - the ID of the song to play - */ -function playSong(songId) { - // Your code here -} - -/** - * Creates a song DOM element based on a song object. - */ -function createSongElement({ id, title, album, artist, duration, coverArt }) { - const children = [] - const classes = [] - const attrs = { onclick: `playSong(${id})` } - return createElement("div", children, classes, attrs) -} - -/** - * Creates a playlist DOM element based on a playlist object. - */ -function createPlaylistElement({ id, name, songs }) { - const children = [] - const classes = [] - const attrs = {} - return createElement("div", children, classes, attrs) -} - -/** - * Creates a new DOM element. - * - * Example usage: - * createElement("div", ["just text", createElement(...)], ["nana", "banana"], {id: "bla"}) - * - * @param {String} tagName - the type of the element - * @param {Array} children - the child elements for the new element. - * Each child can be a DOM element, or a string (if you just want a text element). - * @param {Array} classes - the class list of the new element - * @param {Object} attributes - the attributes for the new element - */ -function createElement(tagName, children = [], classes = [], attributes = {}) { - // Your code here -} - -// You can write more code below this line From d9ef8977829cf0bddd442469fbc36a5d10b13942 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Sat, 18 Sep 2021 21:07:22 +0300 Subject: [PATCH 25/31] more styling --- index.new.html | 19 +------ scripts/index.new.js | 63 ++++++++++++------------ style.css | 115 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 135 insertions(+), 62 deletions(-) diff --git a/index.new.html b/index.new.html index db9e00a3..4c844af1 100644 --- a/index.new.html +++ b/index.new.html @@ -25,24 +25,7 @@

Add a new song

Songs

- -
+

Playlists

diff --git a/scripts/index.new.js b/scripts/index.new.js index bd735a74..dbb131ea 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -72,25 +72,24 @@ function sortByTitle(a, b) { } /** - * Plays a song from the player. - * Playing a song means changing the visual indication of the currently playing song. - * - * @param {Number} songId - the ID of the song to play - */ - let lastSongPlayed; - function playSong(songId) { - try{ - lastSongPlayed.classList.remove("now-playing"); - }finally{ - const songElement=document.getElementById(songId+"song") - const song=findSong(songId); - songElement.classList.add("now-playing"); - setTimeout(()=>songElement.classList.remove("now-playing"),song.duration*1000); - setTimeout(()=>playSong(player.songs[(player.songs.indexOf(song)+1)].id),song.duration*1000); - lastSongPlayed=songElement; - } - } - +* Plays a song from the player. +* Playing a song means changing the visual indication of the currently playing song. +* +* @param {Number} songId - the ID of the song to play +*/ +let lastSongPlayed; +function playSong(songId) { + try{ + lastSongPlayed.classList.remove("now-playing"); + }finally{ + const songElement=document.getElementById(songId+"song") + const song=findSong(songId); + songElement.classList.add("now-playing"); + setTimeout(()=>songElement.classList.remove("now-playing"),song.duration*1000); + setTimeout(()=>playSong(player.songs[(player.songs.indexOf(song)+1)].id),song.duration*1000); + lastSongPlayed=songElement; + } +} /** * Removes a song from the player, and updates the DOM to match. * @@ -108,8 +107,8 @@ function removeSong(songId) { /** * Adds a song to the player, and updates the DOM to match. - */ - function addSong({ title, album, artist, duration, coverArt }) { +*/ +function addSong({ title, album, artist, duration, coverArt }) { checkDurationInput(duration) newId=generateSongId(); player.songs.push({ @@ -133,12 +132,12 @@ function removeSong(songId) { * @param {MouseEvent} event - the click event */ function handleSongClickEvent(event) { // works-need to be written better - if (event.target.className != "remove-button"){ - if(event.target.className !="play-button")return; - } + // if (event.target.className != "remove-button"){ + // if(event.target.className !="play-button")return; + // } let song = event.target.closest(".song"); - if(event.target.className === "remove-button") removeSong(parseInt(song.id.substring(0,1))) - if(event.target.className ==="play-button") playSong(parseInt(song.id.substring(0,1))) + if(event.target.id === "deleteButton") removeSong(parseInt(song.id.substring(0,1))) + if(event.target.id ==="playButton") playSong(parseInt(song.id.substring(0,1))) } /** @@ -169,20 +168,22 @@ function createSongElement({ id, title, album, artist, duration, coverArt }) { const albumEl = createElement("span",[album],["album-name"]) const artistEl = createElement("span", [artist],["artist"]); const durationEl = createElement("span", ["" + secToDur(duration)] ,["duration", "short-duration"], {onclick: `console.log('${duration}')`}); - const playEl = createElement("button",["▶"],["play-button"],{id:"playButton"}); - const deleteEl = createElement("button",["❌"],["remove-button"],{id:"deleteButton"}); + const playEl = createElement("button",["▶"],["song-button","play-button"],{id:"playButton"}); + const deleteEl = createElement("button",["❌"],["song-button","remove-button"],{id:"deleteButton"}); + const buttonsOverly = createElement("p",[playEl,deleteEl],["overlay"]) const imgEl = createElement("img", [] ,["album-art"], {src: coverArt}); const textEl = createElement("div",[nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl],["text"]) - return createElement("div", [imgEl,playEl,deleteEl,textEl],["song"],{id:id+"song"}); + return createElement("div", [imgEl,buttonsOverly,textEl],["song"],{id:id+"song"}); } /** * Creates a playlist DOM element based on a playlist object. */ function createPlaylistElement({ id, name, songs }) { const nameEl=createElement("span", [name,":"],["playlist-name"]); - const quantityEl=createElement("span",[songs.length],["num-of-song"]) + const quantityEl=createElement("span",[songs.length,"songs"],["num-of-song"]) + const duration=createElement("span", [secToDur(playlistDuration(id))],["playlist-duration"]) const attrs = {id:id+"pl"} - return createElement("li", [nameEl,"Number Of Songs:",quantityEl,"Playlist Duration:",secToDur(playlistDuration(id))], ["playlist"],attrs) + return createElement("li", [nameEl,"\t",quantityEl,duration], ["playlist"],attrs) } /** diff --git a/style.css b/style.css index d3a55799..f26e5c9d 100644 --- a/style.css +++ b/style.css @@ -3,15 +3,18 @@ box-sizing: border-box; } body{ - text-align: center; - font-size: 100%; - background-image: url(./images/photo-1507838153414-b4b713384a76.jfif); - background-repeat: no-repeat; - background-blend-mode:soft-light; - background-size:cover; - background-color: #d4cfbf; - margin: 0,0,0,0; - } + display: flex; + flex-direction: column-reverse; + align-items: center; + text-align: center; + font-size: 100%; + background-image: url(./images/photo-1507838153414-b4b713384a76.jfif); + background-repeat: no-repeat; + background-blend-mode:soft-light; + background-size:cover; + background-color: #d4cfbf; + margin-top: 5vw; + } .album-art{ border-radius: 50%; @@ -20,7 +23,7 @@ body{ margin-right: auto; margin-bottom: 0; margin-top: 2%; - width: 50%; + width: 100%; border: 2px solid rgba(84, 87, 87, 0.329); padding: 2px; align-items: center; @@ -51,13 +54,14 @@ h2{ } .song{ position: relative; - width: 390px; + width: 300px; padding: 10px 40px; border: 1px transparent; border-radius: 15px; background: transparent 50%; overflow: hidden; align-self: center; + } input{ @@ -117,13 +121,98 @@ input:hover { #add-sec-headline:hover{ color: rgb(96, 240, 240); } + #songs{ + height: 280px; + width: 300px; + border:transparent; + overflow:auto; + position:relative; display: flex; flex-flow: row wrap; align-items:center; - justify-content : space-around; } + +.overlay { + position: absolute; + bottom: 100%; + left: 0; + right: 0; + background-color: #008bba00; + overflow: hidden; + width: 80%; + height: 10%; + transition: .5s ease; + border-radius: 50%; + display: block; + margin-left: auto; + margin-right: auto; + margin-bottom: 0; + display: flex; + justify-content: center; + align-items: center; +} + +.song:hover .overlay { + bottom: 0; + height: 100%; +} + +.song-button{ + overflow: hidden; + background-color: transparent; + border: none; + color: white; + padding: 70px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; +} + .now-playing{ background-color: rgba(61, 199, 199, 0.315); -} \ No newline at end of file + + +} + +::-webkit-scrollbar { + width: 12px; + height: 12px; + } + + ::-webkit-scrollbar-track { + border: transparent; + border-radius: 10px; + } + + ::-webkit-scrollbar-thumb { + background: transparent; + border-radius: 10px; + } + + ::-webkit-scrollbar-thumb:hover { + background:transparent; + } + + ul { + list-style-type: none; + margin: 0; + padding: 0; + } + + .playlist{ + background-color: rgba(245, 245, 220, 0.377); + margin: 2%; + padding: 1.5%; + width: 100%; + display: flex; + flex-direction: row; + justify-content:space-between; + border-radius: 10%; + border-width: 2px; + border-color: blue; + } + + \ No newline at end of file From ddc8156a065c942d314702df423b4431539f61c7 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Sat, 18 Sep 2021 22:42:47 +0300 Subject: [PATCH 26/31] added shuffle to playlists --- index.new.html | 1 + scripts/index.new.js | 54 +++++++++++++++++++++++++++++++++++--------- style.css | 40 +++++++++++++++++++++++++------- 3 files changed, 76 insertions(+), 19 deletions(-) diff --git a/index.new.html b/index.new.html index 4c844af1..799beca6 100644 --- a/index.new.html +++ b/index.new.html @@ -2,6 +2,7 @@ + Awesome MP3 Player diff --git a/scripts/index.new.js b/scripts/index.new.js index dbb131ea..4c23ca10 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -78,7 +78,7 @@ function sortByTitle(a, b) { * @param {Number} songId - the ID of the song to play */ let lastSongPlayed; -function playSong(songId) { +function playSong(songId,auto=true) { try{ lastSongPlayed.classList.remove("now-playing"); }finally{ @@ -86,7 +86,7 @@ function playSong(songId) { const song=findSong(songId); songElement.classList.add("now-playing"); setTimeout(()=>songElement.classList.remove("now-playing"),song.duration*1000); - setTimeout(()=>playSong(player.songs[(player.songs.indexOf(song)+1)].id),song.duration*1000); + if(auto) setTimeout(()=>playSong(player.songs[(player.songs.indexOf(song)+1)].id),song.duration*1000); lastSongPlayed=songElement; } } @@ -132,14 +132,16 @@ function addSong({ title, album, artist, duration, coverArt }) { * @param {MouseEvent} event - the click event */ function handleSongClickEvent(event) { // works-need to be written better - // if (event.target.className != "remove-button"){ - // if(event.target.className !="play-button")return; - // } let song = event.target.closest(".song"); if(event.target.id === "deleteButton") removeSong(parseInt(song.id.substring(0,1))) if(event.target.id ==="playButton") playSong(parseInt(song.id.substring(0,1))) } +function handlePlaylistClickEvent(event){ + if (event.target.className != "shuffle-button")return; + let playlist = event.target.closest(".playlist"); + if(event.target.id === "shuffle-button") shufflePlaylist(parseInt(playlist.id.substring(0,1))) +} /** * Handles a click event on the button that adds songs. * @@ -179,11 +181,19 @@ function createSongElement({ id, title, album, artist, duration, coverArt }) { * Creates a playlist DOM element based on a playlist object. */ function createPlaylistElement({ id, name, songs }) { - const nameEl=createElement("span", [name,":"],["playlist-name"]); - const quantityEl=createElement("span",[songs.length,"songs"],["num-of-song"]) - const duration=createElement("span", [secToDur(playlistDuration(id))],["playlist-duration"]) + const songsNamesArr = []; + function songsNames(id){ + songsNamesArr.push(findSong(id).title) + } + songs.forEach(songsNames) + const nameEl = createElement("span", [name,":"],["playlist-name"]); + const quantityEl = createElement("span",[songs.length,"songs"],["num-of-song"],{id:"num-of-songs"}) + const songsNameEl = createElement("span",[songsNamesArr],["hide"]) + const durationEl = createElement("span", [secToDur(playlistDuration(id))],["playlist-duration"]) + const shuffleEL = createElement("button",["🔀"],["shuffle-button"],{id:"shuffle-button"}); + const sideEl = createElement("span",[quantityEl,songsNameEl,durationEl,shuffleEL],["side-el"]) const attrs = {id:id+"pl"} - return createElement("li", [nameEl,"\t",quantityEl,duration], ["playlist"],attrs) + return createElement("li", [nameEl,sideEl], ["playlist"],attrs) } /** @@ -241,9 +251,10 @@ generateSongs(player) generatePlaylists(player) // Making the add-song-button actually do something document.getElementById("add-button").addEventListener("click", handleAddSongEvent) - //Making the play and delete buttons actually do something document.getElementById("songs").addEventListener("click" ,handleSongClickEvent ); +//Making shuffle button work +document.getElementById("playlists").addEventListener("click" ,handlePlaylistClickEvent ); //making add section slide. @@ -260,4 +271,25 @@ function toggleAddSection() { addButton.classList.toggle("open"); cancelButton.classList.toggle("open"); content.classList.toggle("close"); -}; \ No newline at end of file +}; + + +/**additions:**/ + +function shufflePlaylist(id){ + let shuffleArr=[]; + let indexArr=[]; + let randomIndex; + for(let i=0;i Date: Sat, 18 Sep 2021 23:18:20 +0300 Subject: [PATCH 27/31] now-playing section not finished!!! --- index.new.html | 3 +++ scripts/index.new.js | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/index.new.html b/index.new.html index 799beca6..d547db72 100644 --- a/index.new.html +++ b/index.new.html @@ -35,5 +35,8 @@

Playlists

+
+

NOW PLAYING:

+
diff --git a/scripts/index.new.js b/scripts/index.new.js index 4c23ca10..3f7fb5f7 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -81,6 +81,7 @@ let lastSongPlayed; function playSong(songId,auto=true) { try{ lastSongPlayed.classList.remove("now-playing"); + document.getElementById("playing-sec").remove(); }finally{ const songElement=document.getElementById(songId+"song") const song=findSong(songId); @@ -88,6 +89,7 @@ function playSong(songId,auto=true) { setTimeout(()=>songElement.classList.remove("now-playing"),song.duration*1000); if(auto) setTimeout(()=>playSong(player.songs[(player.songs.indexOf(song)+1)].id),song.duration*1000); lastSongPlayed=songElement; + document.getElementById("playing").append(createElement("span",[createSongElement(song)],[],{id:"playing-sec"})) } } /** @@ -229,20 +231,18 @@ function createElement(tagName, children = [], classes = [], attributes = {}, ev /** * Inserts all songs in the player as DOM elements into the songs list. */ -const songEl=document.getElementById("songs") function generateSongs(player) { for(song of player.songs.sort(sortByTitle)){ - songEl.append(createSongElement(song)); + document.getElementById("songs").append(createSongElement(song)); } } /** * Inserts all playlists in the player as DOM elements into the playlists list. */ -const playListEl=document.getElementById("playListList") function generatePlaylists(player) { for(playlist of player.playlists){ - playListEl.append(createPlaylistElement(playlist)); + document.getElementById("playListList").append(createPlaylistElement(playlist)); } } From 8dad08277f41edee8488266f52e6718b74c69b4e Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Sun, 19 Sep 2021 00:06:01 +0300 Subject: [PATCH 28/31] last improvment changed function name secToDur- --- index.new.html | 8 ++++---- scripts/index.new.js | 49 ++++++++++++++++++++++---------------------- style.css | 1 - 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/index.new.html b/index.new.html index d547db72..11efbe5f 100644 --- a/index.new.html +++ b/index.new.html @@ -26,17 +26,17 @@

Add a new song

Songs

- +

Playlists

    - +
-
-

NOW PLAYING:

+
+
diff --git a/scripts/index.new.js b/scripts/index.new.js index 3f7fb5f7..2049592d 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -1,4 +1,5 @@ -/*support functions */ +/*support functions: */ + function findSong(id,mPlayer=player){ for(let song of mPlayer.songs){ if (song.id===id){ @@ -23,7 +24,7 @@ function generateSongId(){ return newSongId; } -function secToDur(sec){ +function secondsToDuration(sec){ return((Math.floor(sec/60))<10? "0": "")+`${Math.floor(sec/60)}:` +((sec%60)<10? "0": "")+`${sec%60}` } @@ -33,7 +34,7 @@ function durationToSeconds(duration){ +parseInt(duration[3]*10)+parseInt(duration[4]) } -function checkDurationInput(duration){ // checks digits(maximum is 59:59/minimum is 00:00),:,length. +function checkDurationInput(duration){ // checks the duration format (digits(maximum is 59:59/minimum is 00:00),:,length) if(0<=parseInt(duration[0])&&parseInt(duration[0])<6&&0<=parseInt(duration[1])&&parseInt(duration[1])<=9 &&duration[2]===":"&&0<=parseInt(duration[3])&&parseInt(duration[3])<6&&0<=parseInt(duration[4]) &&parseInt(duration[4])<=9&&duration.length===5){ @@ -52,7 +53,7 @@ function playlistDuration(id) { return (plDuration); } -function updatePlaylist(){ +function updatePlaylist(){ // used to update playlist after deleting songs const list = document.getElementById("playListList"); while (list.hasChildNodes()) { list.removeChild(list.firstChild); @@ -89,8 +90,8 @@ function playSong(songId,auto=true) { setTimeout(()=>songElement.classList.remove("now-playing"),song.duration*1000); if(auto) setTimeout(()=>playSong(player.songs[(player.songs.indexOf(song)+1)].id),song.duration*1000); lastSongPlayed=songElement; - document.getElementById("playing").append(createElement("span",[createSongElement(song)],[],{id:"playing-sec"})) - } + document.getElementById("playing-section").append(createElement("h1",["NOW PLAYING:",createSongElement(song)],[],{id:"playing-sec"})) + } } /** * Removes a song from the player, and updates the DOM to match. @@ -114,17 +115,20 @@ function addSong({ title, album, artist, duration, coverArt }) { checkDurationInput(duration) newId=generateSongId(); player.songs.push({ - id: newId, - title: title, - album: album, - artist: artist, - duration: durationToSeconds(duration), - coverArt: coverArt + id: newId, + title: title, + album: album, + artist: artist, + duration: durationToSeconds(duration), + coverArt: coverArt }) - songEl.append(createSongElement(player.songs[player.songs.length-1])); + document.getElementById("songs").append(createSongElement(player.songs[player.songs.length-1])); + + /* + tried to make the song remain sorted by title: let placeAfterThisSong=player.songs.sort(sortByTitle)[(player.songs.indexOf(findSong(newId))-1)].id; (document.getElementById(newId+"song")).after(document.getElementById(placeAfterThisSong+"song")) - + */ } /** @@ -133,7 +137,7 @@ function addSong({ title, album, artist, duration, coverArt }) { * * @param {MouseEvent} event - the click event */ -function handleSongClickEvent(event) { // works-need to be written better +function handleSongClickEvent(event) { let song = event.target.closest(".song"); if(event.target.id === "deleteButton") removeSong(parseInt(song.id.substring(0,1))) if(event.target.id ==="playButton") playSong(parseInt(song.id.substring(0,1))) @@ -171,7 +175,7 @@ function createSongElement({ id, title, album, artist, duration, coverArt }) { const nameEl = createElement("span", [title],["song-name"]); const albumEl = createElement("span",[album],["album-name"]) const artistEl = createElement("span", [artist],["artist"]); - const durationEl = createElement("span", ["" + secToDur(duration)] ,["duration", "short-duration"], {onclick: `console.log('${duration}')`}); + const durationEl = createElement("span", ["" + secondsToDuration(duration)] ,["duration", "short-duration"], {onclick: `console.log('${duration}')`}); const playEl = createElement("button",["▶"],["song-button","play-button"],{id:"playButton"}); const deleteEl = createElement("button",["❌"],["song-button","remove-button"],{id:"deleteButton"}); const buttonsOverly = createElement("p",[playEl,deleteEl],["overlay"]) @@ -179,19 +183,17 @@ function createSongElement({ id, title, album, artist, duration, coverArt }) { const textEl = createElement("div",[nameEl,albumEl,"Artist: ", artistEl, "Duration: ", durationEl],["text"]) return createElement("div", [imgEl,buttonsOverly,textEl],["song"],{id:id+"song"}); } + /** * Creates a playlist DOM element based on a playlist object. */ function createPlaylistElement({ id, name, songs }) { const songsNamesArr = []; - function songsNames(id){ - songsNamesArr.push(findSong(id).title) - } - songs.forEach(songsNames) + songs.forEach((id)=>songsNamesArr.push(findSong(id).title)) const nameEl = createElement("span", [name,":"],["playlist-name"]); const quantityEl = createElement("span",[songs.length,"songs"],["num-of-song"],{id:"num-of-songs"}) const songsNameEl = createElement("span",[songsNamesArr],["hide"]) - const durationEl = createElement("span", [secToDur(playlistDuration(id))],["playlist-duration"]) + const durationEl = createElement("span", [secondsToDuration(playlistDuration(id))],["playlist-duration"]) const shuffleEL = createElement("button",["🔀"],["shuffle-button"],{id:"shuffle-button"}); const sideEl = createElement("span",[quantityEl,songsNameEl,durationEl,shuffleEL],["side-el"]) const attrs = {id:id+"pl"} @@ -253,11 +255,11 @@ generatePlaylists(player) document.getElementById("add-button").addEventListener("click", handleAddSongEvent) //Making the play and delete buttons actually do something document.getElementById("songs").addEventListener("click" ,handleSongClickEvent ); -//Making shuffle button work +//Making shuffle button actually do something document.getElementById("playlists").addEventListener("click" ,handlePlaylistClickEvent ); -//making add section slide. +//making add section slide. **Needs to be rewritten!!! let inputs = document.getElementById('inputs'); let cancelButton = document.getElementById('cancel-button'); let addButton = document.getElementById('add-button'); @@ -265,7 +267,6 @@ let content = document.getElementById('content-section'); let titleElem = document.getElementById('add-sec-headline'); titleElem.onclick = toggleAddSection; cancelButton.onclick = toggleAddSection; - function toggleAddSection() { inputs.classList.toggle("open"); addButton.classList.toggle("open"); diff --git a/style.css b/style.css index a0c0d306..835a7b3b 100644 --- a/style.css +++ b/style.css @@ -79,7 +79,6 @@ input{ } input:hover { background-color: #634d4d2f; - border: 10px solid rgba(134, 129, 129, 0); } From 6b4aa2f7e3c2ee338592d43c977d7e90fe1a6ef0 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Sun, 19 Sep 2021 00:45:43 +0300 Subject: [PATCH 29/31] orgenized css file --- style.css | 297 +++++++++++++++++++++++++----------------------------- 1 file changed, 139 insertions(+), 158 deletions(-) diff --git a/style.css b/style.css index 835a7b3b..4d61ee55 100644 --- a/style.css +++ b/style.css @@ -1,13 +1,9 @@ -/* *, *:before, *:after { - box-sizing: border-box; - } */ body{ - + text-align: center; display: flex; flex-direction: column-reverse; align-items: center; - text-align: center; font-size: 100%; background-image: url(./images/photo-1507838153414-b4b713384a76.jfif); background-repeat: no-repeat; @@ -15,112 +11,55 @@ body{ background-size:cover; background-color: #d4cfbf; margin-top: 5vw; - } - -.album-art{ - border-radius: 50%; - display: block; - margin-left: auto; - margin-right: auto; - margin-bottom: 0; - margin-top: 2%; - width: 100%; - border: 2px solid rgba(84, 87, 87, 0.329); - padding: 2px; - align-items: center; - size: 5px; -} - - -.short-duration{ - color: greenyellow; -} -.duration{ - color: indianred; } -span{ - margin-right: 0; -} -.text{ - -webkit-animation: moving 11s infinite; - animation: moving 11s infinite; -} -@keyframes moving { - from {transform: translateX(0%);} - to {transform: translateX(110%);} -} h2{ - display: none; + display: none; } +/* content section: */ + /* songs */ .song{ - position: relative; - width: 300px; - padding: 10px 40px; - border: 1px transparent; - border-radius: 15px; - background: transparent 50%; - overflow: hidden; - align-self: center; + position: relative; + width: 300px; + padding: 10px 40px; + overflow: hidden; + align-self: center; } -input{ - width: 150%; - padding:5px; - margin: 5px; - border-radius:15px; - border:0; - box-shadow:4px 4px 10px rgba(0, 0, 0, 0.514); - height:50px; - background-color:rgba(255, 228, 196, 0.493); - color: rgb(20, 2, 70); - -} -input:hover { - background-color: #634d4d2f; -} - - - -::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ - color: rgba(8, 0, 0, 0.562); - font-weight: bold; -} -.add-section-buttons{ - padding:10px; - border:none; - background-color:#3f51b585; - color:#fff; - font-weight:600; - border-radius:5px; - width: 50%; - align-items:center; - margin-left: 25%; - margin-bottom: 2px; -} -.add-section-buttons:hover{ - background-color:#3f51b5; -} -#add-sec-headline{ +.album-art{ + border-radius: 50%; display: block; + margin-left: auto; + margin-right: auto; + margin-bottom: 0; + margin-top: 2%; + width: 100%; + border: 2px solid rgba(84, 87, 87, 0.329); + padding: 2px; + align-items: center; + size: 5px; } -.inputs{ - display: none; + +.duration{ + color: rgb(88, 2, 2); } -.open{ + +.text{ + width:150% ; + height: 5%; display: flex; - flex-direction: column; - align-items:center; - justify-content : space-around; + flex-direction: row; + flex-wrap: nowrap; + white-space: nowrap; + justify-content: space-evenly; + animation: moving 4s infinite; } -.close{ - display: none; +@keyframes moving { + from {transform: translateX(-110%);} + to {transform: translateX(100%);} } -#add-sec-headline:hover{ - color: rgb(96, 240, 240); -} #songs{ height: 280px; @@ -171,71 +110,113 @@ input:hover { font-size: 16px; } +::-webkit-scrollbar { + width: 0px; + height: 0px; +} +.now-playing{ + background-color: rgba(61, 199, 199, 0.315); +} +/* /* playlists */ +ul { + list-style-type: none; + margin: 0; + padding: 0; +} +.playlist{ + background-color: rgba(245, 245, 220, 0.377); + margin: 2%; + padding: 1.5%; + width: 100%; + display: flex; + flex-direction: row; + justify-content:space-between; + border-radius: 10%; + border-width: 2px; + border-color: blue; +} +.side-el{ + width: 50%; + display: flex; + flex-direction: row; + justify-content: space-between; +} +.shuffle-button{ + opacity: 50%; + background-color: transparent; + border-color: transparent; +} -::-webkit-scrollbar { - width: 12px; - height: 12px; - } - - ::-webkit-scrollbar-track { - border: transparent; - border-radius: 10px; - } - - ::-webkit-scrollbar-thumb { - background: transparent; - border-radius: 10px; - } - - ::-webkit-scrollbar-thumb:hover { - background:transparent; - } - - ul { - list-style-type: none; - margin: 0; - padding: 0; - } - - .playlist{ - background-color: rgba(245, 245, 220, 0.377); - margin: 2%; - padding: 1.5%; - width: 100%; - display: flex; - flex-direction: row; - justify-content:space-between; - border-radius: 10%; - border-width: 2px; - border-color: blue; - } - - .side-el{ - width: 50%; - display: flex; - flex-direction: row; - justify-content: space-between; - } - - .shuffle-button{ - opacity: 50%; - background-color: transparent; - border-color: transparent; - } - +.hide { + display: none; +} - .hide { - display: none; - } +.num-of-song:hover + .hide { + display: block; + color: rgba(6, 27, 117, 0.336); +} - .num-of-song:hover + .hide { - display: block; - color: rgba(6, 27, 117, 0.336); - } +/* add section-display */ +.inputs{ + display: none; +} +.open{ + display: flex; + flex-direction: column; + align-items:center; + justify-content : space-around; +} +.close{ + display: none; +} - .now-playing{ - background-color: rgba(61, 199, 199, 0.315); - +#add-sec-headline:hover{ + color: rgb(96, 240, 240); +} + +input{ + width: 150%; + padding:5px; + margin: 5px; + border-radius:15px; + border:0; + box-shadow:4px 4px 10px rgba(0, 0, 0, 0.514); + height:50px; + background-color:rgba(255, 228, 196, 0.493); + color: rgb(20, 2, 70); - } \ No newline at end of file +} +input:hover { + background-color: #634d4d2f; +} + +::placeholder { + color: rgba(8, 0, 0, 0.562); + font-weight: bold; +} + +.add-section-buttons{ + padding:10px; + border:none; + background-color:#3f51b585; + color:#fff; + font-weight:600; + border-radius:5px; + width: 50%; + align-items:center; + margin-left: 25%; + margin-bottom: 2px; +} + +.add-section-buttons:hover{ + background-color:#3f51b5; +} + +#add-sec-headline{ + display: block; +} + + + + From 6b8bbb234471cd76e043fbe2ad15809f88a7677b Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Sun, 19 Sep 2021 01:25:45 +0300 Subject: [PATCH 30/31] Update README.md --- README.md | 93 +++++++++++++++++-------------------------------------- 1 file changed, 28 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 3ed9a821..77c290c3 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,45 @@ -# MP3 DOM +# MP3 Player : +this project suppose to demonstrate simple MP3 Player. -The users of your MP3 player complained about it being inconvenient for regular (non-programmer) people. Time to build a GUI! +![](https://user-images.githubusercontent.com/89573774/132813316-8c310d9f-ef3a-4223-bf49-b59422ba651a.png) -Your task is to create a webpage that conveniently displays the songs and playlists in a player object. The player object will have the same structure as in your previous assignment. +## Basic functions you should know about: -## General Instructions + `playSong` - + + + + `removeSong` - + + -1. Fork this repo into your account. -2. Clone the forked repo to your computer. -3. Create a new git branch for your work. -4. Complete the requirements. -5. Submit your work. -6. May the odds be ever in your favor! + `addSong` - + + + -## New Requirements! -- There is now a section for adding new songs to the player. Make it work! -- Add a play button to every song. Clicking it will play that song. -- Add a remove button to every song. Clicking it will remove the song from the playlist. -- There should be only one event listener on the entire songs list, that handles all play and remove events of songs. -- You are given new template files to use: `index.new.html` and `index.new.js`. +__Note__: The functions are not yet merge to the main branch. -## Webpage Requirements -Your webpage should contain 2 lists: +## Additions +- `shufflePlaylist` -play any playlist in random order. -- A list of the `songs` in the player, sorted by their titles -- A list of the `playlists` in the player, sorted by their names +![image](https://user-images.githubusercontent.com/89573774/133909960-10fe97b3-3ac2-4883-a1e2-1a8b4300a58f.png) -### Songs -Each song list item shall display the following details: -- song `title` -- `album` name -- `artist` name -- an image with the album's cover art (`coverArt`) -- song `duration` (in `mm:ss` format, of course) +__Note__: The functions are not yet merge to the main branch. -One song can be played at a time. There should be some indication of the currently playing song (the specific indication is up to you). Clicking on a song will change the indication of the currently playing song. We have already provided code that handles the click event for you. +## bugs /errors +![image](https://user-images.githubusercontent.com/89573774/133910054-30355550-ca5b-4615-831c-f19f64375a32.png) -### Playlists + in the now playing section you can see the song currently playing. + the problem is that it has the sme id as the song elemet itself. + and also you see there the buttons but they don't work + + - there is no option to pause a song. -Every playlist list item should display the following information: -- playlist `name` -- the number of songs in the playlist -- the total duration of the playlist -## Bonus Requirements +### If you have anything to add or comment I would love it. -- After a song begins to play, it automatically switches to the next one when the song duration has passed. -- The color of the durations of songs should reflect their length. A duration of less than 2 min will show green, and will be gradually redder until it is completely red for durations that are above 7 min. -- When a song is removed, all playlists in the page will also be updated. -- When adding a new song, the songs list will remain sorted by title. -- Anything else you can think of... - -## Technical Instructions - -You are provided with a template for your project: - -- an HTML file (`index.html`) -- a linked, empty CSS file (`style.css`) -- a linked JS script with a sample `player` object (`player.js`) -- a linked JS script with a template for your code (`index.js`) -- an `images` folder with the webpage icon and song cover art - -The HTML defines the basic structure of the page. There are 2 container elements - one for the songs and one for the playlists. You may add more structural elements to the HTML (headings etc.), but the songs and playlists themselves must be generated using JS, based on the `player` object. - -## Submission - -1. On GitHub, open a pull request from your branch to the main branch. -2. **Do not merge the pull request!** -3. Add the user `Cyber4sPopo` as collaborator to your repo. -4. Submit a link to the pull request in Google Classroom. - -## Additional Remarks - -- **Avoid duplication!** Use JS functions and CSS classes wisely. -- Maintain high coding standards. Keep your code readable, indented properly, commented and indicative. -- Maintain a proper git workflow. Commit often, push often, write informative commit messages. -- You are free to style your webpage however you like. Make it BEAUTIFUL! From f5315847759bb8d8a3df817b1190319d0bc2d737 Mon Sep 17 00:00:00 2001 From: tsoriLache <89573774+tsoriLache@users.noreply.github.com> Date: Wed, 22 Sep 2021 09:13:18 +0300 Subject: [PATCH 31/31] Rename index.new.html to index.html --- index.new.html => index.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename index.new.html => index.html (100%) diff --git a/index.new.html b/index.html similarity index 100% rename from index.new.html rename to index.html