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! diff --git a/images/photo-1507838153414-b4b713384a76.jfif b/images/photo-1507838153414-b4b713384a76.jfif new file mode 100644 index 00000000..0dc4e666 Binary files /dev/null and b/images/photo-1507838153414-b4b713384a76.jfif differ diff --git a/index.html b/index.html index c55fb482..11efbe5f 100644 --- a/index.html +++ b/index.html @@ -2,18 +2,41 @@ + Awesome MP3 Player - + -
- +

Awesome Player!!!

+
+

Add a new song

+
+ + + + + +
+ +
-
- +
+
+

Songs

+ +
+
+

Playlists

+
    + +
+
+
+
+
diff --git a/index.new.html b/index.new.html deleted file mode 100644 index eba39f17..00000000 --- a/index.new.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - Awesome MP3 Player - - - - - - -

Awesome Player!!!

-
-

Add a new song

-
- - - - - -
- -
-
-

Songs

-
- -
-
-
-

Playlists

-
- -
-
- - 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 diff --git a/scripts/index.new.js b/scripts/index.new.js index c3a39c8e..2049592d 100644 --- a/scripts/index.new.js +++ b/scripts/index.new.js @@ -1,27 +1,134 @@ -/** - * 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 - */ -function playSong(songId) { - // Your code here +/*support functions: */ + +function findSong(id,mPlayer=player){ + for(let song of mPlayer.songs){ + if (song.id===id){ + return song; + } + } + 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"; +} + +let newSongId=10; +function generateSongId(){ + newSongId+=1; + return newSongId; +} + +function secondsToDuration(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 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){ + return true + }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) { + let plDuration=0; + for(let songID of findPlaylist(id).songs){ + plDuration+=(findSong(songID).duration); + } + return (plDuration); +} + +function updatePlaylist(){ // used to update playlist after deleting songs + const list = document.getElementById("playListList"); + while (list.hasChildNodes()) { + list.removeChild(list.firstChild); + } + 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. +* +* @param {Number} songId - the ID of the song to play +*/ +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); + songElement.classList.add("now-playing"); + 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-section").append(createElement("h1",["NOW PLAYING:",createSongElement(song)],[],{id:"playing-sec"})) + } +} /** * Removes a song from the player, and updates the DOM to match. * * @param {Number} songId - the ID of the song to remove */ function removeSong(songId) { - // Your code here + console.log(player.songs.splice(player.songs.indexOf(findSong(songId)),1)); + for(let playlist of player.playlists){ + const songIndex=playlist.songs.indexOf(songId); + songIndex>=0? playlist.songs.splice(songIndex,1) :songId; + } + document.getElementById(songId+"song").remove(); + updatePlaylist(); } /** * Adds a song to the player, and updates the DOM to match. - */ +*/ function addSong({ title, album, artist, duration, coverArt }) { - // Your code here + checkDurationInput(duration) + newId=generateSongId(); + player.songs.push({ + id: newId, + title: title, + album: album, + artist: artist, + duration: durationToSeconds(duration), + coverArt: coverArt + }) + 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")) + */ } /** @@ -30,39 +137,67 @@ function addSong({ title, album, artist, duration, coverArt }) { * * @param {MouseEvent} event - the click event */ -function handleSongClickEvent(event) { - // Your code here +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))) } +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. * * @param {MouseEvent} event - the click event */ -function handleAddSongEvent(event) { - // Your code here +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; + toggleAddSection(); } /** * 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", ["" + 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"]) + const imgEl = createElement("img", [] ,["album-art"], {src: 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 children = [] - const classes = [] - const attrs = {} - const eventListeners = {} - return createElement("div", children, classes, attrs, eventListeners) + const songsNamesArr = []; + 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", [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"} + return createElement("li", [nameEl,sideEl], ["playlist"],attrs) } /** @@ -79,26 +214,83 @@ 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; } /** * Inserts all songs in the player as DOM elements into the songs list. */ -function generateSongs() { - // Your code here +function generateSongs(player) { + for(song of player.songs.sort(sortByTitle)){ + document.getElementById("songs").append(createSongElement(song)); + } } /** * Inserts all playlists in the player as DOM elements into the playlists list. */ -function generatePlaylists() { - // Your code here +function generatePlaylists(player) { + for(playlist of player.playlists){ + document.getElementById("playListList").append(createPlaylistElement(playlist)); + } } // 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) +//Making the play and delete buttons actually do something +document.getElementById("songs").addEventListener("click" ,handleSongClickEvent ); +//Making shuffle button actually do something +document.getElementById("playlists").addEventListener("click" ,handlePlaylistClickEvent ); + + +//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'); +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"); +}; + + +/**additions:**/ + +function shufflePlaylist(id){ + let shuffleArr=[]; + let indexArr=[]; + let randomIndex; + for(let i=0;i