Skip to content

Instantly share code, notes, and snippets.

@sylphdesign
Created October 12, 2015 23:36
Show Gist options
  • Save sylphdesign/27637f8e9b7abfc5931d to your computer and use it in GitHub Desktop.
Save sylphdesign/27637f8e9b7abfc5931d to your computer and use it in GitHub Desktop.
Editor context menu
#player
ul#controls
li#previous: .fa.fa-bold(onclick="player.previous()")
li#stop: .fa.fa-italic(onclick="player.stop()")
li#play: .fa.fa-play(onclick="player.play()")
li#text: .fa.fa-align-center(onclick="")
li#next: .fa.fa-link(onclick="player.next()")
class Song {
constructor(title, artist, duration, image) {
this.title = title
this.artist = artist
this.duration = duration
this.imageUrl = image
this.isPlaying = false
}
play() {
this.isPlaying = true
}
stop() {
this.isPlaying = false
}
toHTML(block, index) {
// block as in BEM for `header` and `song`
return `
<ul class="${block} ${this.isPlaying ? 'active' : ''}" onclick="player.select(${index})">
<li class="${block}__image"><img src="${this.imageUrl}" alt="${this.title} ${this.artist}"></li>
<li class="${block}__title">${this.title}</li>
<li class="${block}__artist">${this.artist}</li>
<li class="${block}__duration">${this.duration}</li>
${ (block === 'song') ? `<li class="${block}__isplaying"><i class="fa fa-volume-${this.isPlaying ? 'up' : 'off'}"></i></li>` : '' }
</ul>`
}
}
class Player {
constructor() {
this.songs = []
this.nowPlayingIndex = 0
this.$header = $('#header')
this.$playlist = $('#playlist')
this.$stop = $('#stop')
this.$play = $('#play')
}
add(songs) {
songs.forEach(song => {
this.songs.push(song)
})
}
render() {
this.renderPlaylist()
this.renderHeader()
}
play() {
this.songs[this.nowPlayingIndex].play()
this.$play.hide()
this.$stop.show()
this.render()
}
stop() {
this.songs[this.nowPlayingIndex].stop()
this.$stop.hide()
this.$play.show()
this.render()
}
next() {
this.stop()
this.nowPlayingIndex++
if(this.nowPlayingIndex === this.songs.length) {
this.nowPlayingIndex = 0
}
this.play()
}
previous() {
this.stop()
this.nowPlayingIndex--
if(this.nowPlayingIndex < 0) {
this.nowPlayingIndex = (this.songs.length - 1)
}
this.play()
}
select(index) {
this.stop()
this.nowPlayingIndex = index
this.play()
}
renderPlaylist() {
this.$playlist.html('')
this.songs.forEach( (song, index)=> {
this.$playlist.append(song.toHTML('song', index))
})
}
renderHeader() {
this.$header.html('')
this.$header.html(this.songs[this.nowPlayingIndex].toHTML('header'))
}
render() {
this.renderPlaylist()
this.renderHeader()
}
}
let player = new Player
// Song list
player.add([
new Song('Counting Starts',
'OneRepublic', '4:17',
'https://upload.wikimedia.org/wikipedia/en/3/37/OneRepublic_Counting_Stars_cover.png'),
new Song('Do it',
'Tuxedo',
'4:19',
'http://static.djbooth.net/pics-artist/tuxedo.jpg'),
new Song('Paradise',
'Coldplay',
'4:38',
'http://popcrush.com/files/2011/09/coldplay-paradise.jpg')
])
player.play()
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
// Utilities
// px to ems
@function em($u) {
@return ($u/16)+em;
}
// color maps
@function color($shades, $shade: 'base') {
@return map-get(map-get($color, $shades), $shade);
}
//config
$font-primary: 'Nunito', sans-serif;
$font-icons: FontAwesome;
$color-primary: #607D8B;
$color: (
white: (
x-light : transparentize(white, 0.7),
light : transparentize(white, 0.5),
base : white,
),
primary: (
light : transparentize($color-primary, 0.75),
base : $color-primary,
dark : darken($color-primary, 20%),
)
);
// Extends
%center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
// GLOBAL
img {
max-width: 100%;
max-height: 100%;
}
ul, ol {
list-style: none;
margin: 0;
padding: 0;
}
// PLAYER
#player {
width: em(250);
margin: auto;
}
#controls {
display: flex;
justify-content: center;
color: color(primary, light);
background: color(white);
border-radius: em(25);
user-select: none;
> li {
font-size: 1.5em;
padding: em(8);
cursor: pointer;
&:hover {
color: color(primary);
}
&:active {
color: color(primary, dark);
}
}
#play {
display: none;
}
}
@keyframes volumePlaying {
50% { opacity: 1; }
}
.fa {
&-volume-off {
opacity: 0.5;
}
&-volume-up {
opacity: 0.5;
animation: volumePlaying 2s infinite;
}
}
// DEMO STYLES
body {
font: 100% $font-primary;
font-weight: 100;
color: white;
background-color: color(primary);
}
#player {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
// codepen viewbox zoom
@media screen and (max-height: 420px){
body {
font-size: 75%
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment