diff --git a/README.md b/README.md deleted file mode 100644 index 2464d38..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# assignment_royalty_free_music_player -Ushering in the reign of Royalty Free Music w/ JavaScript. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..efbc795 --- /dev/null +++ b/README.txt @@ -0,0 +1,3 @@ +A Pen created at CodePen.io. You can find this one at https://codepen.io/bpgallagher/pen/qKgqxa. + + \ No newline at end of file diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..941cc64 --- /dev/null +++ b/css/style.css @@ -0,0 +1,173 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +html, body { + font-family: "Open Sans"; + height: 100%; } + +.page-header { + background-color: #E8E8E8; + padding: 10px; + border-bottom: 1px solid black; + border-radius: 2px; } + .page-header h1 { + margin: 0; + font-size: 36px; + font-weight: bold; + line-height: 1.5em; + color: #444; } + .page-header h1 .glyphicon { + padding: 10px; } + +#playlist li .glyphicon { + font-size: 2.5em; + color: #aaa; + line-height: 1.5em; + cursor: pointer; } + +.song { + display: inline-block; } + .song .song-title { + margin-top: 0; + margin-bottom: 5px; + font-size: 24px; } + .song .song-artist { + margin-top: 0; + color: #aaa; + font-size: 14px; } + +.ctrls { + background-color: #2C2C2C; + color: white; + padding-top: 20px; + padding-bottom: 20px; + border-radius: 2px; } + .ctrls .glyphicon { + font-size: 2.5em; + padding-left: 10px; + cursor: pointer; } + .ctrls .song { + padding-left: 20px; } + +/*# sourceMappingURL=styles.css.map */ +html, body { + font-family: "Open Sans"; + height: 100%; +} +.page-header { + background-color: #E8E8E8; + padding: 10px; + border-bottom: 1px solid black; + border-radius: 2px; + + h1 { + margin: 0; + font-size: 36px; + font-weight: bold; + line-height: 1.5em; + color: #444; + + .glyphicon { + padding: 10px; + } + } +} + +#playlist { + li { + + .glyphicon { + font-size: 2.5em; + color: #aaa; + line-height: 1.5em; + cursor: pointer; + } + + } +} + +.song { + display: inline-block; + + .song-title { + margin-top: 0; + margin-bottom: 5px; + font-size: 24px; + } + + .song-artist { + margin-top: 0; + color: #aaa; + font-size: 14px; + } +} + +.ctrls { + background-color: #2C2C2C; + color: white; + padding-top: 20px; + padding-bottom: 20px; + border-radius: 2px; + + .glyphicon { + font-size: 2.5em; + padding-left: 10px; + cursor: pointer; + } + + .song { + padding-left: 20px; + } +} + { + "version": 3, + "mappings": "AAAA,UAAW;EACT,WAAW,EAAE,WAAW;EACxB,MAAM,EAAE,IAAI;;AAEd,YAAa;EACX,gBAAgB,EAAE,OAAO;EACzB,OAAO,EAAE,IAAI;EACb,aAAa,EAAE,eAAe;EAC9B,aAAa,EAAE,GAAG;EAElB,eAAG;IACD,MAAM,EAAE,CAAC;IACT,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,KAAK;IAClB,KAAK,EAAE,IAAI;IAEX,0BAAW;MACT,OAAO,EAAE,IAAI;;AAQf,uBAAW;EACT,SAAS,EAAE,KAAK;EAChB,KAAK,EAAE,IAAI;EACX,WAAW,EAAE,KAAK;EAClB,MAAM,EAAE,OAAO;;AAMrB,KAAM;EACJ,OAAO,EAAE,YAAY;EAErB,iBAAY;IACV,UAAU,EAAE,CAAC;IACb,aAAa,EAAE,GAAG;IAClB,SAAS,EAAE,IAAI;EAGjB,kBAAa;IACX,UAAU,EAAE,CAAC;IACb,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;;AAInB,MAAO;EACL,gBAAgB,EAAE,OAAO;EACzB,KAAK,EAAE,KAAK;EACZ,WAAW,EAAE,IAAI;EACjB,cAAc,EAAE,IAAI;EACpB,aAAa,EAAE,GAAG;EAElB,iBAAW;IACT,SAAS,EAAE,KAAK;IAChB,YAAY,EAAE,IAAI;IAClB,MAAM,EAAE,OAAO;EAGjB,YAAM;IACJ,YAAY,EAAE,IAAI", + "sources": ["styles.scss"], + "names": [], + "file": "styles.css" + } diff --git a/index.html b/index.html new file mode 100644 index 0000000..5e8e653 --- /dev/null +++ b/index.html @@ -0,0 +1,72 @@ + + + + + + Viking Royalty Free Music Player + + + + + + + + + + + + + + + + + + + + + + + + Royalty Free Music Player + + + + +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + diff --git a/js/index.js b/js/index.js new file mode 100644 index 0000000..5195057 --- /dev/null +++ b/js/index.js @@ -0,0 +1,347 @@ +// do this when you have multiple files! +var RFMP = RFMP || {}; + +RFMP.songs = [ + { + title: "Requiem for a Fish", + artist: "The Freak Fandango Orchestra", + url: "music/The_Freak_Fandango_Orchestra_-_01_-_Requiem_for_a_Fish.mp3" + }, + { + title: "Russian Beach (Heycaluca)", + artist: "Party People in a Can", + url: "music/Party_People_in_a_Can_-_05_-_Russian_Beach_Heycaluca.mp3" + }, + { + title: "Pueblo Duerme", + artist: "La Barca de Sua", + url: "music/La_Barca_de_Sua_-_05_-_Pueblo_Duerme.mp3" + }, + { + title: "Ragtime Dance", + artist: "Scott Joplin", + url: "music/Scott_Joplin_-_Ragtime_Dance.mp3" + }, + { + title: "Ghost Dance", + artist: "Kevin MacLeod", + url: "music/Kevin_MacLeod_-_Ghost_Dance.mp3" + } +]; +// do this when you have multiple files! +var RFMP = RFMP || {}; + +// the view is for talking to the HTML and the user +RFMP.view = { + + init: function(listeners) { + // adds song HTML to playlist + RFMP.view.addSongs(); + + // pass handler methods from our player + // to add to the DOM + RFMP.view.addListeners(listeners); + + // update the info text for the currently + // playing track + RFMP.view.updateSongInfo(); + }, + + // changes the controls center button to play or pause + updateControls: function() { + if (RFMP.currentState.playing) { + $('#ctrl-play').addClass('glyphicon-pause') + .removeClass('glyphicon-play'); + } else { + $('#ctrl-play').removeClass('glyphicon-pause') + .addClass('glyphicon-play'); + } + }, + + // Changes the text in the control panel + // to reflect the song name and artist + // of the current song + updateSongInfo: function() { + // get the info of the current song + var currentSong = RFMP.songs[RFMP.currentState.song]; + + $('#song-info .song-title').text(currentSong.title); + $('#song-info .song-artist').text(currentSong.artist); + }, + + // this takes in a `$song` jQuery + // element that references the play/pause + // button and returns the index ID + getId: function($song) { + // `+` is a quick way to convert a string + // to a number + return +$song.data('index'); + }, + + // this takes in a `$song` jQuery + // element that references the play/pause + // button and returns the audio element associated + // with it + getAudio: function($song) { + return $song.next(); + }, + + // this return finds the play/pause button + // of the song associated with the `id` + // we passed into the argument + getSongFromId: function(id) { + // the selector looks for a span element + // with a particular `data-index`. + // This data-index corresponds + // to our `songs` array. + // Make sure there's no space between + // span and [] + return $('span[data-index=' + id + ']'); + }, + + // calls the above method with the id + // of the current song + getCurrentSong: function() { + var id = RFMP.currentState.song; + + return RFMP.view.getSongFromId(id); + }, + + // changes the song's button to a "play" icon + changeToPlay: function($song) { + $song.removeClass('glyphicon-pause') + .addClass('glyphicon-play'); + }, + + // changes the song's button to a "pause" icon + changeToPause: function($song) { + $song.addClass('glyphicon-pause') + .removeClass('glyphicon-play'); + }, + + // adds listeners to the elements we need + addListeners: function(listeners) { + // Note: we are simply passing our methods as + // handlers rather than writing anonymouse functions + var $playlist = $('#playlist'), + $ctrlPlay = $('#ctrl-play'), + $ctrlNext = $('#ctrl-next'), + $ctrlPrev = $('#ctrl-prev'); + + // this is event delegation. It adds a `click` + // listener to all the elements with a + // `play-pause` class inside our playlist, + // i.e. all our play/pause buttons. + $playlist.on("click", ".play-pause", listeners.playPause); + + $ctrlPlay.on("click", listeners.playPause); + $ctrlNext.on("click", listeners.nextTrack); + $ctrlPrev.on("click", listeners.prevTrack); + }, + + // creates a song HTML element for each song + // in our `songs` array. Now it's easy to modify + // our song list without touching the HTML. + addSongs: function() { + RFMP.songs.forEach(function(song, index) { + // this creates the element + var $playlistItem = RFMP.view.createSongItem(song, index); + + // and now we add it to the bottom of our playlist + $('#playlist').append($playlistItem); + }); + }, + + // this dynamically creates a list item + // of all the necessary elements + // for a single song and returns it + createSongItem: function(song, index) { + var $li = $('
  • ') + .addClass('col-xs-8 col-xs-offset-2 list-group-item'); + + var $textCol = $('
    ') + .addClass("col-xs-1") + .appendTo($li); + + var $button = $('') + .addClass("glyphicon glyphicon-play play-pause") + .attr("aria-hidden", "true") + // this adds a `data` property that + // refers to the index in the + // `songs` array + .attr("data-index", index) + .appendTo($textCol); + + var $audio = $('