CoffeeScript integrated. Debugging
This commit is contained in:
parent
ab63697594
commit
b9ac20f575
3
Gemfile
3
Gemfile
|
@ -6,6 +6,9 @@ gem 'json'
|
|||
gem 'sass'
|
||||
gem 'coffee-script'
|
||||
|
||||
gem 'therubyracer', :require => false
|
||||
gem 'barista'
|
||||
|
||||
gem 'awesome_print', :require => 'ap'
|
||||
gem 'delayed_job'
|
||||
gem 'lastfm', :git => 'git://github.com/magnolia-fan/ruby-lastfm.git'
|
||||
|
|
|
@ -47,6 +47,8 @@ GEM
|
|||
activesupport (3.0.9)
|
||||
arel (2.0.10)
|
||||
awesome_print (0.4.0)
|
||||
barista (1.2.1)
|
||||
coffee-script (~> 2.2)
|
||||
builder (2.1.2)
|
||||
coffee-script (2.2.0)
|
||||
coffee-script-source
|
||||
|
@ -66,6 +68,7 @@ GEM
|
|||
crack (= 0.1.8)
|
||||
i18n (0.5.0)
|
||||
json (1.5.3)
|
||||
libv8 (3.3.10.2)
|
||||
mail (2.2.19)
|
||||
activesupport (>= 2.3.6)
|
||||
i18n (>= 0.4.0)
|
||||
|
@ -98,6 +101,8 @@ GEM
|
|||
rdoc (3.6.1)
|
||||
sass (3.1.3)
|
||||
sqlite3 (1.3.3)
|
||||
therubyracer (0.9.2)
|
||||
libv8 (~> 3.3.10)
|
||||
thor (0.14.6)
|
||||
treetop (1.4.9)
|
||||
polyglot (>= 0.3.1)
|
||||
|
@ -109,6 +114,7 @@ PLATFORMS
|
|||
|
||||
DEPENDENCIES
|
||||
awesome_print
|
||||
barista
|
||||
coffee-script
|
||||
delayed_job
|
||||
json
|
||||
|
@ -118,3 +124,4 @@ DEPENDENCIES
|
|||
rails (= 3.0.9)
|
||||
sass
|
||||
sqlite3
|
||||
therubyracer
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
class Ajax
|
||||
|
||||
referer: false
|
||||
|
||||
loadArtistData: (name) ->
|
||||
search.showSpinner()
|
||||
name = name.split(' ').join('+')
|
||||
$.get '/artist/' +name+ '/', (data) ->
|
||||
if data.status?
|
||||
if data.status is 'loading'
|
||||
search.showArtistPics data.pics
|
||||
setTimeout () ->
|
||||
this.loadArtistData name
|
||||
, 3000
|
||||
else if data.status is 'corrected'
|
||||
ajax.loadArtistData data.page
|
||||
else if data.status is 'suggestions'
|
||||
search.hideSpinner()
|
||||
search.showSuggestions data.values
|
||||
else if data.status == 'loading_failed'
|
||||
search.hideSpinner()
|
||||
search.showError()
|
||||
else
|
||||
this.setArchor '/artist/' +name+ '/'
|
||||
pages.renderArtist data
|
||||
beathaven.redrawScrollbar()
|
||||
|
||||
loadSearchPage: ->
|
||||
$.get '/templates/search.html', (data) ->
|
||||
this.setArchor '/search/'
|
||||
pages.renderSearch data
|
||||
|
||||
loadSettingsPage: ->
|
||||
$.get '/templates/settings.html', (data) ->
|
||||
this.setArchor '/settings/'
|
||||
pages.renderSettings data
|
||||
|
||||
load404Page: ->
|
||||
$.get '/404.html', (data) ->
|
||||
$('.data-container .inner').html data
|
||||
beathaven.redrawScrollbar()
|
||||
|
||||
setArchor: (anchor) ->
|
||||
@referer = this.getAnchor()
|
||||
window.location.hash = '#' +anchor
|
||||
|
||||
getAnchor: () ->
|
||||
window.location.hash.substring 1;
|
||||
|
||||
setTitle: (title) ->
|
||||
document.title = title+ ' @ BeatHaven'
|
||||
|
||||
detectPage: () ->
|
||||
if m = this.getAnchor().match /\/artist\/(.+)\//
|
||||
this.loadArtistData m[1]
|
||||
else if this.getAnchor() == '' or Ajax.getAnchor().match /\/search\//
|
||||
this.loadSearchPage();
|
||||
else if this.getAnchor().match /\/settings\//
|
||||
this.loadSearchPage()
|
||||
else
|
||||
this.load404Page()
|
||||
|
||||
|
||||
$ ->
|
||||
window.ajax = new Ajax()
|
||||
$('a.data.artist').live 'click', ->
|
||||
ajax.loadArtistData $(this).html()
|
||||
false
|
||||
$(window).bind 'hashchange', ->
|
||||
ajax.detectPage()
|
|
@ -0,0 +1,76 @@
|
|||
$ ->
|
||||
l = document.location
|
||||
if l.host not in ['beathaven.org', 'localhost']
|
||||
l.href = 'http://beathaven.org/'+ l.hash
|
||||
|
||||
window.beathaven = new BeatHaven()
|
||||
window.vkontakte = new Vkontakte(if l.host == 'beathaven.org' then 2335068 else 2383163)
|
||||
|
||||
beathaven.init()
|
||||
vkontakte.init()
|
||||
|
||||
$(window).resize ->
|
||||
beathaven.adjustSizes()
|
||||
window.setTimeout ->
|
||||
beathaven.checkRedrawScrollbar()
|
||||
, 500
|
||||
|
||||
class BeatHaven
|
||||
|
||||
last_height: false
|
||||
|
||||
init: ->
|
||||
this.drawInterface()
|
||||
this.adjustSizes()
|
||||
ajax.detectPage()
|
||||
|
||||
adjustSizes: ->
|
||||
$('.data-container').height $(window).height() - $('.header-container').height()
|
||||
$('.data-container').width $(window).width() - $('.player').width()
|
||||
$('.player-container').height $(window).height()
|
||||
$('.playlist').height $(window).height() - $('.player').height() - $('.player-container .additional-controls').height()
|
||||
|
||||
$('.data-container').scrollbar()
|
||||
$('.playlist').scrollbar()
|
||||
|
||||
checkRedrawScrollbar: ->
|
||||
focused_id = false
|
||||
if document.activeElement.id?
|
||||
focused_id = document.activeElement.id;
|
||||
outer_height = $('.data-container > div').outerHeight()
|
||||
if outer_height > 300 and outer_height != @last_height
|
||||
@last_height = outer_height
|
||||
this.redrawScrollbar()
|
||||
if focused_id
|
||||
document.getElementById(focused_id).focus()
|
||||
focused_id = false
|
||||
window.setTimeout ->
|
||||
beathaven.checkRedrawScrollbar()
|
||||
, 500
|
||||
|
||||
redrawScrollbar: ->
|
||||
$('.data-container').html $('.data-container').find('.inner').first()
|
||||
$('.data-container').scrollbar()
|
||||
|
||||
|
||||
String::htmlsafe = ->
|
||||
replaces = [
|
||||
["\\", "\\\\"]
|
||||
["\"", """]
|
||||
["<", "<"]
|
||||
[">", ">"]
|
||||
]
|
||||
str = this
|
||||
for item in replaces
|
||||
str = str.replace item[0], item[1]
|
||||
str
|
||||
|
||||
String::trim = ->
|
||||
str = this
|
||||
while str.indexOf(' ') != -1
|
||||
str = str.replace(' ', ' ')
|
||||
if str.charAt(0) == ' '
|
||||
str = str.substring 1
|
||||
if str.charAt(str.length - 1) == ' '
|
||||
str = str.substring(0, str.length - 1)
|
||||
str
|
|
@ -0,0 +1,88 @@
|
|||
class Pages
|
||||
|
||||
renderArtist: (data) ->
|
||||
artist_info = $ '
|
||||
<div class="artist-info">
|
||||
<div class="pic">
|
||||
<img src="' +data.artist.pic+ '" alt="' +data.artist.name+ '" width="250" />
|
||||
</div>
|
||||
<h1 class="name">' +data.artist.name+ '</h1>
|
||||
<div class="info">
|
||||
' +data.artist.desc+ '
|
||||
</div>
|
||||
</div>'
|
||||
|
||||
albums_info = $ '<div class="albums"></div>'
|
||||
$.each data.albums, (i, album) ->
|
||||
if album.year?
|
||||
album_info = $ '
|
||||
<div class="album">
|
||||
<h2 class="name">' +album.name+ ' (' +album.year+ ')</h2>
|
||||
<div class="pic">
|
||||
<img src="' +(if album.pic then album.pic else '/images/kitteh.png')+ '" alt="' +album.name+ ' by ' +data.artist.name+ '" width="250" height="250"/>
|
||||
<div class="add-album-button-container">
|
||||
<div class="add-album button gray">Add to Now Playing</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tracklist"><ul></ul></div>
|
||||
</div>
|
||||
<div class="kaboom"></div>'
|
||||
|
||||
$.each album.tracks.album, (i, track) ->
|
||||
track_info = $ '
|
||||
<li>
|
||||
<div class="add-track button gray">+</div>
|
||||
<div class="track-container">
|
||||
<div class="fade"></div>
|
||||
<span class="index">' +(i+1)+ '</span>
|
||||
<div class="trackname" title="' +track.name.htmlsafe()+ '">' +track.name+ '</div>
|
||||
<div class="length">' +track.duration+ '</div>
|
||||
</div>
|
||||
</li>'
|
||||
|
||||
$(album_info).find('.tracklist ul').append(track_info)
|
||||
|
||||
$(albums_info).append(album_info)
|
||||
|
||||
$('.data-container').css backgroundImage: 'none'
|
||||
$('.data-container .inner').html('').append(artist_info).append(albums_info)
|
||||
|
||||
yaCounter7596904.hit ajax.getAnchor(), data.artist.name, ajax.referer
|
||||
ajax.setTitle data.artist.name
|
||||
|
||||
renderSearch: (data) ->
|
||||
$('.data-container').css background: 'url(/images/concrete_wall_2.png) 0 -30px repeat'
|
||||
$('.data-container .inner').html data
|
||||
|
||||
$('.search-container')
|
||||
.css('marginLeft', ($('.data-container').width() - 425) / 2 + 'px')
|
||||
.css('marginTop', ($('.data-container').height() / 2 - 230)+ 'px')
|
||||
.height(($('.data-container').height() - $('#search_form').height()) / 2)
|
||||
|
||||
setTimeout ->
|
||||
$('#search_field').bh_autocomplete
|
||||
serviceUrl: '/artist/autocomplete' # Страница для обработки запросов автозаполнения
|
||||
minChars: 2 # Минимальная длина запроса для срабатывания автозаполнения
|
||||
delimiter: /(,|;)\s*/ # Разделитель для нескольких запросов, символ или регулярное выражение
|
||||
maxHeight: 400 # Максимальная высота списка подсказок, в пикселях
|
||||
width: 415 # Ширина списка
|
||||
zIndex: 9999 # z-index списка
|
||||
deferRequestBy: 500 # Задержка запроса (мсек)
|
||||
onSelect: ->
|
||||
ajax.loadArtistData()
|
||||
$('#search_field').focus()
|
||||
, 501
|
||||
|
||||
yaCounter7596904.hit ajax.getAnchor(), 'Artist Search', ajax.referer
|
||||
ajax.setTitle 'Artist Search'
|
||||
|
||||
renderSettings: (data) ->
|
||||
$('.data-container').css background: 'none'
|
||||
$('.data-container .inner').html data
|
||||
yaCounter7596904.hit ajax.getAnchor(), 'Settings', ajax.referer
|
||||
ajax.setTitle 'Settings'
|
||||
$('.settings-container .tabs .tab').first().trigger 'click'
|
||||
|
||||
$ ->
|
||||
window.pages = new Pages()
|
||||
false
|
|
@ -0,0 +1,245 @@
|
|||
class Player
|
||||
|
||||
bar_width: 330
|
||||
jp: null
|
||||
scrobbled: false
|
||||
|
||||
initJplayer: ->
|
||||
self = this
|
||||
|
||||
@jp = $("#jplayer")
|
||||
@jp.jPlayer
|
||||
swfPath: "/js"
|
||||
supplied: "mp3"
|
||||
cssSelectorAncestor: ""
|
||||
cssSelector:
|
||||
play: "#player .play"
|
||||
pause: "#player .pause"
|
||||
stop: ""
|
||||
videoPlay: ""
|
||||
seekBar: ""
|
||||
playBar: ""
|
||||
mute: ""
|
||||
unmute: ""
|
||||
volumeBar: ""
|
||||
volumeBarValue: ""
|
||||
currentTime: ""
|
||||
duration: ""
|
||||
|
||||
@jp.bind $.jPlayer.event.timeupdate, (e) ->
|
||||
data = e.jPlayer.status
|
||||
if not Player.scrobbled and data.currentPercentAbsolute > 50
|
||||
$obj = $('.playlist-tracks li.now')
|
||||
self.scrobble $obj.attr('data-artist'), $obj.attr('data-album'), $obj.attr('data-track')
|
||||
Player.scrobbled = true
|
||||
$('#player .progress .loaded').width(data.seekPercent * self.bar_width / 100)
|
||||
$('#player .progress .played').width(data.currentPercentAbsolute * self.bar_width / 100)
|
||||
|
||||
@jp.bind $.jPlayer.event.ended, (e) ->
|
||||
next = self.nextTrack()
|
||||
if not next
|
||||
$('#jplayer').jPlayer 'clearMedia'
|
||||
$('#player .now-playing').html 'Nothing left to <strike>lose</strike> play'
|
||||
$('#player .loaded, #player .played').width 0
|
||||
$('.playlist-tracks li').removeClass 'now'
|
||||
else
|
||||
self.setTrack next
|
||||
false
|
||||
|
||||
addTrack: (artist, album, track, length, autoplay) ->
|
||||
if not autoplay?
|
||||
autoplay = false
|
||||
initial_count = $('.playlist-tracks li').length
|
||||
$('.playlist-tracks').append '
|
||||
<li id="i' +Math.round(Math.random() * 999999)+ '" data-artist="' +artist.trim()+ '" data-album="' +album.trim()+ '" data-track="' +track.trim()+ '" data-length="' +length+ '">
|
||||
<div class="item">
|
||||
<div class="fade"></div>
|
||||
<span class="title" title="' +artist.htmlsafe()+ ' &mdash ' +track.htmlsafe()+ '">' +artist+ ' &mdash ' +track+ '</span>
|
||||
<span class="duration">' +length+ '</span>
|
||||
<div class="remove">remove</div>
|
||||
</div>
|
||||
</li>'
|
||||
|
||||
$('#playlist').html($('.playlist-tracks')).scrollbar()
|
||||
$('.playlist-tracks').sortable()
|
||||
|
||||
if autoplay
|
||||
Player.setTrack($('.playlist-tracks li').last().attr('id').split('i')[1])
|
||||
else if initial_count == 0 and not Player.hasTrack()
|
||||
Player.setTrack($('.playlist-tracks li').first().attr('id').split('i')[1])
|
||||
|
||||
setTrack: (id) ->
|
||||
$obj = $('#i' +id)
|
||||
query = $obj.attr('data-artist')+ ' &mdash ' +$obj.attr('data-track')
|
||||
|
||||
$('#player .now-playing').html query+ '<div class="fade"></div>'
|
||||
$('.playlist-tracks li').removeClass 'now'
|
||||
$obj.addClass 'now'
|
||||
$('#player .loaded, #player .played').width 0
|
||||
|
||||
vkontakte.loadTracksData $obj.attr('data-artist'), $obj.attr('data-track'), $obj.attr('data-length'), ->
|
||||
player.playSource()
|
||||
this.updateNowListening $obj.attr('data-artist'), $obj.attr('data-album'), $obj.attr('data-track')
|
||||
|
||||
hasTrack: ->
|
||||
if $('#jplayer audio').length > 0
|
||||
return $('#jplayer audio').attr('src')?
|
||||
else if $('#jplayer object').length > 0
|
||||
$('#jplayer').jPlayer 'play'
|
||||
true
|
||||
false
|
||||
|
||||
playSource: (url) ->
|
||||
$('#jplayer').jPlayer 'setMedia', mp3: url
|
||||
$('#jplayer').jPlayer 'play'
|
||||
@scrobbled = false
|
||||
|
||||
nextTrack: (manual) ->
|
||||
manual = manual?
|
||||
cnt = $('.playlist-tracks li').length
|
||||
if not this.onShuffle() # Shuffle off
|
||||
if $('.playlist-tracks .now').next().length == 0 # Last track and repeat is on
|
||||
if Player.onRepeat() or manual # Repeat or manual click
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1]
|
||||
else
|
||||
false
|
||||
else
|
||||
return $('.playlist-tracks .now').next().attr('id').split('i')[1]
|
||||
else if cnt == 1 # Single track in the playlist
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1]
|
||||
else # Shuffle on
|
||||
while true
|
||||
rnd = Math.floor(Math.random() * (cnt + .999))
|
||||
$li = $('.playlist-tracks li').eq rnd
|
||||
if $li.length > 0 and not $li.hasClass 'now'
|
||||
return $li.attr('id').split('i')[1]
|
||||
false
|
||||
|
||||
prevTrack: ->
|
||||
cnt = $('.playlist-tracks li').length
|
||||
if not Player.onShuffle() # Shuffle off
|
||||
if $('.playlist-tracks .now').prev().length == 0 # First track in the playlist
|
||||
return $('.playlist-tracks li').last().attr('id').split('i')[1]
|
||||
else
|
||||
return $('.playlist-tracks .now').prev().attr('id').split('i')[1]
|
||||
else if cnt == 1 # Single track in the playlist
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1]
|
||||
else # Shuffle on
|
||||
while true
|
||||
rnd = Math.floor(Math.random() * (cnt + .999))
|
||||
$li = $('.playlist-tracks li').eq rnd
|
||||
if $li.length > 0 and not $li.hasClass 'now'
|
||||
return $li.attr('id').split('i')[1]
|
||||
false
|
||||
|
||||
onShuffle: ->
|
||||
return $('#shuffle').hasClass 'active'
|
||||
|
||||
onRepeat: ->
|
||||
return $('#repeat').hasClass 'active'
|
||||
|
||||
updateNowListening: (artist, album, track) ->
|
||||
if session.user.lastfm_username
|
||||
session.query '/lastfm/listening?r=' +Math.random(), artist: artist, album: album, track: track
|
||||
|
||||
scrobble: (artist, album, track) ->
|
||||
if session.user.lastfm_username
|
||||
session.query '/lastfm/scrobble?r=' +Math.random(), artist: artist, album: album, track: track
|
||||
|
||||
|
||||
$ ->
|
||||
window.player = new Player()
|
||||
window.player.initJplayer()
|
||||
false
|
||||
|
||||
|
||||
# Player Controls
|
||||
|
||||
$('#player .controls .prev').live 'click', ->
|
||||
Player.setTrack Player.prevTrack()
|
||||
false
|
||||
|
||||
$('#player .controls .next').live 'click', ->
|
||||
Player.setTrack Player.nextTrack(true)
|
||||
false
|
||||
|
||||
$('#player .play').live 'click', ->
|
||||
if $('.playlist-tracks li').length > 0 and not Player.hasTrack()
|
||||
player.setTrack $('.playlist-tracks li').first().attr('id').split('i')[1]
|
||||
false
|
||||
|
||||
$('#player .progress').live 'click', (e) ->
|
||||
$('#jplayer').jPlayer 'playHead', Math.round((e.offsetX / Player.bar_width) * 100)
|
||||
false
|
||||
|
||||
# Player Additional Controls
|
||||
|
||||
$('#repeat, #shuffle').live 'click', ->
|
||||
$(this).toggleClass 'active'
|
||||
false
|
||||
|
||||
$('#empty-playlist').live 'click', ->
|
||||
if confirm('Are you sure?')
|
||||
$('.playlist-tracks li').remove()
|
||||
$('#jplayer').jPlayer 'clearMedia'
|
||||
$('#player .now-playing').text 'Add some music to playlist'
|
||||
$('#player .loaded, #player .played').width 0
|
||||
false
|
||||
|
||||
# Playlist Actions
|
||||
|
||||
$('.playlist-tracks li .fade, .playlist-tracks li .duration, .playlist-tracks li .remove').live 'mouseover mouseout', (e) ->
|
||||
if e.type == 'mouseover'
|
||||
$(this).parent().find('.duration').hide()
|
||||
$(this).parent().find('.remove').show()
|
||||
else
|
||||
$(this).parent().find('.remove').hide()
|
||||
$(this).parent().find('.duration').show()
|
||||
false
|
||||
|
||||
$('.playlist-tracks li .remove').live 'click', ->
|
||||
$li = $(this).parent().parent()
|
||||
if $li.hasClass 'now'
|
||||
$('#jplayer').jPlayer 'clearMedia'
|
||||
$('#player .now-playing').text '...'
|
||||
$('#player .loaded, #player .played').width 0
|
||||
$li.remove()
|
||||
false
|
||||
|
||||
$('.playlist-tracks li').live 'dblclick', ->
|
||||
player.setTrack $(this).attr('id').split('i')[1]
|
||||
false
|
||||
|
||||
# Adding To Playlist actions
|
||||
|
||||
$('.add-album').live 'click', ->
|
||||
artist = $('.artist-info .name').html()
|
||||
album = $(this).parent().parent().parent().find('h2.name').text().replace /\s\([\d]{4}\)$/, ''
|
||||
for item in $(this).parent().parent().parent().find('.tracklist li')
|
||||
track_name = $(item).find('.trackname').html()
|
||||
length = $(item).find('.length').html()
|
||||
Player.addTrack artist, album, track_name, length
|
||||
false
|
||||
|
||||
$('.add-track').live 'click', ->
|
||||
artist = $('.artist-info .name').html()
|
||||
album = $(this).parent().parent().parent().parent().find('h2.name').text().replace /\s\([\d]{4}\)$/, ''
|
||||
track_name = $(this).parent().find('.trackname').html()
|
||||
length = $(this).parent().find('.length').html()
|
||||
Player.addTrack artist, album, track_name, length
|
||||
false
|
||||
|
||||
$('.tracklist li').live 'mouseover mouseout', (e) ->
|
||||
if e.type == 'mouseover'
|
||||
$(this).find('.add-track').show()
|
||||
else
|
||||
$(this).find('.add-track').hide()
|
||||
false
|
||||
|
||||
$('.tracklist li').live 'dblclick', (e) ->
|
||||
artist = $('.artist-info .name').html()
|
||||
album = $(this).parent().parent().parent().find('h2.name').text().replace /\s\([\d]{4}\)$/, ''
|
||||
track_name = $(this).find('.trackname').html()
|
||||
length = $(this).find('.length').html()
|
||||
Player.addTrack artist, album, track_name, length, true
|
||||
false
|
|
@ -0,0 +1,64 @@
|
|||
class Search
|
||||
|
||||
pics: []
|
||||
|
||||
showSpinner: ->
|
||||
$('.search-container input').attr(disabled: 'disabled').blur()
|
||||
$('.search-container img').show()
|
||||
$('.autocomplete-container').hide()
|
||||
$('.artist_loading.failed').hide()
|
||||
this.hideSuggestions()
|
||||
false
|
||||
|
||||
hideSpinner: ->
|
||||
$('.search-container input').removeAttr 'disabled'
|
||||
$('.search_field').focus()
|
||||
$('.search-container img').hide()
|
||||
false
|
||||
|
||||
showSuggestions: (values) ->
|
||||
for item in values
|
||||
$('.suggestions ul').append '
|
||||
<li>
|
||||
<a class="data artist">' +item.name+ '</a>
|
||||
' +(if item.desc then '<br/><span>'+ item.desc +'</span>' else '')+ '
|
||||
</li>'
|
||||
$('.suggestions').show()
|
||||
false
|
||||
|
||||
hideSuggestions: ->
|
||||
$('.suggestions ul li').remove()
|
||||
$('.suggestions').hide()
|
||||
false
|
||||
|
||||
showArtistPics: (pics) ->
|
||||
$('.artist_loading.ok, .artist_pics').show()
|
||||
for pic in pics
|
||||
if @pics.indexOf(pic) == -1
|
||||
@pics.push(pic);
|
||||
$('.artist_pics').append '
|
||||
<div class="pic">
|
||||
<img src="' +pic+ '" alt=""/>
|
||||
</div>'
|
||||
false
|
||||
|
||||
showError: ->
|
||||
$('.artist_loading.ok, .artist_pics').hide()
|
||||
$('.artist_loading.failed').show()
|
||||
@pics = []
|
||||
|
||||
|
||||
$ ->
|
||||
window.search = new Search()
|
||||
false
|
||||
|
||||
$('.search').live 'click', ->
|
||||
ajax.loadSearchPage()
|
||||
false
|
||||
$('#search_form').live 'submit', ->
|
||||
$('.autocomplete-container').remove()
|
||||
ajax.loadArtistData $('#search_field').val()
|
||||
false
|
||||
$('.suggestions a').live 'click', ->
|
||||
$('#search_field').val $(this).text()
|
||||
false
|
|
@ -0,0 +1,23 @@
|
|||
class Session
|
||||
|
||||
vk_params: null
|
||||
user: null
|
||||
|
||||
constructor: (@vk_params) ->
|
||||
|
||||
query: (url, params, callback) ->
|
||||
q_params = @vk_params
|
||||
for attr in params
|
||||
q_params[attr] = params[attr]
|
||||
$.post url, q_params, callback
|
||||
false
|
||||
|
||||
setVkParams: (params) ->
|
||||
attrs = ['expire', 'mid', 'secret', 'sid', 'sig']
|
||||
for key in attrs
|
||||
@vk_params[key] = params[key]
|
||||
false
|
||||
|
||||
$ ->
|
||||
window.session = new Session()
|
||||
false
|
|
@ -0,0 +1,41 @@
|
|||
class Settings
|
||||
|
||||
getAccountInfo: (callback) ->
|
||||
session.query '/user/update/', {}, callback
|
||||
|
||||
saveAccountInfo: (params, callback) ->
|
||||
session.query '/user/update', params, callback
|
||||
|
||||
loadFormData: (form) ->
|
||||
if form == 'account'
|
||||
$('.settings-container .form input[name$="username"]').val session.user.name
|
||||
$('.settings-container .form input[name$="email"]').val session.email
|
||||
else if form == 'lastfm'
|
||||
if @user.lastfm_username
|
||||
$('.form-container input[name$="username"]').first().val session.lastfm_username
|
||||
|
||||
$ ->
|
||||
window.settings = new Settings()
|
||||
false
|
||||
|
||||
$('.settings') .live 'click', ->
|
||||
ajax.loadSettingsPage();
|
||||
|
||||
$('.settings-container .tabs .tab').live 'click', ->
|
||||
if $(this).hasClass 'active'
|
||||
$('.settings-container .tabs .tab').removeClass 'active'
|
||||
$(this).addClass 'active'
|
||||
$('.form-container').html $('.forms .'+ $(this).attr 'data-fieldset').html()
|
||||
settings.loadFormData $(this).attr 'data-fieldset'
|
||||
|
||||
$('.lastfm-connect') .live 'click', ->
|
||||
window.open session.user.lastfm_login_url
|
||||
|
||||
$('.settings-container .form input').live 'blur', ->
|
||||
active_tab = $('.settings-container .tabs .tab.active').attr 'data-fieldset'
|
||||
if active_tab == 'account'
|
||||
params =
|
||||
username: $('.settings-container .form input[name$="username"]').first().val()
|
||||
email: $('.settings-container .form input[name$="email"]').first().val()
|
||||
settings.saveAccountInfo params, ->
|
||||
$('#header-container .hello .greating').text 'Hi there, ' +(if params.username.length > 0 then params.username else '%username%')+ '!'
|
|
@ -0,0 +1,92 @@
|
|||
class Vkontakte
|
||||
|
||||
qr: []
|
||||
|
||||
constructor: (@api_id) ->
|
||||
|
||||
init: ->
|
||||
VK.init
|
||||
apiId: @api_id
|
||||
nameTransportPath: '/xd_receiver.html'
|
||||
|
||||
VK.Auth.getLoginStatus this.authInfo
|
||||
|
||||
authInfo: (response) ->
|
||||
if typeof response isnt 'undefined' and response.session
|
||||
session.setVkParams response.session
|
||||
|
||||
$('#vk_login, .auth_notice').hide()
|
||||
$('#vk_logout').css display: 'block'
|
||||
|
||||
$('#search_field').focus() if $('#search_field').length > 0
|
||||
|
||||
session.query '/user/auth', {}, (ar) ->
|
||||
if ar.newbie
|
||||
VK.Api.call 'getVariable', key: 1281, (r) ->
|
||||
Session.query '/user/update', name: r.response, (ar2) ->
|
||||
session.user = ar2.user
|
||||
$('#header-container .hello .greating')
|
||||
.text 'Hi there, ' +(if session.user.name then session.user.name else '%username%')+ '!'
|
||||
else
|
||||
session.user = ar.user
|
||||
|
||||
$('#header-container .hello .greating')
|
||||
.text 'Hi there, ' +( if session.user.name then session.user.name else '%username%')+ '!'
|
||||
else
|
||||
$('#vk_login, .auth_notice').css display: 'block'
|
||||
$('#vk_logout').hide()
|
||||
|
||||
loadTracksData: (artist, track, duration, callback) ->
|
||||
track_prepared = track.replace(/\(.*\)/i, '').split('/')[0];
|
||||
query = artist +' '+ track_prepared;
|
||||
if @qr[query]?
|
||||
callback @qr[query]
|
||||
else
|
||||
VK.Api.call 'audio.search', q: query, (r) ->
|
||||
url = this.matchPerfectResult r.response, artist, track, duration
|
||||
@qr[query] = url;
|
||||
callback url
|
||||
|
||||
matchPerfectResult: (data, artist, track, duration) ->
|
||||
duration = duration.split ':'
|
||||
|
||||
duration = parseInt(duration[0], 10) * 60 + parseInt(duration[1], 10)
|
||||
best_score = 0;
|
||||
best_result = null;
|
||||
for item in data
|
||||
score = 0;
|
||||
item.artist = item.artist.trim();
|
||||
item.title = item.title.trim();
|
||||
|
||||
if item.artist == artist
|
||||
score += 10
|
||||
else if item.artist.split(artist).length is 2
|
||||
score += 5
|
||||
else if item.title.split(artist).length is 2
|
||||
score += 4
|
||||
|
||||
if item.title == track
|
||||
score += 10
|
||||
else if item.title.split(track).length is 2
|
||||
score += 5
|
||||
|
||||
if parseInt(item.duration, 10) == duration
|
||||
score += 15
|
||||
else
|
||||
delta = Math.abs parseInt(item.duration, 10) - duration
|
||||
score += (10 - delta) if delta < 10
|
||||
|
||||
if score > best_score
|
||||
best_score = score
|
||||
best_result = item
|
||||
|
||||
if score is 35
|
||||
return best_result.url
|
||||
|
||||
return best_result.url
|
||||
|
||||
$ ->
|
||||
$('#vk_login').click ->
|
||||
VK.Auth.login vkontakte.authInfo, 8
|
||||
$('#vk_logout').click ->
|
||||
VK.Auth.logout vkontakte.authInfo
|
|
@ -23,4 +23,8 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def index
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,14 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Beathaven</title>
|
||||
<%= stylesheet_link_tag :all %>
|
||||
<%= javascript_include_tag :defaults %>
|
||||
<%= csrf_meta_tag %>
|
||||
</head>
|
||||
<body>
|
||||
<head>
|
||||
<title>BetaHaven</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/stylesheets/beathaven.css" />
|
||||
<script type="text/javascript" charset="windows-1251" src="http://vkontakte.ru/js/api/openapi.js"></script>
|
||||
<%= javascript_include_tag "jquery/jquery.min.js" %>
|
||||
<%= javascript_include_tag "jquery/jquery-ui/js/jquery-ui-1.8.13.custom.min.js" %>
|
||||
<%= javascript_include_tag "jquery/jquery.autocomplete.js" %>
|
||||
<%= javascript_include_tag "jquery/jquery.contentchange.js" %>
|
||||
<%= javascript_include_tag "jquery/jquery.jplayer.js" %>
|
||||
<%= javascript_include_tag "jquery/jquery.scroll.js" %>
|
||||
|
||||
<%= yield %>
|
||||
<%= javascript_include_tag "coffee/player.js", :type => "text/javascript", :charset => "utf-8" %>
|
||||
<%= javascript_include_tag "coffee/search.js", :type => "text/javascript", :charset => "utf-8" %>
|
||||
<%= javascript_include_tag "coffee/pages.js", :type => "text/javascript", :charset => "utf-8" %>
|
||||
<%= javascript_include_tag "coffee/settings.js", :type => "text/javascript", :charset => "utf-8" %>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
<div class="player-container">
|
||||
<div class="player">
|
||||
<div id="jplayer"></div>
|
||||
<div class="now-playing">Add some music to playlist</div>
|
||||
<div class="progress">
|
||||
<div class="loaded">
|
||||
<div class="played"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div class="prev"></div>
|
||||
<div class="play"></div>
|
||||
<div class="pause"></div>
|
||||
<div class="next"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="playlist" class="css-scrollbar">
|
||||
<ul class="playlist-tracks"></ul>
|
||||
</div>
|
||||
<div class="additional-controls">
|
||||
<div class="item active" id="repeat">
|
||||
<img src="/images/icns/repeat.png" alt=""/><div class="annotation">Repeat</div>
|
||||
</div>
|
||||
<div class="item" id="shuffle">
|
||||
<img src="/images/icns/shuffle.png" alt=""/><div class="annotation">Shuffle</div>
|
||||
</div>
|
||||
<div class="item" id="empty-playlist">
|
||||
<img src="/images/icns/empty.png" alt=""/><div class="annotation">Empty Playlist</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-container">
|
||||
<div class="hello">
|
||||
<span class="greating"></span>
|
||||
<div class="settings"></div>
|
||||
</div>
|
||||
<ul class="navigation">
|
||||
<li class="logo search">BeatHaven</li>
|
||||
<li class="search">Search</li>
|
||||
<li><a href="https://twitter.com/#!/beat_haven" target="_blank">News</a></li>
|
||||
<li class="vk_auth" id="vk_login">Login</li>
|
||||
<li class="vk_auth" id="vk_logout">Logout</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="data-container" class="css-scrollbar">
|
||||
<div class="inner"></div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<div id="vk_api_transport"></div>
|
||||
<div class="auth_notice"><div class="arrow">↑</div>Don't forget to log in, please. It's simple.</div>
|
||||
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript">var yaParams = {};</script><div style="display:none;"><script type="text/javascript">(function(w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter7596904 = new Ya.Metrika({id:7596904, enableAll: true,params:window.yaParams||{ }}); } catch(e) { } }); })(window, "yandex_metrika_callbacks");</script></div><script src="//mc.yandex.ru/metrika/watch.js" type="text/javascript" defer="defer"></script><noscript><div><img src="//mc.yandex.ru/watch/7596904" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
# Configure barista.
|
||||
Barista.configure do |c|
|
||||
|
||||
# Change the root to use app/scripts
|
||||
c.root = Rails.root.join("app", "coffeescripts")
|
||||
|
||||
# Change the output root, causing Barista to compile into public/coffeescripts
|
||||
c.output_root = Rails.root.join("public", "javascripts", "coffee")
|
||||
#
|
||||
# Disable auto compile, use generated file directly:
|
||||
# c.auto_compile = false
|
||||
|
||||
# Add a new framework:
|
||||
|
||||
# c.register :tests, :root => Rails.root.join('test', 'coffeescript'), :output_prefix => 'test'
|
||||
|
||||
# Disable wrapping in a closure:
|
||||
# c.bare = true
|
||||
# ... or ...
|
||||
# c.bare!
|
||||
|
||||
# Change the output root for a framework:
|
||||
|
||||
# c.change_output_prefix! 'framework-name', 'output-prefix'
|
||||
|
||||
# or for all frameworks...
|
||||
|
||||
# c.each_framework do |framework|
|
||||
# c.change_output_prefix! framework, "vendor/#{framework.name}"
|
||||
# end
|
||||
|
||||
# or, prefix the path for the app files:
|
||||
|
||||
# c.change_output_prefix! :default, 'my-app-name'
|
||||
|
||||
# or, change the directory the framework goes into full stop:
|
||||
|
||||
# c.change_output_prefix! :tests, Rails.root.join('spec', 'javascripts')
|
||||
|
||||
# or, hook into the compilation:
|
||||
|
||||
# c.before_compilation { |path| puts "Barista: Compiling #{path}" }
|
||||
# c.on_compilation { |path| puts "Barista: Successfully compiled #{path}" }
|
||||
# c.on_compilation_error { |path, output| puts "Barista: Compilation of #{path} failed with:\n#{output}" }
|
||||
# c.on_compilation_with_warning { |path, output| puts "Barista: Compilation of #{path} had a warning:\n#{output}" }
|
||||
|
||||
# Turn off preambles and exceptions on failure:
|
||||
|
||||
# c.verbose = false
|
||||
|
||||
# Or, make sure it is always on
|
||||
# c.verbose!
|
||||
|
||||
# If you want to use a custom JS file, you can as well
|
||||
# e.g. vendoring CoffeeScript in your application:
|
||||
# c.js_path = Rails.root.join('public', 'javascripts', 'coffee-script.js')
|
||||
|
||||
# Make helpers and the HAML filter output coffee-script instead of the compiled JS.
|
||||
# Used in combination with the coffeescript_interpreter_js helper in Rails.
|
||||
# c.embedded_interpreter = true
|
||||
|
||||
c.add_preamble = false
|
||||
|
||||
end
|
|
@ -56,6 +56,8 @@ Beathaven::Application.routes.draw do
|
|||
# Note: This route will make all actions in every controller accessible via GET requests.
|
||||
# match ':controller(/:action(/:id(.:format)))'
|
||||
|
||||
match '/' => 'application#index'
|
||||
|
||||
match 'user/auth' => 'user#auth'
|
||||
match 'user/update' => 'user#update'
|
||||
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>BetaHaven</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/css/beathaven.css" />
|
||||
<script type="text/javascript" charset="utf-8" src="/js/jquery/jquery.min.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/jquery/jquery.scroll.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/jquery/jquery.autocomplete.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/jquery/jquery.contentchange.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/jquery/jquery-ui/js/jquery-ui-1.8.13.custom.min.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/jquery/jquery.jplayer.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/beathaven/layout.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/beathaven/vkontakte.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/beathaven/session.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/beathaven/ajax.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/beathaven/search.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/beathaven/settings.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/beathaven/pages.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="/js/beathaven/player.js"></script>
|
||||
<script type="text/javascript" charset="windows-1251" src="http://vkontakte.ru/js/api/openapi.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="player-container">
|
||||
<div class="player">
|
||||
<div id="jplayer"></div>
|
||||
<div class="now-playing">Add some music to playlist</div>
|
||||
<div class="progress">
|
||||
<div class="loaded">
|
||||
<div class="played"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div class="prev"></div>
|
||||
<div class="play"></div>
|
||||
<div class="pause"></div>
|
||||
<div class="next"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="playlist" class="css-scrollbar">
|
||||
<ul class="playlist-tracks"></ul>
|
||||
</div>
|
||||
<div class="additional-controls">
|
||||
<div class="item active" id="repeat">
|
||||
<img src="/images/icns/repeat.png" alt=""/><div class="annotation">Repeat</div>
|
||||
</div>
|
||||
<div class="item" id="shuffle">
|
||||
<img src="/images/icns/shuffle.png" alt=""/><div class="annotation">Shuffle</div>
|
||||
</div>
|
||||
<div class="item" id="empty-playlist">
|
||||
<img src="/images/icns/empty.png" alt=""/><div class="annotation">Empty Playlist</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-container">
|
||||
<div class="hello">
|
||||
<span class="greating"></span>
|
||||
<div class="settings"></div>
|
||||
</div>
|
||||
<ul class="navigation">
|
||||
<li class="logo search">BeatHaven</li>
|
||||
<li class="search">Search</li>
|
||||
<li><a href="https://twitter.com/#!/beat_haven" target="_blank">News</a></li>
|
||||
<li class="vk_auth" id="vk_login">Login</li>
|
||||
<li class="vk_auth" id="vk_logout">Logout</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="data-container" class="css-scrollbar">
|
||||
<div class="inner"></div>
|
||||
</div>
|
||||
|
||||
<div id="vk_api_transport"></div>
|
||||
<div class="auth_notice"><div class="arrow">↑</div>Don't forget to log in, please. It's simple.</div>
|
||||
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript">var yaParams = {};</script><div style="display:none;"><script type="text/javascript">(function(w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter7596904 = new Ya.Metrika({id:7596904, enableAll: true,params:window.yaParams||{ }}); } catch(e) { } }); })(window, "yandex_metrika_callbacks");</script></div><script src="//mc.yandex.ru/metrika/watch.js" type="text/javascript" defer="defer"></script><noscript><div><img src="//mc.yandex.ru/watch/7596904" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,87 @@
|
|||
/* DO NOT MODIFY. This file was compiled Mon, 27 Jun 2011 17:43:40 GMT from
|
||||
* /Users/chez/Sites/beathaven/app/coffeescripts/ajax.coffee
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Ajax;
|
||||
Ajax = (function() {
|
||||
function Ajax() {}
|
||||
Ajax.prototype.referer = false;
|
||||
Ajax.prototype.loadArtistData = function(name) {
|
||||
search.showSpinner();
|
||||
name = name.split(' ').join('+');
|
||||
return $.get('/artist/' + name + '/', function(data) {
|
||||
if (data.status != null) {
|
||||
if (data.status === 'loading') {
|
||||
search.showArtistPics(data.pics);
|
||||
return setTimeout(function() {
|
||||
return this.loadArtistData(name);
|
||||
}, 3000);
|
||||
} else if (data.status === 'corrected') {
|
||||
return ajax.loadArtistData(data.page);
|
||||
} else if (data.status === 'suggestions') {
|
||||
search.hideSpinner();
|
||||
return search.showSuggestions(data.values);
|
||||
} else if (data.status === 'loading_failed') {
|
||||
search.hideSpinner();
|
||||
return search.showError();
|
||||
}
|
||||
} else {
|
||||
this.setArchor('/artist/' + name + '/');
|
||||
pages.renderArtist(data);
|
||||
return beathaven.redrawScrollbar();
|
||||
}
|
||||
});
|
||||
};
|
||||
Ajax.prototype.loadSearchPage = function() {
|
||||
return $.get('/templates/search.html', function(data) {
|
||||
this.setArchor('/search/');
|
||||
return pages.renderSearch(data);
|
||||
});
|
||||
};
|
||||
Ajax.prototype.loadSettingsPage = function() {
|
||||
return $.get('/templates/settings.html', function(data) {
|
||||
this.setArchor('/settings/');
|
||||
return pages.renderSettings(data);
|
||||
});
|
||||
};
|
||||
Ajax.prototype.load404Page = function() {
|
||||
return $.get('/404.html', function(data) {
|
||||
$('.data-container .inner').html(data);
|
||||
return beathaven.redrawScrollbar();
|
||||
});
|
||||
};
|
||||
Ajax.prototype.setArchor = function(anchor) {
|
||||
this.referer = this.getAnchor();
|
||||
return window.location.hash = '#' + anchor;
|
||||
};
|
||||
Ajax.prototype.getAnchor = function() {
|
||||
return window.location.hash.substring(1);
|
||||
};
|
||||
Ajax.prototype.setTitle = function(title) {
|
||||
return document.title = title + ' @ BeatHaven';
|
||||
};
|
||||
Ajax.prototype.detectPage = function() {
|
||||
var m;
|
||||
if (m = this.getAnchor().match(/\/artist\/(.+)\//)) {
|
||||
return this.loadArtistData(m[1]);
|
||||
} else if (this.getAnchor() === '' || Ajax.getAnchor().match(/\/search\//)) {
|
||||
return this.loadSearchPage();
|
||||
} else if (this.getAnchor().match(/\/settings\//)) {
|
||||
return this.loadSearchPage();
|
||||
} else {
|
||||
return this.load404Page();
|
||||
}
|
||||
};
|
||||
return Ajax;
|
||||
})();
|
||||
$(function() {
|
||||
$('a.data.artist').live('click', function() {
|
||||
ajax.loadArtistData($(this).html());
|
||||
return false;
|
||||
});
|
||||
return $(window).bind('hashchange', function() {
|
||||
return ajax.detectPage();
|
||||
});
|
||||
});
|
||||
}).call(this);
|
|
@ -0,0 +1,95 @@
|
|||
/* DO NOT MODIFY. This file was compiled Mon, 27 Jun 2011 17:49:39 GMT from
|
||||
* /Users/chez/Sites/beathaven/app/coffeescripts/beathaven.coffee
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var BeatHaven;
|
||||
$(function() {
|
||||
var ajax, beathaven, l, pages, player, search, session, settings, vkontakte, _ref;
|
||||
l = document.location;
|
||||
if ((_ref = l.host) !== 'beathaven.org' && _ref !== 'localhost') {
|
||||
l.href = 'http://beathaven.org/' + l.hash;
|
||||
}
|
||||
beathaven = new BeatHaven();
|
||||
vkontakte = new Vkontakte(l.host === 'beathaven.org' ? 2335068 : 2383163);
|
||||
session = new Session();
|
||||
ajax = new Ajax();
|
||||
player = new Player();
|
||||
search = new Search();
|
||||
pages = new Pages();
|
||||
settings = new Settings();
|
||||
beathaven.init();
|
||||
vkontakte.init();
|
||||
$(window).resize(function() {
|
||||
return beathaven.adjustSizes();
|
||||
});
|
||||
return window.setTimeout(function() {
|
||||
return beathaven.checkRedrawScrollbar();
|
||||
}, 500);
|
||||
});
|
||||
BeatHaven = (function() {
|
||||
function BeatHaven() {}
|
||||
BeatHaven.prototype.last_height = false;
|
||||
BeatHaven.prototype.init = function() {
|
||||
this.drawInterface();
|
||||
this.adjustSizes();
|
||||
return ajax.detectPage();
|
||||
};
|
||||
BeatHaven.prototype.adjustSizes = function() {
|
||||
$('.data-container').height($(window).height() - $('.header-container').height());
|
||||
$('.data-container').width($(window).width() - $('.player').width());
|
||||
$('.player-container').height($(window).height());
|
||||
$('.playlist').height($(window).height() - $('.player').height() - $('.player-container .additional-controls').height());
|
||||
$('.data-container').scrollbar();
|
||||
return $('.playlist').scrollbar();
|
||||
};
|
||||
BeatHaven.prototype.checkRedrawScrollbar = function() {
|
||||
var focused_id, outer_height;
|
||||
focused_id = false;
|
||||
if (document.activeElement.id != null) {
|
||||
focused_id = document.activeElement.id;
|
||||
}
|
||||
outer_height = $('.data-container > div').outerHeight();
|
||||
if (outer_height > 300 && outer_height !== this.last_height) {
|
||||
this.last_height = outer_height;
|
||||
this.redrawScrollbar();
|
||||
}
|
||||
if (focused_id) {
|
||||
document.getElementById(focused_id).focus();
|
||||
focused_id = false;
|
||||
}
|
||||
return window.setTimeout(function() {
|
||||
return beathaven.checkRedrawScrollbar();
|
||||
}, 500);
|
||||
};
|
||||
BeatHaven.prototype.redrawScrollbar = function() {
|
||||
$('.data-container').html($('.data-container').find('.inner').first());
|
||||
return $('.data-container').scrollbar();
|
||||
};
|
||||
return BeatHaven;
|
||||
})();
|
||||
String.prototype.htmlsafe = function() {
|
||||
var item, replaces, str, _i, _len;
|
||||
replaces = [["\\", "\\\\"], ["\"", """], ["<", "<"], [">", ">"]];
|
||||
str = this;
|
||||
for (_i = 0, _len = replaces.length; _i < _len; _i++) {
|
||||
item = replaces[_i];
|
||||
str = str.replace(item[0], item[1]);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
String.prototype.trim = function() {
|
||||
var str;
|
||||
str = this;
|
||||
while (str.indexOf(' ') !== -1) {
|
||||
str = str.replace(' ', ' ');
|
||||
}
|
||||
if (str.charAt(0) === ' ') {
|
||||
str = str.substring(1);
|
||||
}
|
||||
if (str.charAt(str.length - 1) === ' ') {
|
||||
str = str.substring(0, str.length - 1);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
}).call(this);
|
|
@ -0,0 +1,96 @@
|
|||
/* DO NOT MODIFY. This file was compiled Mon, 27 Jun 2011 17:49:39 GMT from
|
||||
* /Users/chez/Sites/beathaven/app/coffeescripts/pages.coffee
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Pages;
|
||||
Pages = (function() {
|
||||
function Pages() {}
|
||||
Pages.prototype.renderArtist = function(data) {
|
||||
var albums_info, artist_info;
|
||||
artist_info = $('\
|
||||
<div class="artist-info">\
|
||||
<div class="pic">\
|
||||
<img src="' + data.artist.pic + '" alt="' + data.artist.name + '" width="250" />\
|
||||
</div>\
|
||||
<h1 class="name">' + data.artist.name + '</h1>\
|
||||
<div class="info">\
|
||||
' + data.artist.desc + '\
|
||||
</div>\
|
||||
</div>');
|
||||
albums_info = $('<div class="albums"></div>');
|
||||
$.each(data.albums, function(i, album) {
|
||||
var album_info;
|
||||
if (album.year != null) {
|
||||
album_info = $('\
|
||||
<div class="album">\
|
||||
<h2 class="name">' + album.name + ' (' + album.year + ')</h2>\
|
||||
<div class="pic">\
|
||||
<img src="' + (album.pic ? album.pic : '/images/kitteh.png') + '" alt="' + album.name + ' by ' + data.artist.name + '" width="250" height="250"/>\
|
||||
<div class="add-album-button-container">\
|
||||
<div class="add-album button gray">Add to Now Playing</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="tracklist"><ul></ul></div>\
|
||||
</div>\
|
||||
<div class="kaboom"></div>');
|
||||
$.each(album.tracks.album, function(i, track) {
|
||||
var track_info;
|
||||
track_info = $('\
|
||||
<li>\
|
||||
<div class="add-track button gray">+</div>\
|
||||
<div class="track-container">\
|
||||
<div class="fade"></div>\
|
||||
<span class="index">' + (i + 1) + '</span>\
|
||||
<div class="trackname" title="' + track.name.htmlsafe() + '">' + track.name + '</div>\
|
||||
<div class="length">' + track.duration + '</div>\
|
||||
</div>\
|
||||
</li>');
|
||||
return $(album_info).find('.tracklist ul').append(track_info);
|
||||
});
|
||||
return $(albums_info).append(album_info);
|
||||
}
|
||||
});
|
||||
$('.data-container').css({
|
||||
backgroundImage: 'none'
|
||||
});
|
||||
$('.data-container .inner').html('').append(artist_info).append(albums_info);
|
||||
yaCounter7596904.hit(ajax.getAnchor(), data.artist.name, ajax.referer);
|
||||
return ajax.setTitle(data.artist.name);
|
||||
};
|
||||
Pages.prototype.renderSearch = function(data) {
|
||||
$('.data-container').css({
|
||||
background: 'url(/images/concrete_wall_2.png) 0 -30px repeat'
|
||||
});
|
||||
$('.data-container .inner').html(data);
|
||||
$('.search-container').css('marginLeft', ($('.data-container').width() - 425) / 2 + 'px').css('marginTop', ($('.data-container').height() / 2 - 230) + 'px').height(($('.data-container').height() - $('#search_form').height()) / 2);
|
||||
setTimeout(function() {
|
||||
$('#search_field').bh_autocomplete({
|
||||
serviceUrl: '/artist/autocomplete',
|
||||
minChars: 2,
|
||||
delimiter: /(,|;)\s*/,
|
||||
maxHeight: 400,
|
||||
width: 415,
|
||||
zIndex: 9999,
|
||||
deferRequestBy: 500,
|
||||
onSelect: function() {
|
||||
return ajax.loadArtistData();
|
||||
}
|
||||
});
|
||||
return $('#search_field').focus();
|
||||
}, 501);
|
||||
yaCounter7596904.hit(ajax.getAnchor(), 'Artist Search', ajax.referer);
|
||||
return ajax.setTitle('Artist Search');
|
||||
};
|
||||
Pages.prototype.renderSettings = function(data) {
|
||||
$('.data-container').css({
|
||||
background: 'none'
|
||||
});
|
||||
$('.data-container .inner').html(data);
|
||||
yaCounter7596904.hit(ajax.getAnchor(), 'Settings', ajax.referer);
|
||||
ajax.setTitle('Settings');
|
||||
return $('.settings-container .tabs .tab').first().trigger('click');
|
||||
};
|
||||
return Pages;
|
||||
})();
|
||||
}).call(this);
|
|
@ -0,0 +1,285 @@
|
|||
/* DO NOT MODIFY. This file was compiled Mon, 27 Jun 2011 17:49:39 GMT from
|
||||
* /Users/chez/Sites/beathaven/app/coffeescripts/player.coffee
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Player;
|
||||
Player = (function() {
|
||||
function Player() {}
|
||||
Player.prototype.bar_width = 330;
|
||||
Player.prototype.jp = null;
|
||||
Player.prototype.scrobbled = false;
|
||||
Player.prototype.initJplayer = function() {
|
||||
var self;
|
||||
self = this;
|
||||
this.jp = $("#jplayer");
|
||||
this.jp.jPlayer({
|
||||
swfPath: "/js",
|
||||
supplied: "mp3",
|
||||
cssSelectorAncestor: "",
|
||||
cssSelector: {
|
||||
play: "#player .play",
|
||||
pause: "#player .pause",
|
||||
stop: "",
|
||||
videoPlay: "",
|
||||
seekBar: "",
|
||||
playBar: "",
|
||||
mute: "",
|
||||
unmute: "",
|
||||
volumeBar: "",
|
||||
volumeBarValue: "",
|
||||
currentTime: "",
|
||||
duration: ""
|
||||
}
|
||||
});
|
||||
this.jp.bind($.jPlayer.event.timeupdate, function(e) {
|
||||
var $obj, data;
|
||||
data = e.jPlayer.status;
|
||||
if (!Player.scrobbled && data.currentPercentAbsolute > 50) {
|
||||
$obj = $('.playlist-tracks li.now');
|
||||
self.scrobble($obj.attr('data-artist'), $obj.attr('data-album'), $obj.attr('data-track'));
|
||||
Player.scrobbled = true;
|
||||
}
|
||||
$('#player .progress .loaded').width(data.seekPercent * self.bar_width / 100);
|
||||
return $('#player .progress .played').width(data.currentPercentAbsolute * self.bar_width / 100);
|
||||
});
|
||||
this.jp.bind($.jPlayer.event.ended, function(e) {
|
||||
var next;
|
||||
next = self.nextTrack();
|
||||
if (!next) {
|
||||
$('#jplayer').jPlayer('clearMedia');
|
||||
$('#player .now-playing').html('Nothing left to <strike>lose</strike> play');
|
||||
$('#player .loaded, #player .played').width(0);
|
||||
return $('.playlist-tracks li').removeClass('now');
|
||||
} else {
|
||||
return self.setTrack(next);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
};
|
||||
Player.prototype.addTrack = function(artist, album, track, length, autoplay) {
|
||||
var initial_count;
|
||||
if (!(autoplay != null)) {
|
||||
autoplay = false;
|
||||
}
|
||||
initial_count = $('.playlist-tracks li').length;
|
||||
$('.playlist-tracks').append('\
|
||||
<li id="i' + Math.round(Math.random() * 999999) + '" data-artist="' + artist.trim() + '" data-album="' + album.trim() + '" data-track="' + track.trim() + '" data-length="' + length + '">\
|
||||
<div class="item">\
|
||||
<div class="fade"></div>\
|
||||
<span class="title" title="' + artist.htmlsafe() + ' &mdash ' + track.htmlsafe() + '">' + artist + ' &mdash ' + track + '</span>\
|
||||
<span class="duration">' + length + '</span>\
|
||||
<div class="remove">remove</div>\
|
||||
</div>\
|
||||
</li>');
|
||||
$('#playlist').html($('.playlist-tracks')).scrollbar();
|
||||
$('.playlist-tracks').sortable();
|
||||
if (autoplay) {
|
||||
return Player.setTrack($('.playlist-tracks li').last().attr('id').split('i')[1]);
|
||||
} else if (initial_count === 0 && !Player.hasTrack()) {
|
||||
return Player.setTrack($('.playlist-tracks li').first().attr('id').split('i')[1]);
|
||||
}
|
||||
};
|
||||
Player.prototype.setTrack = function(id) {
|
||||
var $obj, query;
|
||||
$obj = $('#i' + id);
|
||||
query = $obj.attr('data-artist') + ' &mdash ' + $obj.attr('data-track');
|
||||
$('#player .now-playing').html(query + '<div class="fade"></div>');
|
||||
$('.playlist-tracks li').removeClass('now');
|
||||
$obj.addClass('now');
|
||||
$('#player .loaded, #player .played').width(0);
|
||||
vkontakte.loadTracksData($obj.attr('data-artist'), $obj.attr('data-track'), $obj.attr('data-length'), function() {
|
||||
return player.playSource();
|
||||
});
|
||||
return this.updateNowListening($obj.attr('data-artist'), $obj.attr('data-album'), $obj.attr('data-track'));
|
||||
};
|
||||
Player.prototype.hasTrack = function() {
|
||||
if ($('#jplayer audio').length > 0) {
|
||||
return $('#jplayer audio').attr('src') != null;
|
||||
} else if ($('#jplayer object').length > 0) {
|
||||
$('#jplayer').jPlayer('play');
|
||||
true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Player.prototype.playSource = function(url) {
|
||||
$('#jplayer').jPlayer('setMedia', {
|
||||
mp3: url
|
||||
});
|
||||
$('#jplayer').jPlayer('play');
|
||||
return this.scrobbled = false;
|
||||
};
|
||||
Player.prototype.nextTrack = function(manual) {
|
||||
var $li, cnt, rnd;
|
||||
manual = manual != null;
|
||||
cnt = $('.playlist-tracks li').length;
|
||||
if (!this.onShuffle()) {
|
||||
if ($('.playlist-tracks .now').next().length === 0) {
|
||||
if (Player.onRepeat() || manual) {
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1];
|
||||
} else {
|
||||
false;
|
||||
}
|
||||
} else {
|
||||
return $('.playlist-tracks .now').next().attr('id').split('i')[1];
|
||||
}
|
||||
} else if (cnt === 1) {
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1];
|
||||
} else {
|
||||
while (true) {
|
||||
rnd = Math.floor(Math.random() * (cnt + .999));
|
||||
$li = $('.playlist-tracks li').eq(rnd);
|
||||
if ($li.length > 0 && !$li.hasClass('now')) {
|
||||
return $li.attr('id').split('i')[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Player.prototype.prevTrack = function() {
|
||||
var $li, cnt, rnd;
|
||||
cnt = $('.playlist-tracks li').length;
|
||||
if (!Player.onShuffle()) {
|
||||
if ($('.playlist-tracks .now').prev().length === 0) {
|
||||
return $('.playlist-tracks li').last().attr('id').split('i')[1];
|
||||
} else {
|
||||
return $('.playlist-tracks .now').prev().attr('id').split('i')[1];
|
||||
}
|
||||
} else if (cnt === 1) {
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1];
|
||||
} else {
|
||||
while (true) {
|
||||
rnd = Math.floor(Math.random() * (cnt + .999));
|
||||
$li = $('.playlist-tracks li').eq(rnd);
|
||||
if ($li.length > 0 && !$li.hasClass('now')) {
|
||||
return $li.attr('id').split('i')[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Player.prototype.onShuffle = function() {
|
||||
return $('#shuffle').hasClass('active');
|
||||
};
|
||||
Player.prototype.onRepeat = function() {
|
||||
return $('#repeat').hasClass('active');
|
||||
};
|
||||
Player.prototype.updateNowListening = function(artist, album, track) {
|
||||
if (session.user.lastfm_username) {
|
||||
return session.query('/lastfm/listening?r=' + Math.random(), {
|
||||
artist: artist,
|
||||
album: album,
|
||||
track: track
|
||||
});
|
||||
}
|
||||
};
|
||||
Player.prototype.scrobble = function(artist, album, track) {
|
||||
if (session.user.lastfm_username) {
|
||||
return session.query('/lastfm/scrobble?r=' + Math.random(), {
|
||||
artist: artist,
|
||||
album: album,
|
||||
track: track
|
||||
});
|
||||
}
|
||||
};
|
||||
return Player;
|
||||
})();
|
||||
$(function() {
|
||||
return player.initJplayer();
|
||||
});
|
||||
$('#player .controls .prev').live('click', function() {
|
||||
Player.setTrack(Player.prevTrack());
|
||||
return false;
|
||||
});
|
||||
$('#player .controls .next').live('click', function() {
|
||||
Player.setTrack(Player.nextTrack(true));
|
||||
return false;
|
||||
});
|
||||
$('#player .play').live('click', function() {
|
||||
if ($('.playlist-tracks li').length > 0 && !Player.hasTrack()) {
|
||||
player.setTrack($('.playlist-tracks li').first().attr('id').split('i')[1]);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('#player .progress').live('click', function(e) {
|
||||
$('#jplayer').jPlayer('playHead', Math.round((e.offsetX / Player.bar_width) * 100));
|
||||
return false;
|
||||
});
|
||||
$('#repeat, #shuffle').live('click', function() {
|
||||
$(this).toggleClass('active');
|
||||
return false;
|
||||
});
|
||||
$('#empty-playlist').live('click', function() {
|
||||
if (confirm('Are you sure?')) {
|
||||
$('.playlist-tracks li').remove();
|
||||
$('#jplayer').jPlayer('clearMedia');
|
||||
$('#player .now-playing').text('Add some music to playlist');
|
||||
$('#player .loaded, #player .played').width(0);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('.playlist-tracks li .fade, .playlist-tracks li .duration, .playlist-tracks li .remove').live('mouseover mouseout', function(e) {
|
||||
if (e.type === 'mouseover') {
|
||||
$(this).parent().find('.duration').hide();
|
||||
$(this).parent().find('.remove').show();
|
||||
} else {
|
||||
$(this).parent().find('.remove').hide();
|
||||
$(this).parent().find('.duration').show();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('.playlist-tracks li .remove').live('click', function() {
|
||||
var $li;
|
||||
$li = $(this).parent().parent();
|
||||
if ($li.hasClass('now')) {
|
||||
$('#jplayer').jPlayer('clearMedia');
|
||||
$('#player .now-playing').text('...');
|
||||
$('#player .loaded, #player .played').width(0);
|
||||
}
|
||||
$li.remove();
|
||||
return false;
|
||||
});
|
||||
$('.playlist-tracks li').live('dblclick', function() {
|
||||
player.setTrack($(this).attr('id').split('i')[1]);
|
||||
return false;
|
||||
});
|
||||
$('.add-album').live('click', function() {
|
||||
var album, artist, item, length, track_name, _i, _len, _ref;
|
||||
artist = $('.artist-info .name').html();
|
||||
album = $(this).parent().parent().parent().find('h2.name').text().replace(/\s\([\d]{4}\)$/, '');
|
||||
_ref = $(this).parent().parent().parent().find('.tracklist li');
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
item = _ref[_i];
|
||||
track_name = $(item).find('.trackname').html();
|
||||
length = $(item).find('.length').html();
|
||||
Player.addTrack(artist, album, track_name, length);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('.add-track').live('click', function() {
|
||||
var album, artist, length, track_name;
|
||||
artist = $('.artist-info .name').html();
|
||||
album = $(this).parent().parent().parent().parent().find('h2.name').text().replace(/\s\([\d]{4}\)$/, '');
|
||||
track_name = $(this).parent().find('.trackname').html();
|
||||
length = $(this).parent().find('.length').html();
|
||||
Player.addTrack(artist, album, track_name, length);
|
||||
return false;
|
||||
});
|
||||
$('.tracklist li').live('mouseover mouseout', function(e) {
|
||||
if (e.type === 'mouseover') {
|
||||
$(this).find('.add-track').show();
|
||||
} else {
|
||||
$(this).find('.add-track').hide();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('.tracklist li').live('dblclick', function(e) {
|
||||
var album, artist, length, track_name;
|
||||
artist = $('.artist-info .name').html();
|
||||
album = $(this).parent().parent().parent().find('h2.name').text().replace(/\s\([\d]{4}\)$/, '');
|
||||
track_name = $(this).find('.trackname').html();
|
||||
length = $(this).find('.length').html();
|
||||
Player.addTrack(artist, album, track_name, length, true);
|
||||
return false;
|
||||
});
|
||||
}).call(this);
|
|
@ -0,0 +1,81 @@
|
|||
/* DO NOT MODIFY. This file was compiled Mon, 27 Jun 2011 17:49:39 GMT from
|
||||
* /Users/chez/Sites/beathaven/app/coffeescripts/search.coffee
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Search;
|
||||
Search = (function() {
|
||||
function Search() {}
|
||||
Search.prototype.pics = [];
|
||||
Search.prototype.showSpinner = function() {
|
||||
$('.search-container input').attr({
|
||||
disabled: 'disabled'
|
||||
}).blur();
|
||||
$('.search-container img').show();
|
||||
$('.autocomplete-container').hide();
|
||||
$('.artist_loading.failed').hide();
|
||||
this.hideSuggestions();
|
||||
return false;
|
||||
};
|
||||
Search.prototype.hideSpinner = function() {
|
||||
$('.search-container input').removeAttr('disabled');
|
||||
$('.search_field').focus();
|
||||
$('.search-container img').hide();
|
||||
return false;
|
||||
};
|
||||
Search.prototype.showSuggestions = function(values) {
|
||||
var item, _i, _len;
|
||||
for (_i = 0, _len = values.length; _i < _len; _i++) {
|
||||
item = values[_i];
|
||||
$('.suggestions ul').append('\
|
||||
<li>\
|
||||
<a class="data artist">' + item.name + '</a>\
|
||||
' + (item.desc ? '<br/><span>' + item.desc(+'</span>') : '') + '\
|
||||
</li>');
|
||||
}
|
||||
$('.suggestions').show();
|
||||
return false;
|
||||
};
|
||||
Search.prototype.hideSuggestions = function() {
|
||||
$('.suggestions ul li').remove();
|
||||
$('.suggestions').hide();
|
||||
return false;
|
||||
};
|
||||
Search.prototype.showArtistPics = function(pics) {
|
||||
var pic, _i, _len;
|
||||
$('.artist_loading.ok, .artist_pics').show();
|
||||
for (_i = 0, _len = pics.length; _i < _len; _i++) {
|
||||
pic = pics[_i];
|
||||
if (this.pics.indexOf(pic) === -1) {
|
||||
this.pics.push(pic);
|
||||
$('.artist_pics').append('\
|
||||
<div class="pic">\
|
||||
<img src="' + pic + '" alt=""/>\
|
||||
</div>');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Search.prototype.showError = function() {
|
||||
$('.artist_loading.ok, .artist_pics').hide();
|
||||
$('.artist_loading.failed').show();
|
||||
return this.pics = [];
|
||||
};
|
||||
return Search;
|
||||
})();
|
||||
$(function() {
|
||||
$('.search').live('click', function() {
|
||||
ajax.loadSearchPage();
|
||||
return false;
|
||||
});
|
||||
$('#search_form').live('submit', function() {
|
||||
$('.autocomplete-container').remove();
|
||||
ajax.loadArtistData($('#search_field').val());
|
||||
return false;
|
||||
});
|
||||
return $('.suggestions a').live('click', function() {
|
||||
$('#search_field').val($(this).text());
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}).call(this);
|
|
@ -0,0 +1,34 @@
|
|||
/* DO NOT MODIFY. This file was compiled Mon, 27 Jun 2011 17:49:39 GMT from
|
||||
* /Users/chez/Sites/beathaven/app/coffeescripts/session.coffee
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Session;
|
||||
Session = (function() {
|
||||
Session.prototype.vk_params = null;
|
||||
Session.prototype.user = null;
|
||||
function Session(vk_params) {
|
||||
this.vk_params = vk_params;
|
||||
}
|
||||
Session.prototype.query = function(url, params, callback) {
|
||||
var attr, q_params, _i, _len;
|
||||
q_params = this.vk_params;
|
||||
for (_i = 0, _len = params.length; _i < _len; _i++) {
|
||||
attr = params[_i];
|
||||
q_params[attr] = params[attr];
|
||||
}
|
||||
$.post(url, q_params, callback);
|
||||
return false;
|
||||
};
|
||||
Session.prototype.setVkParams = function(params) {
|
||||
var attrs, key, _i, _len;
|
||||
attrs = ['expire', 'mid', 'secret', 'sid', 'sig'];
|
||||
for (_i = 0, _len = attrs.length; _i < _len; _i++) {
|
||||
key = attrs[_i];
|
||||
this.vk_params[key] = params[key];
|
||||
}
|
||||
return false;
|
||||
};
|
||||
return Session;
|
||||
})();
|
||||
}).call(this);
|
|
@ -0,0 +1,54 @@
|
|||
/* DO NOT MODIFY. This file was compiled Mon, 27 Jun 2011 14:00:02 GMT from
|
||||
* /Users/chez/Sites/beathaven/app/coffeescripts/settings.coffee
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Settings;
|
||||
Settings = (function() {
|
||||
function Settings() {}
|
||||
Settings.prototype.getAccountInfo = function(callback) {
|
||||
return session.query('/user/update/', {}, callback);
|
||||
};
|
||||
Settings.prototype.saveAccountInfo = function(params, callback) {
|
||||
return session.query('/user/update', params, callback);
|
||||
};
|
||||
Settings.prototype.loadFormData = function(form) {
|
||||
if (form === 'account') {
|
||||
$('.settings-container .form input[name$="username"]').val(session.user.name);
|
||||
return $('.settings-container .form input[name$="email"]').val(session.email);
|
||||
} else if (form === 'lastfm') {
|
||||
if (this.user.lastfm_username) {
|
||||
return $('.form-container input[name$="username"]').first().val(session.lastfm_username);
|
||||
}
|
||||
}
|
||||
};
|
||||
return Settings;
|
||||
})();
|
||||
$('.settings').live('click', function() {
|
||||
return ajax.loadSettingsPage();
|
||||
});
|
||||
$('.settings-container .tabs .tab').live('click', function() {
|
||||
if ($(this).hasClass('active')) {
|
||||
$('.settings-container .tabs .tab').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
$('.form-container').html($('.forms .' + $(this).attr('data-fieldset')).html());
|
||||
return settings.loadFormData($(this).attr('data-fieldset'));
|
||||
}
|
||||
});
|
||||
$('.lastfm-connect').live('click', function() {
|
||||
return window.open(session.user.lastfm_login_url);
|
||||
});
|
||||
$('.settings-container .form input').live('blur', function() {
|
||||
var active_tab, params;
|
||||
active_tab = $('.settings-container .tabs .tab.active').attr('data-fieldset');
|
||||
if (active_tab === 'account') {
|
||||
params = {
|
||||
username: $('.settings-container .form input[name$="username"]').first().val(),
|
||||
email: $('.settings-container .form input[name$="email"]').first().val()
|
||||
};
|
||||
return settings.saveAccountInfo(params, function() {
|
||||
return $('#header-container .hello .greating').text('Hi there, ' + (params.username.length > 0 ? params.username : '%username%') + '!');
|
||||
});
|
||||
}
|
||||
});
|
||||
}).call(this);
|
|
@ -0,0 +1,121 @@
|
|||
/* DO NOT MODIFY. This file was compiled Mon, 27 Jun 2011 17:49:39 GMT from
|
||||
* /Users/chez/Sites/beathaven/app/coffeescripts/vkontakte.coffee
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Vkontakte;
|
||||
Vkontakte = (function() {
|
||||
Vkontakte.prototype.qr = [];
|
||||
function Vkontakte(api_id) {
|
||||
this.api_id = api_id;
|
||||
}
|
||||
Vkontakte.prototype.init = function() {
|
||||
VK.init({
|
||||
apiId: this.api_id,
|
||||
nameTransportPath: '/xd_receiver.html'
|
||||
});
|
||||
return VK.Auth.getLoginStatus(this.authInfo);
|
||||
};
|
||||
Vkontakte.prototype.authInfo = function(response) {
|
||||
if (typeof response !== 'undefined' && response.session) {
|
||||
session.setVkParams(response.session);
|
||||
$('#vk_login, .auth_notice').hide();
|
||||
$('#vk_logout').css({
|
||||
display: 'block'
|
||||
});
|
||||
if ($('#search_field').length > 0) {
|
||||
$('#search_field').focus();
|
||||
}
|
||||
return session.query('/user/auth', {}, function(ar) {
|
||||
if (ar.newbie) {
|
||||
VK.Api.call('getVariable', {
|
||||
key: 1281
|
||||
}, function(r) {
|
||||
return Session.query('/user/update', {
|
||||
name: r.response
|
||||
}, function(ar2) {
|
||||
session.user = ar2.user;
|
||||
return $('#header-container .hello .greating').text('Hi there, ' + (session.user.name ? session.user.name : '%username%') + '!');
|
||||
});
|
||||
});
|
||||
} else {
|
||||
session.user = ar.user;
|
||||
}
|
||||
return $('#header-container .hello .greating').text('Hi there, ' + (session.user.name ? session.user.name : '%username%') + '!');
|
||||
});
|
||||
} else {
|
||||
$('#vk_login, .auth_notice').css({
|
||||
display: 'block'
|
||||
});
|
||||
return $('#vk_logout').hide();
|
||||
}
|
||||
};
|
||||
Vkontakte.prototype.loadTracksData = function(artist, track, duration, callback) {
|
||||
var query, track_prepared;
|
||||
track_prepared = track.replace(/\(.*\)/i, '').split('/')[0];
|
||||
query = artist(+' ' + track_prepared);
|
||||
if (this.qr[query] != null) {
|
||||
return callback(this.qr[query]);
|
||||
} else {
|
||||
return VK.Api.call('audio.search', {
|
||||
q: query
|
||||
}, function(r) {
|
||||
var url;
|
||||
url = this.matchPerfectResult(r.response, artist, track, duration);
|
||||
this.qr[query] = url;
|
||||
return callback(url);
|
||||
});
|
||||
}
|
||||
};
|
||||
Vkontakte.prototype.matchPerfectResult = function(data, artist, track, duration) {
|
||||
var best_result, best_score, delta, item, score, _i, _len;
|
||||
duration = duration.split(':');
|
||||
duration = parseInt(duration[0], 10) * 60 + parseInt(duration[1], 10);
|
||||
best_score = 0;
|
||||
best_result = null;
|
||||
for (_i = 0, _len = data.length; _i < _len; _i++) {
|
||||
item = data[_i];
|
||||
score = 0;
|
||||
item.artist = item.artist.trim();
|
||||
item.title = item.title.trim();
|
||||
if (item.artist === artist) {
|
||||
score += 10;
|
||||
} else if (item.artist.split(artist).length === 2) {
|
||||
score += 5;
|
||||
} else if (item.title.split(artist).length === 2) {
|
||||
score += 4;
|
||||
}
|
||||
if (item.title === track) {
|
||||
score += 10;
|
||||
} else if (item.title.split(track).length === 2) {
|
||||
score += 5;
|
||||
}
|
||||
if (parseInt(item.duration, 10) === duration) {
|
||||
score += 15;
|
||||
} else {
|
||||
delta = Math.abs(parseInt(item.duration, 10) - duration);
|
||||
if (delta < 10) {
|
||||
score += 10 - delta;
|
||||
}
|
||||
}
|
||||
if (score > best_score) {
|
||||
best_score = score;
|
||||
best_result = item;
|
||||
}
|
||||
if (score === 35) {
|
||||
return best_result.url;
|
||||
}
|
||||
}
|
||||
return best_result.url;
|
||||
};
|
||||
return Vkontakte;
|
||||
})();
|
||||
$(function() {
|
||||
$('#vk_login').click(function() {
|
||||
return VK.Auth.login(vkontakte.authInfo, 8);
|
||||
});
|
||||
return $('#vk_logout').click(function() {
|
||||
return VK.Auth.logout(vkontakte.authInfo);
|
||||
});
|
||||
});
|
||||
}).call(this);
|
|
@ -1,87 +0,0 @@
|
|||
var Ajax = {
|
||||
|
||||
referer: false,
|
||||
|
||||
loadArtistData: function(name) {
|
||||
Search.showSpinner();
|
||||
name = name.split(' ').join('+');
|
||||
$.get('/artist/'+ name +'/', function(data){
|
||||
if (typeof data.status != 'undefined') {
|
||||
if (data.status == 'loading') {
|
||||
Search.showArtistPics(data.pics);
|
||||
setTimeout(function() {
|
||||
Ajax.loadArtistData(name);
|
||||
}, 3000);
|
||||
} else if (data.status == 'corrected') {
|
||||
Ajax.loadArtistData(data.page);
|
||||
} else if (data.status == 'suggestions') {
|
||||
Search.hideSpinner();
|
||||
Search.showSuggestions(data.values);
|
||||
} else if (data.status == 'loading_failed') {
|
||||
Search.hideSpinner();
|
||||
Search.showError();
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
Ajax.setArchor('/artist/'+ name +'/');
|
||||
Pages.renderArtist(data);
|
||||
beathaven.redrawScrollbar();
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
loadSearchPage: function() {
|
||||
$.get('/templates/search.html', function(data){
|
||||
Ajax.setArchor('/search/');
|
||||
Pages.renderSearch(data);
|
||||
})
|
||||
},
|
||||
|
||||
loadSettingsPage: function() {
|
||||
$.get('/templates/settings.html', function(data){
|
||||
Ajax.setArchor('/settings/');
|
||||
Pages.renderSettings(data);
|
||||
})
|
||||
},
|
||||
|
||||
load404Page: function() {
|
||||
$.get('/404.html', function(data){
|
||||
$('.data-container .inner').html(data);
|
||||
beathaven.redrawScrollbar();
|
||||
})
|
||||
},
|
||||
|
||||
setArchor: function(anchor) {
|
||||
Ajax.referer = Ajax.getAnchor();
|
||||
window.location.hash = '#'+ anchor;
|
||||
},
|
||||
|
||||
getAnchor: function() {
|
||||
return window.location.hash.substring(1);
|
||||
},
|
||||
|
||||
setTitle: function(title) {
|
||||
document.title = title +' @ BeatHaven';
|
||||
},
|
||||
|
||||
detectPage: function() {
|
||||
if (m = Ajax.getAnchor().match(/\/artist\/(.+)\//)) {
|
||||
Ajax.loadArtistData(m[1]);
|
||||
} else if (Ajax.getAnchor() === '' || Ajax.getAnchor().match(/\/search\//)) {
|
||||
Ajax.loadSearchPage();
|
||||
} else if (Ajax.getAnchor().match(/\/settings\//)) {
|
||||
Ajax.loadSearchPage();
|
||||
} else {
|
||||
Ajax.load404Page();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(function(){
|
||||
$('a.data.artist').live('click', function(){
|
||||
Ajax.loadArtistData($(this).html());
|
||||
return false;
|
||||
});
|
||||
//$(window).bind('hashchange', Ajax.detectPage);
|
||||
})
|
|
@ -1,80 +0,0 @@
|
|||
$(function(){
|
||||
if (document.location.host != 'beathaven.org' && document.location.host != 'localhost') {
|
||||
document.location.href = 'http://beathaven.org/'+ document.location.hash;
|
||||
}
|
||||
beathaven.init();
|
||||
$(window).resize(beathaven.adjustSizes)
|
||||
window.setTimeout(beathaven.checkRedrawScrollbar, 500);
|
||||
})
|
||||
var beathaven = {
|
||||
|
||||
last_height: false,
|
||||
|
||||
init: function () {
|
||||
this.drawInterface();
|
||||
this.adjustSizes();
|
||||
Ajax.detectPage();
|
||||
},
|
||||
|
||||
drawInterface: function() {
|
||||
},
|
||||
|
||||
adjustSizes: function() {
|
||||
$('.data-container').height($(window).height() - $('.header-container').height());
|
||||
$('.data-container').width($(window).width() - $('.player').width()).scrollbar();
|
||||
$('.player-container').height($(window).height());
|
||||
$('.playlist').height($(window).height() - $('.player').height() - $('.player-container .additional-controls').height());
|
||||
|
||||
$('.playlist').scrollbar();
|
||||
},
|
||||
|
||||
checkRedrawScrollbar: function() {
|
||||
var focused_id = false;
|
||||
if (typeof document.activeElement.id !== 'undefined') {
|
||||
focused_id = document.activeElement.id;
|
||||
}
|
||||
var outer_height = $('.data-container > div').outerHeight();
|
||||
if (outer_height > 300 && outer_height != beathaven.last_height) {
|
||||
beathaven.last_height = outer_height;
|
||||
beathaven.redrawScrollbar();
|
||||
}
|
||||
if (focused_id) {
|
||||
document.getElementById(focused_id).focus();
|
||||
focused_id = false;
|
||||
}
|
||||
window.setTimeout(beathaven.checkRedrawScrollbar, 500);
|
||||
},
|
||||
|
||||
redrawScrollbar: function() {
|
||||
$('.data-container').html($('.data-container').find('.inner').first());
|
||||
$('.data-container').scrollbar();
|
||||
}
|
||||
}
|
||||
|
||||
String.prototype.htmlsafe = function() {
|
||||
var replaces = [
|
||||
["\\", "\\\\"],
|
||||
["\"", """],
|
||||
["<", "<"],
|
||||
[">", ">"]
|
||||
];
|
||||
var str = this;
|
||||
for (var i = 0; i < replaces.length; i++) {
|
||||
str = str.replace(replaces[i][0], replaces[i][1]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
String.prototype.trim = function() {
|
||||
var str = this;
|
||||
while (str.indexOf(' ') !== -1) {
|
||||
str = str.replace(' ', ' ');
|
||||
}
|
||||
if (str.charAt(0) == ' ') {
|
||||
str = str.substring(1);
|
||||
}
|
||||
if (str.charAt(str.length - 1) == ' ') {
|
||||
str = str.substring(0, str.length - 1);
|
||||
}
|
||||
return str;
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
var Pages = {
|
||||
|
||||
renderArtist: function(data){
|
||||
var artist_info = $('\
|
||||
<div class="artist-info">\
|
||||
<div class="pic">\
|
||||
<img src="'+ data.artist.pic +'" alt="'+ data.artist.name +'" width="250" />\
|
||||
</div>\
|
||||
<h1 class="name">'+ data.artist.name +'</h1>\
|
||||
<div class="info">\
|
||||
'+ data.artist.desc +'\
|
||||
</div>\
|
||||
</div>\
|
||||
');
|
||||
|
||||
var albums_info = $('<div class="albums"></div>');
|
||||
$.each(data.albums, function(i, album){
|
||||
if (album.year != null) {
|
||||
var album_info = $('\
|
||||
<div class="album">\
|
||||
<h2 class="name">'+ album.name +' ('+ album.year +')</h2>\
|
||||
<div class="pic">\
|
||||
<img src="'+ (album.pic ? album.pic : '/images/kitteh.png') +'" alt="'+ album.name +' by '+ data.artist.name +'" width="250" height="250"/>\
|
||||
<div class="add-album-button-container">\
|
||||
<div class="add-album button gray">Add to Now Playing</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="tracklist">\
|
||||
<ul>\
|
||||
</ul>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="kaboom"></div>\
|
||||
');
|
||||
|
||||
$.each(album.tracks.album, function(i, track){
|
||||
var track_info = $('\
|
||||
<li>\
|
||||
<div class="add-track button gray">+</div>\
|
||||
<div class="track-container">\
|
||||
<div class="fade"></div>\
|
||||
<span class="index">'+ (i+1) +'</span>\
|
||||
<div class="trackname" title="'+ track.name.htmlsafe() +'">'+ track.name +'</div>\
|
||||
<div class="length">'+ track.duration +'</div>\
|
||||
</div>\
|
||||
</li>\
|
||||
');
|
||||
|
||||
$(album_info).find('.tracklist ul').append(track_info);
|
||||
});
|
||||
|
||||
$(albums_info).append(album_info);
|
||||
}
|
||||
})
|
||||
|
||||
$('.data-container').css('backgroundImage', 'none');
|
||||
$('.data-container .inner').html('').append(artist_info).append(albums_info);
|
||||
|
||||
yaCounter7596904.hit(Ajax.getAnchor(), data.artist.name, Ajax.referer);
|
||||
Ajax.setTitle(data.artist.name);
|
||||
},
|
||||
|
||||
renderSearch: function(data) {
|
||||
$('.data-container').css('background', 'url(/images/concrete_wall_2.png) 0 -30px repeat');
|
||||
$('.data-container .inner').html(data);
|
||||
|
||||
$('.search-container')
|
||||
.css('marginLeft', ($('.data-container').width() - 425) / 2 + 'px')
|
||||
.css('marginTop', ($('.data-container').height() / 2 - 230) +'px')
|
||||
.height(($('.data-container').height() - $('#search_form').height()) / 2);
|
||||
|
||||
setTimeout(function(){
|
||||
$('#search_field').bh_autocomplete({
|
||||
serviceUrl: '/artist/autocomplete', // Страница для обработки запросов автозаполнения
|
||||
minChars: 2, // Минимальная длина запроса для срабатывания автозаполнения
|
||||
delimiter: /(,|;)\s*/, // Разделитель для нескольких запросов, символ или регулярное выражение
|
||||
maxHeight: 400, // Максимальная высота списка подсказок, в пикселях
|
||||
width: 415, // Ширина списка
|
||||
zIndex: 9999, // z-index списка
|
||||
deferRequestBy: 500, // Задержка запроса (мсек)
|
||||
onSelect: Ajax.loadArtistData
|
||||
});
|
||||
$('#search_field').focus();
|
||||
}, 501)
|
||||
|
||||
yaCounter7596904.hit(Ajax.getAnchor(), 'Artist Search', Ajax.referer);
|
||||
Ajax.setTitle('Artist Search');
|
||||
},
|
||||
|
||||
renderSettings: function(data) {
|
||||
$('.data-container').css('background', 'none');
|
||||
$('.data-container .inner').html(data);
|
||||
yaCounter7596904.hit(Ajax.getAnchor(), 'Settings', Ajax.referer);
|
||||
Ajax.setTitle('Settings');
|
||||
$('.settings-container .tabs .tab').first().trigger('click');
|
||||
}
|
||||
}
|
|
@ -1,261 +0,0 @@
|
|||
var Player = {
|
||||
|
||||
bar_width: 330,
|
||||
jp: null,
|
||||
scrobbled: false,
|
||||
|
||||
initJplayer: function() {
|
||||
this.jp = $("#jplayer");
|
||||
this.jp.jPlayer({
|
||||
swfPath: "/js",
|
||||
supplied: "mp3",
|
||||
cssSelectorAncestor: "",
|
||||
cssSelector: {
|
||||
play: "#player .play",
|
||||
pause: "#player .pause",
|
||||
stop: "",
|
||||
videoPlay: "",
|
||||
seekBar: "",
|
||||
playBar: "",
|
||||
mute: "",
|
||||
unmute: "",
|
||||
volumeBar: "",
|
||||
volumeBarValue: "",
|
||||
currentTime: "",
|
||||
duration: ""
|
||||
}
|
||||
});
|
||||
this.jp.bind($.jPlayer.event.timeupdate, function(e){
|
||||
data = e.jPlayer.status;
|
||||
if (!Player.scrobbled && data.currentPercentAbsolute > 50) {
|
||||
var $obj = $('.playlist-tracks li.now');
|
||||
Player.scrobble($obj.attr('data-artist'), $obj.attr('data-album'), $obj.attr('data-track'));
|
||||
Player.scrobbled = true;
|
||||
}
|
||||
$('#player .progress .loaded').width(data.seekPercent * Player.bar_width / 100);
|
||||
$('#player .progress .played').width(data.currentPercentAbsolute * Player.bar_width / 100);
|
||||
});
|
||||
this.jp.bind($.jPlayer.event.ended, function(e){
|
||||
var next = Player.nextTrack();
|
||||
if (next === false) {
|
||||
$('#jplayer').jPlayer('clearMedia');
|
||||
$('#player .now-playing').html('Nothing left to <strike>lose</strike> play');
|
||||
$('#player .loaded, #player .played').width(0);
|
||||
$('.playlist-tracks li').removeClass('now');
|
||||
} else {
|
||||
Player.setTrack(next);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addTrack: function(artist, album, track, length, autoplay) {
|
||||
if (typeof autoplay === 'undefined') {
|
||||
autoplay = false;
|
||||
}
|
||||
var initial_count = $('.playlist-tracks li').length;
|
||||
$('.playlist-tracks').append('\
|
||||
<li id="i'+ Math.round(Math.random() * 999999) +'" data-artist="'+ artist.trim() +'" data-album="'+ album.trim() +'" data-track="'+ track.trim() +'" data-length="'+ length +'">\
|
||||
<div class="item">\
|
||||
<div class="fade"></div>\
|
||||
<span class="title" title="'+ artist.htmlsafe() +' — '+ track.htmlsafe() +'">'+ artist +' — '+ track +'</span>\
|
||||
<span class="duration">'+ length +'</span>\
|
||||
<div class="remove">remove</div>\
|
||||
</div>\
|
||||
</li>\
|
||||
');
|
||||
|
||||
$('#playlist').html($('.playlist-tracks')).scrollbar();
|
||||
$('.playlist-tracks').sortable();
|
||||
|
||||
if (autoplay) {
|
||||
Player.setTrack($('.playlist-tracks li').last().attr('id').split('i')[1]);
|
||||
} else if (initial_count === 0 && !Player.hasTrack()) {
|
||||
Player.setTrack($('.playlist-tracks li').first().attr('id').split('i')[1]);
|
||||
}
|
||||
},
|
||||
|
||||
setTrack: function(id) {
|
||||
var $obj = $('#i'+ id);
|
||||
var query = $obj.attr('data-artist') +' — '+ $obj.attr('data-track');
|
||||
|
||||
$('#player .now-playing').html(query +'<div class="fade"></div>');
|
||||
$('.playlist-tracks li').removeClass('now');
|
||||
$obj.addClass('now');
|
||||
$('#player .loaded, #player .played').width(0);
|
||||
|
||||
Vkontakte.loadTracksData($obj.attr('data-artist'), $obj.attr('data-track'), $obj.attr('data-length'), Player.playSource);
|
||||
Player.updateNowListening($obj.attr('data-artist'), $obj.attr('data-album'), $obj.attr('data-track'));
|
||||
},
|
||||
|
||||
hasTrack: function() {
|
||||
if ($('#jplayer audio').length > 0) {
|
||||
return typeof $('#jplayer audio').attr('src') !== 'undefined';
|
||||
} else if ($('#jplayer audio').length > 0) {
|
||||
$('#jplayer').jPlayer('play');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
playSource: function(url) {
|
||||
$('#jplayer').jPlayer('setMedia', {mp3: url}).jPlayer('play');
|
||||
Player.scrobbled = false;
|
||||
},
|
||||
|
||||
nextTrack: function(manual) {
|
||||
var manual = typeof manual !== 'undefined'
|
||||
var cnt = $('.playlist-tracks li').length;
|
||||
if (!Player.onShuffle()) { // Shuffle off
|
||||
if ($('.playlist-tracks .now').next().length == 0 && true) {
|
||||
if (Player.onRepeat() || manual) { // Last track and repeat is on
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return $('.playlist-tracks .now').next().attr('id').split('i')[1];
|
||||
}
|
||||
} else if (cnt === 1) { // Single track in the playlist
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1];
|
||||
} else { // Shuffle on
|
||||
while (1) {
|
||||
var rnd = Math.floor(Math.random() * (cnt + .999));
|
||||
var $li = $('.playlist-tracks li').eq(rnd);
|
||||
if ($li.length > 0 && !$li.hasClass('now')) {
|
||||
return $li.attr('id').split('i')[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
prevTrack: function() {
|
||||
var cnt = $('.playlist-tracks li').length;
|
||||
if (!Player.onShuffle()) { // Shuffle off
|
||||
if ($('.playlist-tracks .now').prev().length == 0 && true) { // First track in the playlist
|
||||
return $('.playlist-tracks li').last().attr('id').split('i')[1];
|
||||
} else {
|
||||
return $('.playlist-tracks .now').prev().attr('id').split('i')[1];
|
||||
}
|
||||
} else if (cnt === 1) { // Single track in the playlist
|
||||
return $('.playlist-tracks li').first().attr('id').split('i')[1];
|
||||
} else { // Shuffle on
|
||||
while (1) {
|
||||
var rnd = Math.floor(Math.random() * (cnt + .999));
|
||||
var $li = $('.playlist-tracks li').eq(rnd);
|
||||
if ($li.length > 0 && !$li.hasClass('now')) {
|
||||
return $li.attr('id').split('i')[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onShuffle: function() {
|
||||
return $('#shuffle').hasClass('active');
|
||||
},
|
||||
|
||||
onRepeat: function() {
|
||||
return $('#repeat').hasClass('active');
|
||||
},
|
||||
|
||||
updateNowListening: function(artist, album, track) {
|
||||
if (Settings.user.lastfm_username) {
|
||||
Session.query('/lastfm/listening?r='+ Math.random(), {'artist': artist, 'album': album, 'track': track});
|
||||
}
|
||||
},
|
||||
|
||||
scrobble: function(artist, album, track) {
|
||||
if (Settings.user.lastfm_username) {
|
||||
Session.query('/lastfm/scrobble?r='+ Math.random(), {'artist': artist, 'album': album, 'track': track});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(function(){
|
||||
Player.initJplayer();
|
||||
});
|
||||
|
||||
$('#player .controls .prev').live('click', function(){
|
||||
Player.setTrack(Player.prevTrack());
|
||||
});
|
||||
|
||||
$('#player .controls .next').live('click', function(){
|
||||
Player.setTrack(Player.nextTrack(true));
|
||||
});
|
||||
|
||||
$('.add-album').live('click', function() {
|
||||
var artist = $('.artist-info .name').html();
|
||||
var album = $(this).parent().parent().parent().find('h2.name').text().replace(/\s\([\d]{4}\)$/, '');
|
||||
$(this).parent().parent().parent().find('.tracklist li').each(function(i, item){
|
||||
var track_name = $(item).find('.trackname').html();
|
||||
var length = $(item).find('.length').html();
|
||||
Player.addTrack(artist, album, track_name, length);
|
||||
});
|
||||
})
|
||||
$('.add-track').live('click', function(){
|
||||
var artist = $('.artist-info .name').html();
|
||||
var album = $(this).parent().parent().parent().parent().find('h2.name').text().replace(/\s\([\d]{4}\)$/, '');
|
||||
var track_name = $(this).parent().find('.trackname').html();
|
||||
var length = $(this).parent().find('.length').html();
|
||||
Player.addTrack(artist, album, track_name, length);
|
||||
});
|
||||
|
||||
$('#player .play').live('click', function(){
|
||||
if ($('.playlist-tracks li').length > 0 && !Player.hasTrack()) {
|
||||
Player.setTrack($('.playlist-tracks li').first().attr('id').split('i')[1]);
|
||||
}
|
||||
});
|
||||
|
||||
$('.tracklist li').live('mouseover mouseout', function(e){
|
||||
if (e.type == 'mouseover') {
|
||||
$(this).find('.add-track').show();
|
||||
} else {
|
||||
$(this).find('.add-track').hide();
|
||||
}
|
||||
}).live('dblclick', function(e){
|
||||
var artist = $('.artist-info .name').html();
|
||||
var album = $(this).parent().parent().parent().find('h2.name').text().replace(/\s\([\d]{4}\)$/, '');
|
||||
var track_name = $(this).find('.trackname').html();
|
||||
var length = $(this).find('.length').html();
|
||||
Player.addTrack(artist, album, track_name, length, true);
|
||||
});
|
||||
|
||||
$('.playlist-tracks li .fade, .playlist-tracks li .duration, .playlist-tracks li .remove').live('mouseover mouseout', function(e){
|
||||
if (e.type == 'mouseover') {
|
||||
$(this).parent().find('.duration').hide();
|
||||
$(this).parent().find('.remove').show();
|
||||
} else {
|
||||
$(this).parent().find('.remove').hide();
|
||||
$(this).parent().find('.duration').show();
|
||||
}
|
||||
});
|
||||
|
||||
$('.playlist-tracks li .remove').live('click', function(){
|
||||
var $li = $(this).parent().parent();
|
||||
if ($li.hasClass('now')) {
|
||||
$('#jplayer').jPlayer('clearMedia');
|
||||
$('#player .now-playing').text('...');
|
||||
$('#player .loaded, #player .played').width(0);
|
||||
}
|
||||
$li.remove();
|
||||
});
|
||||
|
||||
$('.playlist-tracks li').live('dblclick', function(){
|
||||
Player.setTrack($(this).attr('id').split('i')[1]);
|
||||
});
|
||||
|
||||
$('#player .progress').live('click', function(e){
|
||||
$('#jplayer').jPlayer('playHead', Math.round((e.offsetX / Player.bar_width) * 100));
|
||||
});
|
||||
|
||||
$('#repeat, #shuffle').live('click', function(){
|
||||
$(this).toggleClass('active');
|
||||
});
|
||||
|
||||
$('#empty-playlist').live('click', function(){
|
||||
if (confirm('Are you sure?')) {
|
||||
$('.playlist-tracks li').remove();
|
||||
$('#jplayer').jPlayer('clearMedia');
|
||||
$('#player .now-playing').text('Add some music to playlist');
|
||||
$('#player .loaded, #player .played').width(0);
|
||||
}
|
||||
});
|
|
@ -1,71 +0,0 @@
|
|||
var Search = {
|
||||
|
||||
pics: [],
|
||||
|
||||
showSpinner: function() {
|
||||
$('.search-container input').attr('disabled', 'disabled').blur();
|
||||
$('.search-container img').show();
|
||||
$('.autocomplete-container').hide();
|
||||
$('.artist_loading.failed').hide();
|
||||
Search.hideSuggestions();
|
||||
},
|
||||
|
||||
hideSpinner: function() {
|
||||
$('.search-container input').removeAttr('disabled');
|
||||
$('.search_field').focus();
|
||||
$('.search-container img').hide();
|
||||
},
|
||||
|
||||
showSuggestions: function(values) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
$('.suggestions ul').append('\
|
||||
<li>\
|
||||
<a class="data artist">'+ values[i].name +'</a>\
|
||||
'+ (values[i].desc ? '<br/><span>'+ values[i].desc +'</span>' : '') +'\
|
||||
</li>\
|
||||
');
|
||||
}
|
||||
$('.suggestions').show();
|
||||
},
|
||||
|
||||
hideSuggestions: function() {
|
||||
$('.suggestions ul li').remove();
|
||||
$('.suggestions').hide();
|
||||
},
|
||||
|
||||
showArtistPics: function(pics) {
|
||||
$('.artist_loading.ok, .artist_pics').show();
|
||||
for (var i = 0; i < pics.length; i++) {
|
||||
if (Search.pics.indexOf(pics[i]) === -1) {
|
||||
Search.pics.push(pics[i]);
|
||||
$('.artist_pics').append('\
|
||||
<div class="pic">\
|
||||
<img src="'+ pics[i] +'" alt=""/>\
|
||||
</div>\
|
||||
');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
showError: function() {
|
||||
$('.artist_loading.ok, .artist_pics').hide();
|
||||
$('.artist_loading.failed').show();
|
||||
Search.pics = []
|
||||
}
|
||||
}
|
||||
|
||||
$(function(){
|
||||
$('.search').live('click', function(){
|
||||
Ajax.loadSearchPage();
|
||||
return false;
|
||||
});
|
||||
$('#search_form').live('submit', function(){
|
||||
$('.autocomplete-container').remove();
|
||||
Ajax.loadArtistData($('#search_field').val());
|
||||
return false;
|
||||
});
|
||||
$('.suggestions a').live('click', function(){
|
||||
$('#search_field').val($(this).text());
|
||||
return false;
|
||||
});
|
||||
});
|
|
@ -1,20 +0,0 @@
|
|||
var Session = {
|
||||
|
||||
user_id: null,
|
||||
vk_params: {},
|
||||
|
||||
query: function(url, params, callback) {
|
||||
var q_params = this.vk_params;
|
||||
for (attr in params) {
|
||||
q_params[attr] = params[attr];
|
||||
}
|
||||
$.post(url, q_params, callback);
|
||||
},
|
||||
|
||||
setVkParams: function(params) {
|
||||
attrs = ['expire', 'mid', 'secret', 'sid', 'sig'];
|
||||
for (var i = 0; i < attrs.length; i++) {
|
||||
this.vk_params[attrs[i]] = params[attrs[i]];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
var Settings = {
|
||||
|
||||
user: null,
|
||||
|
||||
getAccountInfo: function(callback) {
|
||||
Session.query('/user/update', {}, callback);
|
||||
},
|
||||
|
||||
saveAccountInfo: function(params, callback) {
|
||||
Session.query('/user/update', params, callback);
|
||||
},
|
||||
|
||||
loadFormData: function(form) {
|
||||
if (form == 'account') {
|
||||
$('.settings-container .form input[name$="username"]').val(Settings.user.name);
|
||||
$('.settings-container .form input[name$="email"]').val(Settings.user.email);
|
||||
} else if (form == 'lastfm') {
|
||||
if (Settings.user.lastfm_username) {
|
||||
$('.form-container input[name$="username"]').first().val(Settings.user.lastfm_username);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$('.settings').live('click', function() {
|
||||
Ajax.loadSettingsPage();
|
||||
});
|
||||
|
||||
$('.settings-container .tabs .tab').live('click', function(){
|
||||
if (!$(this).hasClass('active')) {
|
||||
$('.settings-container .tabs .tab').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
$('.form-container').html($('.forms .'+ $(this).attr('data-fieldset')).html());
|
||||
Settings.loadFormData($(this).attr('data-fieldset'));
|
||||
}
|
||||
});
|
||||
|
||||
$('.lastfm-connect').live('click', function(){
|
||||
window.open(Settings.user.lastfm_login_url);
|
||||
});
|
||||
|
||||
$('.settings-container .form input').live('blur', function(){
|
||||
var active_tab = $('.settings-container .tabs .tab.active').attr('data-fieldset');
|
||||
if (active_tab == 'account') {
|
||||
params = {
|
||||
'username': $('.settings-container .form input[name$="username"]').first().val(),
|
||||
'email': $('.settings-container .form input[name$="email"]').first().val(),
|
||||
};
|
||||
Settings.saveAccountInfo(params, function(){
|
||||
$('#header-container .hello .greating').text('Hi there, '+ (params.username.length > 0 ? params.username : '%username%') +'!');
|
||||
});
|
||||
}
|
||||
})
|
|
@ -1,102 +0,0 @@
|
|||
var Vkontakte = {
|
||||
|
||||
qr: [],
|
||||
|
||||
authInfo: function(response) {
|
||||
if (typeof response != 'undefined' && response.session) {
|
||||
Session.setVkParams(response.session);
|
||||
$('#vk_login, .auth_notice').hide();
|
||||
$('#vk_logout').css('display', 'block');
|
||||
if ($('#search_field').length > 0) {
|
||||
$('#search_field').focus();
|
||||
}
|
||||
Session.query('/user/auth', {}, function(ar){
|
||||
if (ar.newbie) {
|
||||
VK.Api.call('getVariable', {key: 1281}, function(r) {
|
||||
Session.query('/user/update', {'name': r.response}, function(ar2) {
|
||||
Settings.user = ar2.user;
|
||||
$('#header-container .hello .greating').text('Hi there, '+ (Settings.user.name ? Settings.user.name : '%username%') +'!');
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Settings.user = ar.user;
|
||||
}
|
||||
$('#header-container .hello .greating').text('Hi there, '+ (Settings.user.name ? Settings.user.name : '%username%') +'!');
|
||||
});
|
||||
} else {
|
||||
$('#vk_login, .auth_notice').css('display', 'block');
|
||||
$('#vk_logout').hide();
|
||||
}
|
||||
},
|
||||
|
||||
loadTracksData: function(artist, track, duration, callback) {
|
||||
var track_prepared = track.replace(/\(.*\)/i, '').split('/')[0];
|
||||
var query = artist +' '+ track_prepared;
|
||||
if (typeof Vkontakte.qr[query] !== 'undefined') {
|
||||
callback(Vkontakte.qr[query]);
|
||||
} else {
|
||||
VK.Api.call('audio.search', {q: query}, function(r){
|
||||
var url = Vkontakte.matchPerfectResult(r.response, artist, track, duration);
|
||||
Vkontakte.qr[query] = url;
|
||||
callback(url);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
matchPerfectResult: function(data, artist, track, duration) {
|
||||
var duration = duration.split(':');
|
||||
if (duration[1].charAt(0) === '0') {
|
||||
duration[1] = duration[1].substring(1);
|
||||
}
|
||||
duration = parseInt(duration[0]) * 60 + parseInt(duration[1]);
|
||||
var best_score = 0;
|
||||
var best_result = null;
|
||||
for (var i = 1; i < data.length; i++) {
|
||||
var score = 0;
|
||||
data[i].artist = data[i].artist.trim();
|
||||
data[i].title = data[i].title.trim();
|
||||
if (data[i].artist === artist) {
|
||||
score += 10;
|
||||
} else if (data[i].artist.split(artist).length === 2) {
|
||||
score += 5;
|
||||
} else if (data[i].title.split(artist).length === 2) {
|
||||
score += 4;
|
||||
}
|
||||
if (data[i].title === track) {
|
||||
score += 10;
|
||||
} else if (data[i].title.split(track).length === 2) {
|
||||
score += 5;
|
||||
}
|
||||
if (parseInt(data[i].duration) === duration) {
|
||||
score += 15;
|
||||
} else {
|
||||
var delta = Math.abs(parseInt(data[i].duration) - duration);
|
||||
if (delta < 10) {
|
||||
score += (10 - delta);
|
||||
}
|
||||
}
|
||||
if (score > best_score) {
|
||||
best_score = score;
|
||||
best_result = data[i];
|
||||
}
|
||||
if (score === 35) {
|
||||
return best_result.url;
|
||||
}
|
||||
}
|
||||
return best_result.url;
|
||||
}
|
||||
}
|
||||
|
||||
$(function(){
|
||||
VK.init({
|
||||
apiId: (document.location.host == 'beathaven.org' ? 2335068 : 2383163),
|
||||
nameTransportPath: "/xd_receiver.html"
|
||||
});
|
||||
VK.Auth.getLoginStatus(Vkontakte.authInfo);
|
||||
$('#vk_login').click(function(){
|
||||
VK.Auth.login(Vkontakte.authInfo, 8);
|
||||
});
|
||||
$('#vk_logout').click(function(){
|
||||
VK.Auth.logout(Vkontakte.authInfo);
|
||||
});
|
||||
})
|
Loading…
Reference in New Issue