Close menu with clickaway

This commit is contained in:
An Phan 2016-02-19 15:20:34 +08:00
parent eafa856b02
commit 640d8fc8dc
8 changed files with 64 additions and 61 deletions

View file

@ -39,6 +39,7 @@
"rangeslider.js": "^2.1.1", "rangeslider.js": "^2.1.1",
"sinon": "^1.17.2", "sinon": "^1.17.2",
"vue": "^1.0.16", "vue": "^1.0.16",
"vue-clickaway": "^1.1.1",
"vue-hot-reload-api": "^1.2.2", "vue-hot-reload-api": "^1.2.2",
"vue-resource": "~0.5.1", "vue-resource": "~0.5.1",
"vueify": "^7.0.2", "vueify": "^7.0.2",

View file

@ -4,18 +4,18 @@
<span class="overview"> <span class="overview">
<img :src="album.cover" width="64" height="64" class="cover"> <img :src="album.cover" width="64" height="64" class="cover">
{{ album.name }} {{ album.name }}
<i class="fa fa-angle-down toggler" <i class="fa fa-angle-down toggler"
v-show="isPhone && !showingControls" v-show="isPhone && !showingControls"
@click="showingControls = true"></i> @click="showingControls = true"></i>
<i class="fa fa-angle-up toggler" <i class="fa fa-angle-up toggler"
v-show="isPhone && showingControls" v-show="isPhone && showingControls"
@click.prevent="showingControls = false"></i> @click.prevent="showingControls = false"></i>
<span class="meta" v-show="meta.songCount"> <span class="meta" v-show="meta.songCount">
by <a class="artist" @click.prevent="viewArtistDetails">{{ album.artist.name }}</a> by <a class="artist" @click.prevent="viewArtistDetails">{{ album.artist.name }}</a>
{{ meta.songCount }} {{ meta.songCount | pluralize 'song' }} {{ meta.songCount }} {{ meta.songCount | pluralize 'song' }}
{{ meta.totalLength }} {{ meta.totalLength }}
</span> </span>
</span> </span>
@ -27,7 +27,7 @@
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1"> <button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected <i class="fa fa-random"></i> Selected
</button> </button>
<button class="add-to" @click.prevent="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length"> <button class="add-to" @click.prevent.stop="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length">
{{ showingAddToMenu ? 'Cancel' : 'Add To…' }} {{ showingAddToMenu ? 'Cancel' : 'Add To…' }}
</button> </button>

View file

@ -4,18 +4,18 @@
<span class="overview"> <span class="overview">
<img :src="artist.image" width="64" height="64" class="cover"> <img :src="artist.image" width="64" height="64" class="cover">
{{ artist.name }} {{ artist.name }}
<i class="fa fa-angle-down toggler" <i class="fa fa-angle-down toggler"
v-show="isPhone && !showingControls" v-show="isPhone && !showingControls"
@click="showingControls = true"></i> @click="showingControls = true"></i>
<i class="fa fa-angle-up toggler" <i class="fa fa-angle-up toggler"
v-show="isPhone && showingControls" v-show="isPhone && showingControls"
@click.prevent="showingControls = false"></i> @click.prevent="showingControls = false"></i>
<span class="meta" v-show="meta.songCount"> <span class="meta" v-show="meta.songCount">
{{ artist.albums.length }} {{ artist.albums.length | pluralize 'album' }} {{ artist.albums.length }} {{ artist.albums.length | pluralize 'album' }}
{{ meta.songCount }} {{ meta.songCount | pluralize 'song' }} {{ meta.songCount }} {{ meta.songCount | pluralize 'song' }}
{{ meta.totalLength }} {{ meta.totalLength }}
</span> </span>
</span> </span>
@ -27,7 +27,7 @@
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1"> <button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected <i class="fa fa-random"></i> Selected
</button> </button>
<button class="add-to" @click.prevent="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length"> <button class="add-to" @click.prevent.stop="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length">
{{ showingAddToMenu ? 'Cancel' : 'Add To…' }} {{ showingAddToMenu ? 'Cancel' : 'Add To…' }}
</button> </button>

View file

@ -2,22 +2,22 @@
<section id="favoritesWrapper"> <section id="favoritesWrapper">
<h1 class="heading"> <h1 class="heading">
<span>Songs You Love <span>Songs You Love
<i class="fa fa-angle-down toggler" <i class="fa fa-angle-down toggler"
v-show="isPhone && !showingControls" v-show="isPhone && !showingControls"
@click="showingControls = true"></i> @click="showingControls = true"></i>
<i class="fa fa-angle-up toggler" <i class="fa fa-angle-up toggler"
v-show="isPhone && showingControls" v-show="isPhone && showingControls"
@click.prevent="showingControls = false"></i> @click.prevent="showingControls = false"></i>
<span class="meta" v-show="meta.songCount"> <span class="meta" v-show="meta.songCount">
{{ meta.songCount }} {{ meta.songCount | pluralize 'song' }} {{ meta.songCount }} {{ meta.songCount | pluralize 'song' }}
{{ meta.totalLength }} {{ meta.totalLength }}
</span> </span>
</span> </span>
<div class="buttons" v-show="!isPhone || showingControls"> <div class="buttons" v-show="!isPhone || showingControls">
<button class="play-shuffle" <button class="play-shuffle"
@click.prevent="shuffle" @click.prevent="shuffle"
v-if="state.songs.length && selectedSongs.length < 2" v-if="state.songs.length && selectedSongs.length < 2"
> >
@ -26,28 +26,28 @@
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1"> <button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected <i class="fa fa-random"></i> Selected
</button> </button>
<button class="add-to" @click.prevent="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length"> <button class="add-to" @click.prevent.stop="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length">
{{ showingAddToMenu ? 'Cancel' : 'Add To…' }} {{ showingAddToMenu ? 'Cancel' : 'Add To…' }}
</button> </button>
<add-to-menu <add-to-menu
:songs="selectedSongs" :songs="selectedSongs"
:showing="showingAddToMenu && state.songs.length" :showing="showingAddToMenu && state.songs.length"
:settings="{ canLike: false }"> :settings="{ canLike: false }">
<add-to-menu> <add-to-menu>
</div> </div>
</h1> </h1>
<song-list <song-list
v-show="state.songs.length" v-show="state.songs.length"
:items="state.songs" :items="state.songs"
:selected-songs.sync="selectedSongs" :selected-songs.sync="selectedSongs"
type="favorites"> type="favorites">
</song-list> </song-list>
<div v-show="!state.songs.length" class="none"> <div v-show="!state.songs.length" class="none">
Start loving! Start loving!
Click the <i style="margin: 0 5px" class="fa fa-heart"></i> icon when a song is playing to add it Click the <i style="margin: 0 5px" class="fa fa-heart"></i> icon when a song is playing to add it
to this list. to this list.
</div> </div>
</section> </section>
@ -55,11 +55,11 @@
<script> <script>
import isMobile from 'ismobilejs'; import isMobile from 'ismobilejs';
import favoriteStore from '../../../stores/favorite'; import favoriteStore from '../../../stores/favorite';
import playback from '../../../services/playback'; import playback from '../../../services/playback';
import hasSongList from '../../../mixins/has-song-list'; import hasSongList from '../../../mixins/has-song-list';
export default { export default {
mixins: [hasSongList], mixins: [hasSongList],

View file

@ -2,22 +2,22 @@
<section id="playlistWrapper"> <section id="playlistWrapper">
<h1 class="heading"> <h1 class="heading">
<span>{{ playlist.name }} <span>{{ playlist.name }}
<i class="fa fa-angle-down toggler" <i class="fa fa-angle-down toggler"
v-show="isPhone && !showingControls" v-show="isPhone && !showingControls"
@click="showingControls = true"></i> @click="showingControls = true"></i>
<i class="fa fa-angle-up toggler" <i class="fa fa-angle-up toggler"
v-show="isPhone && showingControls" v-show="isPhone && showingControls"
@click.prevent="showingControls = false"></i> @click.prevent="showingControls = false"></i>
<span class="meta" v-show="meta.songCount"> <span class="meta" v-show="meta.songCount">
{{ meta.songCount }} {{ meta.songCount | pluralize 'song' }} {{ meta.songCount }} {{ meta.songCount | pluralize 'song' }}
{{ meta.totalLength }} {{ meta.totalLength }}
</span> </span>
</span> </span>
<div class="buttons" v-show="!isPhone || showingControls"> <div class="buttons" v-show="!isPhone || showingControls">
<button class="play-shuffle" <button class="play-shuffle"
@click.prevent="shuffle" @click.prevent="shuffle"
v-if="playlist.songs.length && selectedSongs.length < 2" v-if="playlist.songs.length && selectedSongs.length < 2"
> >
@ -26,7 +26,7 @@
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1"> <button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected <i class="fa fa-random"></i> Selected
</button> </button>
<button class="add-to" @click.prevent="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length"> <button class="add-to" @click.prevent.stop="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length">
{{ showingAddToMenu ? 'Cancel' : 'Add To…' }} {{ showingAddToMenu ? 'Cancel' : 'Add To…' }}
</button> </button>
<button class="del" <button class="del"
@ -39,15 +39,15 @@
</div> </div>
</h1> </h1>
<song-list v-show="playlist.songs.length" <song-list v-show="playlist.songs.length"
:items="playlist.songs" :items="playlist.songs"
:selected-songs.sync="selectedSongs" :selected-songs.sync="selectedSongs"
:playlist="playlist" :playlist="playlist"
type="playlist"> type="playlist">
</song-list> </song-list>
<div v-show="!playlist.songs.length" class="none"> <div v-show="!playlist.songs.length" class="none">
The playlist is currently empty. You can fill it up by dragging songs into its name in the sidebar, The playlist is currently empty. You can fill it up by dragging songs into its name in the sidebar,
or use the &quot;Add To&quot; button. or use the &quot;Add To&quot; button.
</div> </div>
</section> </section>

View file

@ -27,7 +27,7 @@
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1"> <button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected <i class="fa fa-random"></i> Selected
</button> </button>
<button class="add-to" @click.prevent="showingAddToMenu = !showingAddToMenu" v-if="state.songs.length > 1"> <button class="add-to" @click.prevent.stop="showingAddToMenu = !showingAddToMenu" v-if="state.songs.length > 1">
{{ showingAddToMenu ? 'Cancel' : 'Add To…' }} {{ showingAddToMenu ? 'Cancel' : 'Add To…' }}
</button> </button>
<button class="clear" @click.prevent="clear" v-if="state.songs.length">Clear</button> <button class="clear" @click.prevent="clear" v-if="state.songs.length">Clear</button>

View file

@ -2,24 +2,24 @@
<section id="songsWrapper"> <section id="songsWrapper">
<h1 class="heading"> <h1 class="heading">
<span>All Songs <span>All Songs
<i class="fa fa-angle-down toggler" <i class="fa fa-angle-down toggler"
v-show="isPhone && !showingControls" v-show="isPhone && !showingControls"
@click="showingControls = true"></i> @click="showingControls = true"></i>
<i class="fa fa-angle-up toggler" <i class="fa fa-angle-up toggler"
v-show="isPhone && showingControls" v-show="isPhone && showingControls"
@click.prevent="showingControls = false"></i> @click.prevent="showingControls = false"></i>
<span class="meta" v-show="meta.songCount"> <span class="meta" v-show="meta.songCount">
{{ meta.songCount }} {{ meta.songCount | pluralize 'song' }} {{ meta.songCount }} {{ meta.songCount | pluralize 'song' }}
{{ meta.totalLength }} {{ meta.totalLength }}
</span> </span>
</span> </span>
<div class="buttons" v-show="!isPhone || showingControls"> <div class="buttons" v-show="!isPhone || showingControls">
<button <button
class="play-shuffle" class="play-shuffle"
@click.prevent="shuffle" @click.prevent="shuffle"
v-if="state.songs.length && selectedSongs.length < 2" v-if="state.songs.length && selectedSongs.length < 2"
> >
<i class="fa fa-random"></i> All <i class="fa fa-random"></i> All
@ -28,7 +28,7 @@
<i class="fa fa-random"></i> Selected <i class="fa fa-random"></i> Selected
</button> </button>
<button class="add-to" @click.prevent="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length"> <button class="add-to" @click.prevent.stop="showingAddToMenu = !showingAddToMenu" v-if="selectedSongs.length">
{{ showingAddToMenu ? 'Cancel' : 'Add To…' }} {{ showingAddToMenu ? 'Cancel' : 'Add To…' }}
</button> </button>

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="add-to-playlist" v-show="showing"> <div class="add-to-playlist" v-show="showing" v-on-clickaway="hideMenu">
<p>Add {{ songs.length }} {{ songs.length | pluralize 'song' }} to</p> <p>Add {{ songs.length }} {{ songs.length | pluralize 'song' }} to</p>
<ul> <ul>
@ -10,11 +10,11 @@
</ul> </ul>
<p>or create a new playlist</p> <p>or create a new playlist</p>
<form class="form-save form-simple" @submit.prevent="createNewPlaylistFromSongs"> <form class="form-save form-simple" @submit.prevent="createNewPlaylistFromSongs">
<input type="text" <input type="text"
@keyup.esc.prevent="hideMenu" @keyup.esc.prevent="hideMenu"
v-model="newPlaylistName" v-model="newPlaylistName"
placeholder="Playlist name" placeholder="Playlist name"
required> required>
<button type="submit"> <button type="submit">
@ -26,6 +26,7 @@
<script> <script>
import _ from 'lodash'; import _ from 'lodash';
import VueClickaway from 'vue-clickaway';
import playlistStore from '../../stores/playlist'; import playlistStore from '../../stores/playlist';
import favoriteStore from '../../stores/favorite'; import favoriteStore from '../../stores/favorite';
@ -33,6 +34,7 @@
export default { export default {
props: ['songs', 'showing', 'settings'], props: ['songs', 'showing', 'settings'],
mixins: [ VueClickaway.mixin ],
data() { data() {
return { return {
@ -106,14 +108,14 @@
*/ */
createNewPlaylistFromSongs() { createNewPlaylistFromSongs() {
this.newPlaylistName = this.newPlaylistName.trim(); this.newPlaylistName = this.newPlaylistName.trim();
if (!this.newPlaylistName) { if (!this.newPlaylistName) {
return; return;
} }
playlistStore.store(this.newPlaylistName, this.songs, () => { playlistStore.store(this.newPlaylistName, this.songs, () => {
this.newPlaylistName = ''; this.newPlaylistName = '';
// Activate the new playlist right away // Activate the new playlist right away
this.$root.loadPlaylist(_.last(this.playlistState.playlists)); this.$root.loadPlaylist(_.last(this.playlistState.playlists));
}); });
@ -127,8 +129,8 @@
}, },
clearSelection() { clearSelection() {
this.$parent.$broadcast('song:selection-clear'); this.$parent.$broadcast('song:selection-clear');
} },
}, },
}; };
</script> </script>
@ -144,7 +146,7 @@
top: 36px; top: 36px;
left: 0; left: 0;
width: 100%; width: 100%;
p { p {
margin: 4px 0; margin: 4px 0;
font-size: 90%; font-size: 90%;
@ -159,7 +161,7 @@
ul { ul {
max-height: 5 * ($itemHeight + $itemMargin); max-height: 5 * ($itemHeight + $itemMargin);
overflow-y: scroll; overflow-y: scroll;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
} }