czaks
11 years ago
3 changed files with 365 additions and 4 deletions
@ -0,0 +1,18 @@ |
|||
var orig_title = document.title; |
|||
|
|||
$(function(){ |
|||
orig_title = document.title; |
|||
}); |
|||
|
|||
update_title = function() { |
|||
var updates = 0; |
|||
for(var i in title_collectors) { |
|||
updates += title_collectors[i](); |
|||
} |
|||
document.title = (updates ? "("+updates+") " : "") + orig_title; |
|||
}; |
|||
|
|||
var title_collectors = []; |
|||
add_title_collector = function(f) { |
|||
title_collectors.push(f); |
|||
}; |
@ -0,0 +1,334 @@ |
|||
$(function(){ |
|||
var status = {}; |
|||
|
|||
time_loaded = Date.now(); |
|||
|
|||
var updating_suspended = false; |
|||
|
|||
var storage = function() { |
|||
return JSON.parse(localStorage.watch !== undefined ? localStorage.watch : "{}"); |
|||
}; |
|||
|
|||
var storage_save = function(s) { |
|||
localStorage.watch = JSON.stringify(s); |
|||
}; |
|||
|
|||
var osize = function(o) { |
|||
var size = 0; |
|||
for (var key in o) { |
|||
if (o.hasOwnProperty(key)) size++; |
|||
} |
|||
return size; |
|||
}; |
|||
|
|||
var is_pinned = function(boardconfig) { |
|||
return boardconfig.pinned || boardconfig.watched || (boardconfig.threads ? osize(boardconfig.threads) : false); |
|||
}; |
|||
var is_boardwatched = function(boardconfig) { |
|||
return boardconfig.watched; |
|||
}; |
|||
var is_threadwatched = function(boardconfig, thread) { |
|||
return boardconfig && boardconfig.threads && boardconfig.threads[thread]; |
|||
}; |
|||
var toggle_pinned = function(board) { |
|||
var st = storage(); |
|||
var bc = st[board] || {}; |
|||
if (is_pinned(bc)) { |
|||
bc.pinned = false; |
|||
bc.watched = false; |
|||
bc.threads = {}; |
|||
} |
|||
else { |
|||
bc.pinned = true; |
|||
} |
|||
st[board] = bc; |
|||
storage_save(st); |
|||
return bc.pinned; |
|||
}; |
|||
var toggle_boardwatched = function(board) { |
|||
var st = storage(); |
|||
var bc = st[board] || {}; |
|||
bc.watched = !is_boardwatched(bc) && Date.now(); |
|||
st[board] = bc; |
|||
storage_save(st); |
|||
return bc.watched; |
|||
}; |
|||
var toggle_threadwatched = function(board, thread) { |
|||
var st = storage(); |
|||
var bc = st[board] || {}; |
|||
if (is_threadwatched(bc, thread)) { |
|||
delete bc.threads[thread]; |
|||
} |
|||
else { |
|||
bc.threads = bc.threads || {}; |
|||
bc.threads[thread] = Date.now(); |
|||
} |
|||
st[board] = bc; |
|||
storage_save(st); |
|||
return is_threadwatched(bc, thread); |
|||
}; |
|||
var update_pinned = function() { |
|||
if (typeof update_title != "undefined") update_title(); |
|||
|
|||
var bl = $('.boardlist').first(); |
|||
$('#watch-pinned').remove(); |
|||
var pinned = $('<div id="watch-pinned"></div>').css('display', 'inline-block').css('vertical-align', 'middle').appendTo(bl); |
|||
|
|||
var st = storage(); |
|||
for (var i in st) { |
|||
if (is_pinned(st[i])) { |
|||
var link; |
|||
if (bl.find('[href*="/'+i+'/"]:not(.cb-menuitem)').length) link = bl.find('[href*="/'+i+'/"]').first(); |
|||
|
|||
// TODO: fix path
|
|||
else link = $('<a href="/'+i+'/" class="cb-item cb-cat">/'+i+'/</a>').appendTo(pinned); |
|||
|
|||
if (link[0].origtitle === undefined) { |
|||
link[0].origtitle = link.html(); |
|||
} |
|||
else { |
|||
link.html(link[0].origtitle); |
|||
} |
|||
|
|||
if (st[i].watched) { |
|||
link.css("font-weight", "bold"); |
|||
if (status && status[i] && status[i].new_threads) { |
|||
link.html(link.html() + " (" + status[i].new_threads + ")"); |
|||
} |
|||
} |
|||
else if (st[i].threads && osize(st[i].threads)) { |
|||
link.css("font-style", "italic"); |
|||
|
|||
link.attr("data-board", i); |
|||
|
|||
if (status && status[i] && status[i].threads) { |
|||
var new_posts = 0; |
|||
for (var tid in status[i].threads) { |
|||
if (status[i].threads[tid] > 0) { |
|||
new_posts += status[i].threads[tid]; |
|||
} |
|||
} |
|||
if (new_posts > 0) { |
|||
link.html(link.html() + " (" + new_posts + ")"); |
|||
} |
|||
} |
|||
|
|||
link.mouseenter(function() { |
|||
updating_suspended = true; |
|||
|
|||
var list = $("<div class='boardlist top cb-menu'></div>") |
|||
.css("top", $(this).position().top + 13 + $(this).height()) |
|||
.css("left", $(this).position().left) |
|||
.css("right", "auto") |
|||
.appendTo($(this)); |
|||
var board = $(this).attr("data-board"); |
|||
|
|||
for (var tid in storage()[board].threads) { |
|||
// TODO: fix path
|
|||
var newposts = "(0)"; |
|||
if (status && status[board] && status[board].threads && status[board].threads[tid]) { |
|||
if (status[board].threads[tid] == -404) { |
|||
newposts = "<i class='icon icon-ban-circle'></i>"; |
|||
} |
|||
else { |
|||
newposts = "("+status[board].threads[tid]+")"; |
|||
} |
|||
} |
|||
|
|||
var tag = $("<a href='/"+board+"/res/"+tid+".html'><span>#"+tid+"</span><span class='cb-uri'>"+newposts+"</span>"); |
|||
|
|||
tag |
|||
.attr('data-thread', tid) |
|||
.addClass("cb-menuitem") |
|||
.appendTo(list) |
|||
.find(".cb-uri").mouseenter(function() { |
|||
this.oldval = $(this).html(); |
|||
$(this).css("min-width", $(this).width()); |
|||
$(this).html("<i class='icon icon-minus'></i>"); |
|||
}) |
|||
.mouseleave(function() { |
|||
$(this).html(this.oldval); |
|||
}) |
|||
.click(function() { |
|||
var b = $(this).parent().parent().parent().attr("data-board"); |
|||
var t = $(this).parent().attr("data-thread"); |
|||
toggle_threadwatched(b, t); |
|||
$(this).parent().parent().parent().mouseleave(); |
|||
return false; |
|||
}); |
|||
} |
|||
|
|||
}).mouseleave(function() { |
|||
updating_suspended = false; |
|||
$('.boardlist .cb-menu').remove(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
var fetch_jsons = function() { |
|||
if (updating_suspended) return; |
|||
|
|||
var st = storage(); |
|||
for (var i in st) { |
|||
if (st[i].watched) { |
|||
// TODO: fix path
|
|||
var r = $.getJSON("/"+i+"/threads.json", {nocache: Math.random()}, function(j, x, r) { |
|||
handle_board_json(r.board, j); |
|||
}); |
|||
r.board = i; |
|||
} |
|||
else if (st[i].threads) { |
|||
for (var j in st[i].threads) { |
|||
var r = $.getJSON("/"+i+"/res/"+j+".json", {nocache: Math.random()}, function(k, x, r) { |
|||
handle_thread_json(r.board, r.thread, k); |
|||
}).error(function(r) { |
|||
if(r.status == 404) handle_thread_404(r.board, r.thread); |
|||
}); |
|||
|
|||
r.board = i; |
|||
r.thread = j; |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var handle_board_json = function(board, json) { |
|||
var last_thread; |
|||
|
|||
var new_threads = 0; |
|||
|
|||
for (var i in json) { |
|||
for (var j in json[i].threads) { |
|||
var thread = json[i].threads[j]; |
|||
|
|||
if (thread.last_modified > storage()[board].watched / 1000) { |
|||
last_thread = thread.no; |
|||
|
|||
new_threads++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
status = status || {}; |
|||
status[board] = status[board] || {}; |
|||
status[board].last_thread = last_thread; |
|||
status[board].new_threads = new_threads; |
|||
update_pinned(); |
|||
}; |
|||
var handle_thread_json = function(board, threadid, json) { |
|||
for (var i in json.posts) { |
|||
var post = json.posts[i]; |
|||
|
|||
var new_posts = 0; |
|||
if (post.time > storage()[board].threads[threadid] / 1000) { |
|||
new_posts++; |
|||
} |
|||
status = status || {}; |
|||
status[board] = status[board] || {}; |
|||
status[board].threads = status[board].threads || {}; |
|||
status[board].threads[threadid] = new_posts; |
|||
update_pinned(); |
|||
} |
|||
}; |
|||
var handle_thread_404 = function(board, threadid) { |
|||
status = status || {}; |
|||
status[board] = status[board] || {}; |
|||
status[board].threads = status[board].threads || {}; |
|||
status[board].threads[threadid] = -404; //notify 404
|
|||
update_pinned(); |
|||
}; |
|||
|
|||
if (active_page == "thread") { |
|||
var board = $('form[name="post"] input[name="board"]').val(); |
|||
var thread = $('form[name="post"] input[name="thread"]').val(); |
|||
|
|||
var boardconfig = storage()[board] || {}; |
|||
|
|||
$('hr:first').before('<div id="watch-thread" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>'); |
|||
$('#watch-thread a').html(is_threadwatched(boardconfig, thread) ? _("Stop watching this thread") : _("Watch this thread")).click(function() { |
|||
$(this).html(toggle_threadwatched(board, thread) ? _("Stop watching this thread") : _("Watch this thread")); |
|||
update_pinned(); |
|||
}); |
|||
} |
|||
if (active_page == "index") { |
|||
var board = $('form[name="post"] input[name="board"]').val(); |
|||
|
|||
var boardconfig = storage()[board] || {}; |
|||
|
|||
$('hr:first').before('<div id="watch-pin" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>'); |
|||
$('#watch-pin a').html(is_pinned(boardconfig) ? _("Unpin this board") : _("Pin this board")).click(function() { |
|||
$(this).html(toggle_pinned(board) ? _("Unpin this board") : _("Pin this board")); |
|||
update_pinned(); |
|||
}); |
|||
|
|||
$('hr:first').before('<div id="watch-board" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>'); |
|||
$('#watch-board a').html(is_boardwatched(boardconfig) ? _("Stop watching this board") : _("Watch this board")).click(function() { |
|||
$(this).html(toggle_boardwatched(board) ? _("Stop watching this board") : _("Watch this board")); |
|||
$('#watch-pin a').html(is_pinned(board) ? _("Unpin this board") : _("Pin this board")); |
|||
update_pinned(); |
|||
}); |
|||
|
|||
} |
|||
|
|||
var check_post = function(frame, post) { |
|||
return post.length && $(frame).scrollTop() + $(frame).height() >= |
|||
post.position().top + post.height(); |
|||
} |
|||
|
|||
$(window).scroll(function() { |
|||
if (!status) return; |
|||
var refresh = false; |
|||
for(var bid in status) { |
|||
if (status[bid].new_threads && (active_page == "ukko" || active_page == "index") |
|||
&& check_post(this, $('[data-board="'+bid+'"]#thread_'+status[bid].last_thread))) { |
|||
var st = storage() |
|||
st[bid].watched = time_loaded; |
|||
storage_save(st); |
|||
refresh = true; |
|||
} |
|||
if (!status[bid].threads) continue; |
|||
|
|||
for (var tid in status[bid].threads) { |
|||
if(status[bid].threads[tid] && check_post(this, $('[data-board="'+bid+'"]#thread_'+tid))) { |
|||
var st = storage(); |
|||
st[bid].threads[tid] = time_loaded; |
|||
storage_save(st); |
|||
refresh = true; |
|||
} |
|||
} |
|||
} |
|||
if (refresh) { |
|||
fetch_jsons(); |
|||
refresh = false; |
|||
} |
|||
}); |
|||
|
|||
if (typeof add_title_collector != "undefined") |
|||
add_title_collector(function() { |
|||
if (!status) return 0; |
|||
var sum = 0; |
|||
for (var bid in status) { |
|||
if (status[bid].new_threads) { |
|||
sum += status[bid].new_threads; |
|||
if (!status[bid].threads) continue; |
|||
for (var tid in status[bid].threads) { |
|||
if (status[bid].threads[tid] > 0) { |
|||
if (auto_reload_enabled && active_page == "thread") { |
|||
var board = $('form[name="post"] input[name="board"]').val(); |
|||
var thread = $('form[name="post"] input[name="thread"]').val(); |
|||
|
|||
if (board == bid && thread == tid) continue; |
|||
} |
|||
sum += status[bid].threads[tid]; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return sum; |
|||
}); |
|||
|
|||
update_pinned(); |
|||
fetch_jsons(); |
|||
setInterval(fetch_jsons, 10000); |
|||
}); |
Loading…
Reference in new issue