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()