function Playlist(pl, audio) { this.pl = pl; this.audio = audio; this.current = null; this.lastalbum = null; this.get = function(path, track) { var li = this.pl.getElementsByTagName('li')[0]; while(li) { var as = li.getElementsByTagName('a'); if(as.length == 2) { var a = as[0]; if(a.ml.path == path && (!track || a.ml.track == track)) return li; } li = li.nextElementSibling; } return null; } this.add = function(ml) { var a = document.createElement('a'); a.setAttribute('class', 'song'); a.setAttribute('href', '#'); var name = ml.get_text(); a.appendChild(document.createTextNode(name)); a.ml = ml; var li = document.createElement('li'); var pl = this; a.onclick = function() { while(li.previousElementSibling && li.previousElementSibling.getAttribute('class') != 'album') li.previousElementSibling.parentElement.removeChild(li.previousElementSibling); // Remove children above the album marker. // This could probably be done in a more elegant way. if(li.previousElementSibling && li.previousElementSibling.previousElementSibling) while(li.previousElementSibling.previousElementSibling) li.previousElementSibling.previousElementSibling.parentElement.removeChild(li.previousElementSibling.previousElementSibling); if(li.previousElementSibling && pl.pl.firstChild != li.previousElementSibling) pl.pl.removeChild(pl.pl.firstChild); a.setAttribute('class', 'song playing'); pl.current = li; ml.play(); var nextsong = li.nextElementSibling; log('nextsong: ' + nextsong); // avoid breaking when a track has been removed while(nextsong && nextsong.childElementCount == 0) nextsong = nextsong.nextElementSibling; if(nextsong && nextsong.getAttribute('class') == 'album') nextsong = nextsong.nextElementSibling; if(nextsong) { var nexta = nextsong.getElementsByTagName('a')[0]; nexta.ml.recode(); } return false; } log(a.click); if(ml.metadata.album != this.lastalbum) { var album_li = document.createElement('li'); album_li.appendChild(document.createTextNode(ml.metadata.album)); album_li.setAttribute('class', 'album'); var a_del = document.createElement('a'); a_del.setAttribute('class', 'delete'); a_del.setAttribute('href', '#'); a_del.setAttribute('title', 'Remove'); var del_img = new Image(); del_img.src = '/static/icons/delete.png'; a_del.appendChild(del_img); a_del.onclick = (function(album_li) { return function() { while(album_li.nextElementSibling && album_li.nextElementSibling.getAttribute('class') != 'album') pl.pl.removeChild(album_li.nextElementSibling); pl.pl.removeChild(album_li); return false; } })(album_li); var span = document.createElement('span'); span.style.display = 'none'; album_li.onmouseover = (function(span) { return function() { span.style.display = ''; } })(span); album_li.onmouseout = (function(span) { return function() { span.style.display = 'none'; } })(span); span.appendChild(a_del); album_li.appendChild(span); this.pl.appendChild(album_li); this.lastalbum = ml.metadata.album; } var div = document.createElement('div'); // anchor to remove track from playlist var a_del = document.createElement('a'); a_del.setAttribute('class', 'delete'); a_del.setAttribute('href', '#'); a_del.setAttribute('title', 'Remove'); var del_img = new Image(); del_img.src = '/static/icons/delete.png'; a_del.appendChild(del_img); a_del.onclick = function() { log(li.previousElementSibling); log(li.nextElementSibling); // remove previous element if it is an album header and we're at end of queue, // or next element is an album header if(li.previousElementSibling && li.previousElementSibling.getAttribute('class') == 'album' && (!li.nextElementSibling || li.nextElementSibling.getAttribute('class') == 'album')) pl.pl.removeChild(li.previousElementSibling); pl.pl.removeChild(li); if(pl.pl.childElementCount == 0) pl.lastalbum = null; // recode next var next = pl.get_next(); if(next) next.getElementsByTagName('a')[0].ml.recode(); return false; } var span = document.createElement('span'); span.style.display = 'none'; div.onmouseover = (function(span) { return function() { span.style.display = ''; } })(span); div.onmouseout = (function(span) { return function() { span.style.display = 'none'; } })(span); div.appendChild(a); div.appendChild(document.createTextNode(' ')); span.appendChild(a_del); span.setAttribute('class', 'right'); div.appendChild(span); li.appendChild(div); this.pl.appendChild(li); if(this.get_next() == li) ml.recode(); } // get the next queued song this.get_next = function() { var next = null; if(this.current) next = this.current.nextElementSibling; else if(this.pl.firstChild) next = this.pl.firstChild; if(!next) return null; if(next.getAttribute('class') == 'album') next = next.nextElementSibling; return next; } // play the next queued song this.next = function() { log('next'); log('this: ' + this); log('current: ' + this.current); if(this.current) { var old = this.current; log('old: ' + old); this.current = this.current.nextElementSibling; log('new current: ' + this.current); old.parentElement.removeChild(old); } // avoid breaking when a track has been removed while(this.current && this.current.getAttribute('class') == 'album') { log('next while loop'); this.current = this.current.nextElementSibling; } if(this.current) { var a = this.current.getElementsByTagName('a')[0]; a.onclick(); } else { this.lastalbum = null; this.pl.removeChild(this.pl.firstChild); } } }