Skip to content

Instantly share code, notes, and snippets.

@perrupa
Created September 24, 2012 17:48
Show Gist options
  • Save perrupa/3777267 to your computer and use it in GitHub Desktop.
Save perrupa/3777267 to your computer and use it in GitHub Desktop.
Song Carousel
var Song = Backbone.Model.extend({
defaults : {
selected : false,
active : false
},
initialize : function(attributes) {
this.set("uniqueID", this.cid);
if(!this.get("voted")) {
this.set({"voted" : this.defaults.voted});
}
}
});
var SongCollection = Backbone.Collection.extend({
Model : Song,
currentIndex : 0,
displayedSize : 5,
getCurrentSongs : function() {
var songs = this.toArray(),
interval = Math.floor(this.displayedSize / 2),
self = this;
// return songs.slice(this.currentIndex, this.currentIndex + this.displayedSize);
var range = _.range(this.currentIndex - interval, this.currentIndex + interval + 1);
var currentSongs = _.map(range, function(i) {
return self.getSongAt(i);
});
return currentSongs;
},
getCurrentSong : function() {
//return this.at(this.currentIndex + Math.floor(this.displayedSize / 2));
return this.at(this.currentIndex);
},
getPrevious : function() {
var interval = Math.floor(this.displayedSize / 2),
index = this.currentIndex - 1,//interval,
song = this.getSongAt(index);
return song;
},
getNext : function() {
var interval = Math.floor(this.displayedSize / 2),
index = this.currentIndex + 1,// interval,
song = this.getSongAt(index);
return song;
},
getSongAt : function(index) {
if(index > this.length - 1 || index < 0)
return {};
else
return this.at(index);
},
forward : function() {
if(this.currentIndex >= this.length) return this;
this.at(this.currentIndex).set("selected", false);
this.at(this.currentIndex).set("active", false);
this.currentIndex++;
this.at(this.currentIndex).set("selected", true);
return this;
},
backward : function() {
if(this.currentIndex === 0) return this;
this.at(this.currentIndex).set("selected", false);
this.at(this.currentIndex).set("active", false);
this.currentIndex--;
this.at(this.currentIndex).set("selected", true);
return this;
}
});
var SongView = Backbone.View.extend({
events : {
"click em" : "authorClick",
"click .playBtn" : "openPlayer"
},
// template : Handlebars.compile($("#songTemplate").html()),
// template : Handlebars.compile($("#smallSongTemplate").html()),
template : Handlebars.compile($("#largeSongTemplate").html()),
// songPlayerTemplate : Handlebars.compile($("#songPlayerTemplate").html()),
initialize : function() {
// _.bindAll(this, 'render', 'authorClick', 'openPlayer', 'test');
//this.model.bind('change', this.render, this);
//this.model.bind('destroy', this.remove, this);
},
render : function() {
//this.model.view = this;
this.$el.html(this.template(this.model.toJSON())).addClass("song");
if(this.model.get("selected")) {
this.$el.addClass("selected");
createJplayer($("#"+this.model.cid), this.model.get("song_path"), "#jPlayerControls")
} else {
this.$el.removeClass("selected");
}
this.delegateEvents(this.events);
return this;
},
openPlayer : function() {
this.model.set("active", true);
this.render();
var $target = $("#"+this.model.cid);
createJplayer($target, this.model.get("song_path"), "#jPlayerControls");
},
authorClick : function() {
alert(this.model.get("composer"));
}
});
var App = Backbone.View.extend({
events : {
"click .forward" : "forward",
"click .backward" : "backward"
},
initialize : function() {
_.bindAll(this, 'render', 'forward', 'backward');
var self = this;
this.collection.each(function(song) {
if(!self.songViews.hasOwnProperty(song.cid)) {
self.songViews[song.cid] = new SongView({model : song});
}
});
this.render();
},
songContainerTemplate : Handlebars.compile($("#songContainerTemplate").html()),
songTemplate : Handlebars.compile($("#smallSongTemplate").html()),
songViews : {},
render : function() {
var self = this,
songs = this.collection.getCurrentSongs(),
$songContainer = self.$el.find(".songContainer");
// var songs = [].concat(this.collection.getPrevious(), this.collection.getCurrentSongs(), this.collection.getNext());
$songContainer.empty().transition({x : 0}, 0);
_.each(songs, function(song) {
var view;
if(song.hasOwnProperty("cid")) {
//song.createView();
song.set("selected", song.cid == self.collection.getCurrentSong().cid)
view = self.songViews[song.cid].render().$el;
} else {
view = $("<div/>").html(self.songTemplate(song)).addClass("song");
}
$(view).detach();
$songContainer.append(view);
});
//this.collection.getCurrentSong().view.$el.addClass("selected");
return this;
},
destroyJPlayer : function(cid){
var selector = "#"+cid;
if(this.$el.find(selector)){
$(selector).jPlayer("destroy");
}
},
addWrappingSongs : function() {
var $songContainer = this.$el.find(".songContainer");
//Adding a song to both ends so that "text-align: center" doesn't throw the layout off.
var nextSong = this.collection.getNext(),
prevSong = this.collection.getPrevious(),
emptySong = $("<div></div>").addClass("song");
this.songViews[nextSong.cid]
var nextSongView = this.songViews.hasOwnProperty(nextSong.cid) ? this.songViews[nextSong.cid].render().$el : emptySong,
prevSongView = this.songViews.hasOwnProperty(prevSong.cid) ? this.songViews[prevSong.cid].render().$el : emptySong;
$songContainer
.append(nextSongView)
.prepend(prevSongView);
},
forward : function(e) {
e.preventDefault();
this.destroyJPlayer(this.collection.getCurrentSong().cid);
var self = this,
width = this.$el.find(".song").width(),
$songContainer = self.$el.find(".songContainer"),
next = this.collection.getNext();
if(next.cid === undefined) {
$songContainer.transition({x : "-2%"}, function() {
$(this).transition({x : "0%"});
})
return this;
}
// this.$el.find(".selected").transition({scale : 0.5, y : "-30%", opacity : 0.5});
this.addWrappingSongs();
//handle shrinking the main guy here.
//shift list to the left
$songContainer.transition({x : -width}, 700, function() {
self.collection.forward();
// self.$el.find(".song").transition({scale : 1, y : "0", opacity : 1}, 0);
//rerender, because our animation is done.
self.render();
});
return this;
},
backward : function(e) {
e.preventDefault();
this.destroyJPlayer(this.collection.getCurrentSong().cid);
var self = this,
width = this.$el.find(".song").width(),
$songContainer = self.$el.find(".songContainer"),
prev = this.collection.getPrevious();
if(prev.cid === undefined) {
$songContainer.transition({x : "2%"}, function() {
$(this).transition({x : "0%"});
})
return this;
}
var oldSelected = this.$el.find(".selected");
//oldSelected.prev().transition({scale:1.333,y:"0%"});
// oldSelected.transition({scale : 0.5, y : "-30%", opacity : 0.5});
this.addWrappingSongs();
//handle shrinking the main guy here.
//shift list to the right
$songContainer.transition({x : width}, 700, function() {
self.collection.backward();
// self.$el.find(".song").transition({scale : 1, y : "0", opacity : 1}, 0);
//rerender, because our animation is done.
self.render();
});
return this;
}
});
// DOM is ready...
$(function() {
$(".navLink").click(function(e) {
e.preventDefault();
var $chosenArea = $($(this).attr('data-reveal')),
wasClosed = !$chosenArea.is(":visible"),
$self = $(this),
visibleNoteAreas = $(".upperNoteArea:visible"),
showArea = function($link) {
($link || $("div")).addClass("active");
$chosenArea.slideDown(300);
};
$(".headerArea .navLink").removeClass("active");
visibleNoteAreas.slideUp(300, function() {
if(wasClosed) {
showArea($self);
}
});
if(wasClosed) {
showArea($self);
}
});
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment