-
Notifications
You must be signed in to change notification settings - Fork 0
/
site.js
122 lines (107 loc) · 3.46 KB
/
site.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"use strict";
var sp = getSpotifyApi(1);
var models = sp.require('sp://import/scripts/api/models');
var views = sp.require('sp://import/scripts/api/views');
var player = models.player;
$(document).ready(function() {
/**
* Current dropped playlist.
*/
var playlist = null;
/**
* Construct jquery elements.
*/
$("#sort-radio-container").buttonset();
/**
* Setup sort button's handlers: sort on click.
*/
$("#sort-button").button()
.on('click', function(e) {
if (playlist) {
var name = $('#sort-title').val() || "unnamed";
sort_by(playlist, name, get_sort_function());
}
});
/**
* Setup #dropbox's handlers: highlight on drag, create playlist on drop.
*/
$('#dropbox')
.on('dragenter dragover', function(e) {
e.originalEvent.dataTransfer.dropEffect = 'copy'; // allow drop
$(this).addClass('over');
return false;
})
.on('dragleave drop', function(e) {
$(this).removeClass('over');
return false;
})
.on('drop', function(e) {
// get dropped playlist
var uri = e.originalEvent.dataTransfer.getData('text');
playlist = models.Playlist.fromURI(uri);
// add display player (to show playlist has been loaded)
var player = new views.Player();
player.track = null;
player.context = playlist;
$("#smart-player").empty().append(player.node);
// fill in default name for playlist
$('#sort-title').val(playlist.name + " (sorted)");
// show player and hide text
$('#dropbox-text').css('display','none');
$('#smart-player').css('display','block');
return false;
});
});
/**
* Create a copy of playlist, with tracks sorted by the value computed by sort_value.
*
* @param {models.Playlist} playlist The spotify playlist to sort.
* @param {String} name The title of the new playlist.
* @param {Function} sort_value Function used to sort tracks:
* models.Track -> *
* @return {models.Playlist} A new sorted playlist.
*/
function sort_by(playlist, name, sort_value) {
// sort on a clone so we don't edit the original playlist
var sorted_tracks = playlist.tracks.clone()
.sort(function(x,y){ return compare(sort_value(x),sort_value(y)); })
// all tracks in sorted order to new playlist
var new_playlist = new models.Playlist(name);
new_playlist.add(sorted_tracks);
return new_playlist;
}
/**
* Return a function used to sort tracks, based on which checkbox is checked.
*
* @return {Function} models.Track -> (string or number)
*/
function get_sort_function() {
// use lower case so we don't sort A-Z before a-z
if ($('#sort-on-title').prop('checked')) {
return function(x){ return x.name.toLowerCase() };
}
if ($('#sort-on-artist').prop('checked')) {
return function(x){ return x.artists[0].name.toLowerCase() };
}
if ($('#sort-on-album').prop('checked')) {
return function(x){ return x.album.name.toLowerCase() };
}
if ($('#sort-on-popularity').prop('checked')) {
return function(x){ return x.popularity };
}
return function(x){ return x };
}
/**
* Compare two values, returning 0 if equal, -1 if x<y, and 1 otherwise.
*/
function compare(x, y) {
return x === y ? 0 : x <= y ? -1 : 1;
}
/**
* Equivalent to Array.forEach, but also returns the array for chaining.
*/
Array.prototype.tap = function(f) { this.forEach(f); return this; };
/**
* Returns a shallow copy of the array.
*/
Array.prototype.clone = function(x) { return this.map(function(y) { return y; }); };