var currentSearch = '' var currentThread = '' var keyboard_mode = "navigate" var idleTimeout = undefined var fadeInterval = undefined var faded = false var qLeftPadding = 20 /* *************************************************** 1. page loads 2. user seraches "dodpop" << thread list received 2a user picks thread << file list received 3. user picks song 1 << player enqueues thread << song 1 starts playing << if no action is taken, song 2 will be next.. *************************************************** */ var Dymaxion = { count: 0, pos: 0, nowPlaying: {thread:0,file:0}, index: {count:0,rows:[],pos:0}, search: {count:0,rows:[],pos:0}, thread: {count:0,rows:[],pos:0}, comment: [], files: [], } var Player = { currentSound: false, nextSound: false, count: 0, rows: [], pos: 0, threadid: 0, file: 0, justbeforefinishMutex: false, playing: false, play: function (pos) { Player.threadid = Thread.threadid Player.rows = Dymaxion.thread.rows Player.count = Dymaxion.thread.rows.length -1 Player.pos = pos // 0 thread 1 filename 2 title 3 subtitle if (Player.pos < Player.count) Player.playFile(Thread.threadid, Player.rows[Player.pos][1]) }, playPrev: function () { Player.pos = Player.prev() if (Thread.threadid === Player.threadid) Cursor.select(Player.pos) if (Player.pos < Player.count) Player.playFile(Thread.threadid, Player.rows[Player.pos][1]) }, playNext: function () { Player.pos = Player.next() if (Thread.threadid === Player.threadid) Cursor.select(Player.pos) if (Player.pos < Player.count) Player.playFile(Thread.threadid, Player.rows[Player.pos][1]) }, playFile: function (thread, filename) { warn('playing '+Player.pos) if (soundManager.supported()) { if (Player.currentSound) { Player.currentSound.stop() Player.currentSound.destruct() Player.currentSound = false Player.onjustbeforefinishMutex = '' } Player.currentSound = soundManager.createSound ({ id: filename, url: '/bucky/data/'+thread+'/'+filename, // onload: [ event handler function object ], }); Player.currentSound.play(); } }, onbeforefinish: function () { var pos = Player.next() var thread = Thread.threadid var filename = Player.rows[pos][1] Player.onjustbeforefinishMutex = filename warn('loading '+filename) Player.nextSound = soundManager.createSound ({ id: filename, url: '/bucky/data/'+thread+'/'+filename, }); }, onjustbeforefinish: function () { Player.pos = Player.next() var filename = Player.rows[Player.pos][1] if (filename === Player.onjustbeforefinishMutex) { Player.nextSound.play(); warn('playing '+Player.pos) } else { warn('MUTEX: new sound!') } }, cursorPush: function () { warn("pushing cursor") if (Thread.threadid === Player.threadid) Cursor.select(Player.pos) }, onfinish: function () { //setTimeout(Player.cursorPush, 2500) Player.cursorPush() Player.currentSound.destruct() Player.currentSound = Player.nextSound }, prev: function () { var pos = this.pos - 1 if (pos < 0) pos = this.count - 1 return pos }, next: function () { var pos = this.pos + 1 if (pos == this.count) pos = 0 return pos }, loadSoundManager: function () { soundManager.debugMode = false soundManager.url = '/dymaxion/' soundManager.useFlashBlock = false soundManager.onready(function() { if (soundManager.supported()) warn('soundmanager loaded') else warn('soundmanager did not load!') }); soundManager.defaultOptions.onjustbeforefinish = Player.onjustbeforefinish soundManager.defaultOptions.onbeforefinish = Player.onbeforefinish soundManager.defaultOptions.onfinish = Player.onfinish }, } var Cursor = { mode: "search", count: 0, rows: [], pos: 0, perpage: 8, playing: -1, redrawPage: function () { var list = '' var page = Math.floor(this.pos/this.perpage) var pos = this.perpage * page warn('page# ' + page) for (var i = 0; i < this.perpage && pos < this.count; i++) { // 0 thread 1 filename 2 title 3 subtitle var row = this.rows[pos] if (row[3]) { list += "
  • "+row[2]+"

    " list += "

    "+row[3]+"

    " list += "
  • " } else { list += "
  • "+row[2]+"

    " list += "
  • " } pos += 1 } $('#list').html(list) if (this.pos < this.perpage) $('#pageup').hide() else $('#pageup').show() if (Math.floor((this.count-1)/this.perpage) === page) $('#pagedown').hide() else $('#pagedown').show() if (this.playing !== -1) $('#cursor-'+this.playing).addClass("playing") $('#list').show() }, selectFirst: function () { this.select(0) }, selectPageUp: function () { this.pos -= this.perpage if (this.pos < 0) this.pos = this.count - 1 this.redrawPage() this.selectOn(this.pos) }, selectPageDown: function () { this.pos += this.perpage if (this.pos >= this.count) this.pos = 0 this.redrawPage() this.selectOn(this.pos) }, selectPrev: function () { this.selectOff(this.pos) this.pos = this.prev() if (this.pos % this.perpage === this.perpage - 1 || this.pos === this.count - 1) this.redrawPage() this.selectOn(this.pos) }, selectNext: function () { this.selectOff(this.pos) this.pos = this.next() if (this.pos % this.perpage === 0) this.redrawPage() this.selectOn(this.pos) }, selectOff: function (n) { $('#cursor-'+n).removeClass("selected") }, selectOn: function (n) { $('#cursor-'+n).addClass("selected") }, select: function (n) { this.selectOff(this.pos) this.pos = n this.redrawPage() warn("AT "+n) this.selectOn(n) }, prev: function () { var pos = this.pos - 1 if (pos < 0) pos = this.count - 1 return pos }, next: function () { var pos = this.pos + 1 if (pos == this.count) pos = 0 return pos }, chooseThis: function () { return this.choose(this.pos) }, choose: function (pos) { warn("choose "+pos+" in "+this.mode) switch (this.mode) { case "index": Dymaxion.search.count = 0 Dymaxion.index.pos = pos var thread = $('#cursor-'+pos).attr('data-thread') var filename = $('#cursor-'+pos).attr('data-filename') Thread.load(thread, filename) break case "search": Dymaxion.search.pos = pos var thread = $('#cursor-'+pos).attr('data-thread') var filename = $('#cursor-'+pos).attr('data-filename') Thread.load(thread, filename) break case "thread": var thread = $('#cursor-'+pos).attr('data-thread') var filename = $('#cursor-'+pos).attr('data-filename') if (this.playing != -1) $('#cursor-'+this.playing).removeClass("playing") this.playing = pos $('#cursor-'+pos).addClass("playing") Player.play(pos) break } }, report: function (cmd) { warn("> "+cmd+" "+this.pos+" "+this.count) }, } function kp (e) { var evt = window.event ? window.event : e var key = evt.keyCode ? evt.keyCode : e.which if (faded) unFade() else clearTimeout(idleTimeout) // warn("keypress " + evt.type + " on " + key) return keypress(key) } function keypress (key) { if (keyboard_mode == 'textentry') return keypress_textentry(key) document.getElementById('username').innerHTML = '"'+ key +'"' switch (key) { case 27: // escape Search.lastAutocomplete = ''; $('#q').blur() $('#searchbox').hide() $('header').show() break case 33: // pageup Cursor.selectPageUp(); break case 34: // pagedown Cursor.selectPageDown(); break case 38: // up Cursor.selectPrev(); break case 40: // down Cursor.selectNext(); break case 37: // left if (Cursor.mode === "thread" && Dymaxion.search.count !== 0) { Search.display() } else { Index.display() } break case 39: // right case 13: // enter Cursor.chooseThis(); break case 177: // prev case 90: // z ///////////////// prev if (Player.count) Player.playPrev() break case 179: // play/pause case 88: // x if (Player.currentSound) Player.currentSound.play() break case 67: // c if (Player.currentSound) Player.currentSound.togglePause() break case 178: // stop case 86: // v if (Player.currentSound) Player.currentSound.stop() break case 176: // next case 66: // b ///////////////// advance if (Player.count) Player.playNext() break case 82: // r window.location.reload() break case 71: // g case 70: // f show_searchbox() break case 72: // h warn("> HALP!") Thread.load(1716) break case 73: // i Index.display() break } idleTimeout = setTimeout("startFader()", 1000) return false } function startFader() { faded = true fadeamt = 0.5 fadeInterval = setInterval("fade()", 420); } function fade() { if (fadeamt > 0.02) fadeamt -= 0.0007 else { clearInterval(fadeInterval) fadeamt = 0.03 } $('#listbox').css('opacity', fadeamt) $('#msg').css('opacity', fadeamt) $('#pageup').css('opacity', fadeamt) $('#pagedown').css('opacity', fadeamt) $('#hello').css('opacity', fadeamt) $('header').css('opacity', fadeamt) } function unFade() { clearInterval(fadeInterval) $('#listbox').css('opacity', 0.5) $('#msg').css('opacity', 0.5) $('#pageup').css('opacity', 0.5) $('#pagedown').css('opacity', 0.5) $('#hello').css('opacity', 0.5) $('header').css('opacity', 0.5) faded = false } function show_searchbox() { keyboard_mode = "textentry" $('#q').val('') $('#frag').hide() $('header').hide() $('#searchbox').show() $('#q').focus() } function hide_searchbox() { keyboard_mode = 'navigate' $('#q').blur() $('#frag').hide() $('#searchbox').hide() $('header').show() Search.lastAutocomplete = ''; } function keypress_textentry (key) { document.getElementById('username').innerHTML = '"'+ key +'"' switch (key) { case 8: // backspace $('#frag').hide() break case 38: // up break case 40: // down hide_searchbox() Cursor.select(0) return case 27: // esc hide_searchbox() Index.display() break case 13: // enter hide_searchbox() Cursor.select(0) // search($('#q').val()) return false case 32: // space return true case 178: // stop if (Player.currentSound) Player.currentSound.stop() return false } // for letters in range: 0-z if (key >= 48 && key <= 90) { var q = $('#q').val() q += String.fromCharCode(key).toLowerCase() $('#frag').hide() autocomplete(q) } return true } // - /api/login // + /api/index // + /api/thread // + /api/search // + /api/autocomplete // - /api/post // - /api/tag var Index = { go: function () { $('#list').fadeOut(200, function(){ }); if (! Dymaxion.index.count) $.get("/cgi-bin/bucky/2/api/index",{},Index.parse) else Index.display() }, parse: function (raw) { if (raw) warn("got it") else warn("index empty") var lines = raw.split("\n") var rows = [] var count = 0 for (i in lines) { if (! lines[i]) continue var fields = lines[i].split('\t') // 0 thread 1 title 2 subtitle 3 filename rows.push([fields[0],fields[3],fields[1],fields[2]]) count += 1 } Dymaxion.index.rows = rows Dymaxion.index.count = count Index.display() }, display: function () { $('header').html('Bucky Dymaxion') $('header').fadeIn(500, function(){}) Cursor.mode = "index" Cursor.rows = Dymaxion.index.rows Cursor.count = Dymaxion.index.count Cursor.select(Dymaxion.index.pos) $('#list').fadeIn(500, function(){}) }, }; var Search = { q: '', lastAutocomplete: '', oldSequence: '', autocompleteTimeout: '', go: function (q) { $('#list').fadeOut(200, function(){}) $('header').html('Results for ' +q+ '') $('#frag').html('') this.q = q warn ("> " +q); $.get("/cgi-bin/bucky/2/api/search",{'q':q},Search.parse) }, parse: function (raw) { warn("got it") var lines = raw.split("\n") var rows = [] var count = 0 for (i in lines) { if (! lines[i]) continue var fields = lines[i].split('\t') // 0 thread 1 title 2 subtitle 3 filename rows.push([fields[0],fields[3],fields[1],fields[2]]) count += 1 } // if only 1 search result, jump to that page if (count == 1) { Thread.load(rows[0][0],rows[0][3]) return } Dymaxion.search.count = count Dymaxion.search.rows = rows Search.display() }, display: function () { $('header').html("Results for " + this.q + "") $('header').fadeIn(500, function(){ }) Cursor.mode = "search"; Cursor.count = Dymaxion.search.count Cursor.rows = Dymaxion.search.rows Cursor.select(Dymaxion.search.pos) $('#list').fadeIn(500, function(){ }); }, autocomplete: function (q) { if (q === Search.lastAutocomplete) { $('#frag').hide() $('#frag').html('') return } warn("autocomplete "+q) Search.oldSequence = q clearTimeout(Search.autocompleteTimeout) Search.autocompleteTimeout = setTimeout(Search.autocompleteGo, 200) }, autocompleteGo: function (q) { $.get("/cgi-bin/bucky/2/api/autocomplete",{'q':q}, Search.autocompleteRaw); }, autocompleteRaw: function(raw) { if (Search.oldSequence !== q) { warn('bailing: '+q) return; } warn('not bailing: '+q) var lines = raw.split("\n") var rows = [] var count = 0 var frag = '' for (i in lines) { if (! frag) { var frag = lines[0] if (frag === "_") { warn("matched full word "+q) $('#frag').hide() $('#frag').html('') Search.q = q } else { Search.lastAutocomplete = q+frag var qt = document.getElementById('qtmp') qt.innerHTML = q // var qwidth = document.defaultView.getComputedStyle(qt,null).getPropertyValue('offsetWidth'); var qwidth = qt.offsetWidth qt.innerHTML = '' warn("qwidth: "+qwidth) warn("matched "+q+"_"+frag) document.getElementById('frag').innerHTML = frag document.getElementById('frag').style.left = qwidth + qLeftPadding Search.q = Search.lastAutocomplete $('#frag').fadeIn(500) } continue } if (! lines[i]) continue var fields = lines[i].split('\t') // 0 thread 1 title 2 subtitle 3 filename rows.push([fields[0],fields[3],fields[1],fields[2]]) count += 1 } $('header').html('Results for ' +Search.q+ ''); Cursor.mode = "search"; Cursor.count = count Cursor.rows = rows Dymaxion.search.count = count Dymaxion.search.rows = rows Cursor.redrawPage() $('#list').fadeIn(200, function(){ }); warn ("> " +q); }, }; var Thread = { thread: false, threadid: 0, fileid: 0, matchpos: 0, load: function (threadid, fileid) { if (! threadid) return Thread.threadid = threadid Thread.fileid = fileid warn ("loading "+threadid) $.get("/cgi-bin/bucky/2/api/thread",{'id':threadid},Thread.parse) }, parse: function (raw) { warn("got it") var lines = raw.split("\n") var bg = ''; var count = 0 var rows = [] var thread = false Thread.matchpos = 0 for (i in lines) { if (! lines[i]) continue var fields = lines[i].split('\t') // thread (first line) // 0 id 1 title 2 flagged 3 createdate 4 username 5 keyword if (! thread) thread = fields // file: // 0 id 1 type 2 filename 3 title 4 date 5 size else if (fields[1] === 'mp3') { // 0 id 1 type 2 filename 3 title 4 date 5 size rows.push([thread[0],fields[2],fields[3],undefined]) if (fields[0] === Thread.fileid) Thread.matchpos = count count += 1 } else if ( ! bg && ( thread[2] && fields[0] === thread[2] ) || (! thread[2] && (fields[1] === 'jpg' || fields[1] === 'gif' || fields[1] === 'png')) ) { bg = fields[2] $('#background').fadeOut(500, function () { warn("bg = "+bg) warn("/bucky/data/"+Thread.threadid+"/"+bg) document.getElementById('background').src = "/bucky/data/"+Thread.threadid+"/"+bg document.getElementById('background').onload = function(){ $('#background').fadeIn(500, function (){}) } }) } // comment: // 0 id 1 type 2 username 3 date 4 comment else if (fields[1] === 'comment') { if (! fields[4]) continue rows.push([thread[0],fields[2],'',fields[4],]) count += 1 } } Thread.thread = thread Dymaxion.thread.count = count Dymaxion.thread.rows = rows Thread.display() }, display: function () { $('header').html(Thread.thread[1]); $('header').fadeIn(500, function(){ }) Cursor.mode = "thread"; Cursor.count = Dymaxion.thread.count Cursor.rows = Dymaxion.thread.rows if (Thread.fileid) Cursor.select(Thread.matchpos) else Cursor.select(0) }, } function warn(s) { var h = document.getElementById('msg').innerHTML h = s + '
    ' + h document.getElementById('msg').innerHTML = h } function init () { warn ("yo") document.onkeydown = kp Index.go() Player.loadSoundManager() $('#background').hide() document.getElementById('background').src = "/dymaxion/paradis.jpg" document.getElementById('background').onload = function(){ $('#background').fadeIn(5000, function (){}) } // Search.go('surgeon') // Thread.load(666) } init()