@ -19,23 +19,23 @@
// From http://stackoverflow.com/a/14035162
$ . fn . scrollStopped = function ( callback ) {
$ ( this ) . scroll ( function ( ) {
var self = this , $this = $ ( self ) ;
if ( $this . data ( 'scrollTimeout' ) ) {
clearTimeout ( $this . data ( 'scrollTimeout' ) ) ;
}
$this . data ( 'scrollTimeout' , setTimeout ( callback , 250 , self ) ) ;
} ) ;
$ ( this ) . scroll ( function ( ) {
var self = this , $this = $ ( self ) ;
if ( $this . data ( 'scrollTimeout' ) ) {
clearTimeout ( $this . data ( 'scrollTimeout' ) ) ;
}
$this . data ( 'scrollTimeout' , setTimeout ( callback , 250 , self ) ) ;
} ) ;
} ;
function makeIcon ( mode ) {
var favicon = $ ( "link[rel='shortcut icon']" ) ;
var favicon = $ ( "link[rel='shortcut icon']" ) ;
if ( ! favicon . length ) {
var favicon = $ ( '<link rel="shortcut icon"></link>' ) . appendTo ( 'head' ) ;
}
if ( ! favicon . length ) {
var favicon = $ ( '<link rel="shortcut icon"></link>' ) . appendTo ( 'head' ) ;
}
$ ( "link[rel='shortcut icon']" ) . attr ( "href" , configRoot + "static/favicon" + ( mode ? "-" + mode : "" ) + ".ico" ) ;
$ ( "link[rel='shortcut icon']" ) . attr ( "href" , configRoot + "static/favicon" + ( mode ? "-" + mode : "" ) + ".ico" ) ;
}
+ function ( ) {
@ -43,297 +43,305 @@ var notify = false;
auto_reload_enabled = true ; // for watch.js to interop
$ ( document ) . ready ( function ( ) {
if ( $ ( 'div.banner' ) . length == 0 )
{
return ; // not index
}
if ( $ ( ".post.op" ) . length != 1 )
{
return ; //not thread page
}
// Adds Options panel item
if ( typeof localStorage . auto_thread_update === 'undefined' ) {
localStorage . auto_thread_update = 'true' ; //default value
}
if ( window . Options && Options . get_tab ( 'general' ) ) {
Options . extend_tab ( "general" , "<fieldset id='auto-update-fs'><legend>" + _ ( "Auto update" ) + "</legend>"
+ ( '<label id="auto-thread-update"><input type="checkbox">' + _ ( 'Auto update thread' ) + '</label>' )
+ ( '<label id="auto_thread_desktop_notifications"><input type="checkbox">' + _ ( 'Show desktop notifications when users quote me' ) + '</label>' )
+ ( '<label id="auto_thread_desktop_notifications_all"><input type="checkbox">' + _ ( 'Show desktop notifications on all replies' ) + '</label>' )
+ '</fieldset>' ) ;
$ ( '#auto-thread-update>input' ) . on ( 'click' , function ( ) {
if ( $ ( '#auto-thread-update>input' ) . is ( ':checked' ) ) {
localStorage . auto_thread_update = 'true' ;
} else {
localStorage . auto_thread_update = 'false' ;
}
} ) ;
$ ( '#auto_thread_desktop_notifications>input,#auto_thread_desktop_notifications_all>input' ) . on ( 'click' , function ( ) {
if ( ! ( "Notification" in window ) ) return ;
var setting = $ ( this ) . parent ( ) . attr ( 'id' ) ;
if ( $ ( this ) . is ( ':checked' ) ) {
Notification . requestPermission ( function ( permission ) {
if ( permission === "granted" ) {
localStorage [ setting ] = 'true' ;
}
} ) ;
if ( Notification . permission === "granted" ) {
localStorage [ setting ] = 'true' ;
}
} else {
localStorage [ setting ] = 'false' ;
}
} ) ;
if ( localStorage . auto_thread_update === 'true' ) {
$ ( '#auto-thread-update>input' ) . prop ( 'checked' , true ) ;
}
if ( localStorage . auto_thread_desktop_notifications === 'true' ) {
$ ( '#auto_thread_desktop_notifications>input' ) . prop ( 'checked' , true ) ;
notify = "mention" ;
}
if ( localStorage . auto_thread_desktop_notifications_all === 'true' ) {
$ ( '#auto_thread_desktop_notifications_all>input' ) . prop ( 'checked' , true ) ;
notify = "all" ;
}
}
// not thread
if ( active_page != 'thread' )
return ;
var countdown_interval ;
// Add an update link
$ ( ".threadlinks span:last-child" ) . append ( "<span id='updater'><a href='#' id='update_thread'>[" + _ ( "Update" ) + "]</a> (<input type='checkbox' id='auto_update_status'> " + _ ( "Auto" ) + ") <span id='update_secs'></span></span>" ) ;
// Set the updater checkbox according to user setting
if ( localStorage . auto_thread_update === 'true' ) {
$ ( '#auto_update_status' ) . prop ( 'checked' , true ) ;
}
// Grab the settings
var settings = new script_settings ( 'auto-reload' ) ;
var poll_interval_mindelay = settings . get ( 'min_delay_bottom' , 5000 ) ;
var poll_interval_maxdelay = settings . get ( 'max_delay' , 600000 ) ;
var poll_interval_errordelay = settings . get ( 'error_delay' , 30000 ) ;
// number of ms to wait before reloading
var poll_interval_delay = poll_interval_mindelay ;
var poll_current_time = poll_interval_delay ;
var end_of_page = false ;
var new_posts = 0 ;
var first_new_post = null ;
var title = document . title ;
if ( typeof update_title == "undefined" ) {
var update_title = function ( ) {
if ( new_posts ) {
document . title = "(" + new_posts + ") " + title ;
} else {
document . title = title ;
makeIcon ( false ) ;
}
} ;
}
if ( typeof add_title_collector != "undefined" )
add_title_collector ( function ( ) {
return new_posts ;
} ) ;
var window_active = true ;
$ ( window ) . focus ( function ( ) {
window_active = true ;
recheck_activated ( ) ;
// Reset the delay if needed
if ( settings . get ( 'reset_focus' , true ) ) {
poll_interval_delay = poll_interval_mindelay ;
}
} ) ;
$ ( window ) . blur ( function ( ) {
window_active = false ;
} ) ;
$ ( '#auto_update_status' ) . click ( function ( ) {
if ( $ ( "#auto_update_status" ) . is ( ':checked' ) ) {
auto_update ( poll_interval_mindelay ) ;
} else {
stop_auto_update ( ) ;
$ ( '#update_secs' ) . text ( "" ) ;
}
} ) ;
var decrement_timer = function ( ) {
poll_current_time = poll_current_time - 1000 ;
$ ( '#update_secs' ) . text ( poll_current_time / 1000 ) ;
if ( poll_current_time <= 0 ) {
poll ( manualUpdate = false ) ;
}
}
var recheck_activated = function ( end_of_page ) {
if ( typeof end_of_page == "undefined" ) var end_of_page = false ;
if ( end_of_page || ( new_posts && window_active &&
$ ( window ) . scrollTop ( ) + $ ( window ) . height ( ) >=
$ ( 'div.boardlist.bottom' ) . position ( ) . top ) ) {
new_posts = 0 ;
}
update_title ( ) ;
first_new_post = null ;
} ;
// automatically updates the thread after a specified delay
var auto_update = function ( delay ) {
clearInterval ( countdown_interval ) ;
poll_current_time = delay ;
countdown_interval = setInterval ( decrement_timer , 1000 ) ;
$ ( '#update_secs' ) . text ( poll_current_time / 1000 ) ;
}
var stop_auto_update = function ( ) {
clearInterval ( countdown_interval ) ;
}
var epoch = ( new Date ) . getTime ( ) ;
var epochold = epoch ;
var timeDiff = function ( delay ) {
if ( ( epoch - epochold ) > delay ) {
epochold = epoch = ( new Date ) . getTime ( ) ;
return true ;
} else {
epoch = ( new Date ) . getTime ( ) ;
return ;
}
}
var poll = function ( manualUpdate ) {
stop_auto_update ( ) ;
$ ( '#update_secs' ) . text ( _ ( "Updating..." ) ) ;
$ . ajax ( {
url : document . location ,
success : function ( data ) {
var loaded_posts = 0 ; // the number of new posts loaded in this update
$ ( data ) . find ( 'div.post.reply' ) . each ( function ( ) {
var id = $ ( this ) . attr ( 'id' ) ;
if ( $ ( '#' + id ) . length == 0 ) {
if ( ! new_posts ) {
first_new_post = this ;
makeIcon ( 'reply' ) ;
if ( notify === "all" || ( notify === "mention" && $ ( this ) . find ( '.own_post' ) . length ) ) {
var body = $ ( this ) . children ( '.body' ) . html ( ) . replace ( /<br\s*[\/]?>/gi , "\n" ) ;
var n = new Notification ( "New reply to " + $ ( 'title' ) . text ( ) , { body : $ ( '<div/>' ) . html ( body ) . text ( ) } ) ;
}
}
if ( $ ( "div.post" ) . length > 1 ) {
$ ( this ) . parent ( ) . insertAfter ( $ ( 'div.post:not(.post-hover):last' ) . parent ( ) . next ( ) ) . after ( '<br class="clear">' ) ;
}
else {
$ ( this ) . insertAfter ( $ ( 'div.post:not(.post-hover):last' ) ) . after ( '<br class="clear">' ) ;
}
new_posts ++ ;
loaded_posts ++ ;
$ ( document ) . trigger ( 'new_post' , this ) ;
recheck_activated ( ) ;
}
} ) ;
time_loaded = Date . now ( ) ; // interop with watch.js
if ( $ ( '#auto_update_status' ) . is ( ':checked' ) ) {
// If there are no new posts, double the delay. Otherwise set it to the min.
if ( loaded_posts == 0 ) {
// if the update was manual, don't increase the delay
if ( manualUpdate == false ) {
poll_interval_delay *= 2 ;
// Don't increase the delay beyond the maximum
if ( poll_interval_delay > poll_interval_maxdelay ) {
poll_interval_delay = poll_interval_maxdelay ;
}
}
} else {
poll_interval_delay = poll_interval_mindelay ;
}
auto_update ( poll_interval_delay ) ;
} else {
// Decide the message to show if auto update is disabled
if ( loaded_posts > 0 )
$ ( '#update_secs' ) . text ( fmt ( _ ( "Thread updated with {0} new post(s)" ) , [ loaded_posts ] ) ) ;
else
$ ( '#update_secs' ) . text ( _ ( "No new posts found" ) ) ;
}
} ,
error : function ( xhr , status_text , error_text ) {
if ( status_text == "error" ) {
if ( error_text == "Not Found" ) {
$ ( '#update_secs' ) . text ( _ ( "Thread deleted or pruned" ) ) ;
$ ( '#auto_update_status' ) . prop ( 'checked' , false ) ;
$ ( '#auto_update_status' ) . prop ( 'disabled' , true ) ; // disable updates if thread is deleted
return ;
} else {
$ ( '#update_secs' ) . text ( "Error: " + error_text ) ;
}
} else if ( status_text ) {
$ ( '#update_secs' ) . text ( _ ( "Error: " ) + status_text ) ;
} else {
$ ( '#update_secs' ) . text ( _ ( "Unknown error" ) ) ;
}
// Keep trying to update
if ( $ ( '#auto_update_status' ) . is ( ':checked' ) ) {
poll_interval_delay = poll_interval_errordelay ;
auto_update ( poll_interval_delay ) ;
}
}
} ) ;
return false ;
} ;
$ ( post ) . on ( 'submit' , function ( e ) {
poll ( manualUpdate = true ) ;
dothis ( this ) ;
} ) ;
$ ( window ) . scrollStopped ( function ( ) {
// if the newest post is not visible
if ( $ ( this ) . scrollTop ( ) + $ ( this ) . height ( ) <
$ ( 'div.post:last' ) . position ( ) . top + $ ( 'div.post:last' ) . height ( ) ) {
end_of_page = false ;
} else {
if ( $ ( "#auto_update_status" ) . is ( ':checked' ) && timeDiff ( poll_interval_mindelay ) ) {
poll ( manualUpdate = true ) ;
}
end_of_page = true ;
}
recheck_activated ( end_of_page ) ;
} ) ;
$ ( '#update_thread' ) . on ( 'click' , function ( ) { poll ( manualUpdate = true ) ; return false ; } ) ;
if ( $ ( "#auto_update_status" ) . is ( ':checked' ) ) {
auto_update ( poll_interval_delay ) ;
}
if ( $ ( 'div.banner' ) . length == 0 )
{
return ; // not index
}
if ( $ ( ".post.op" ) . length != 1 )
{
return ; //not thread page
}
// Adds Options panel item
if ( typeof localStorage . auto_thread_update === 'undefined' ) {
localStorage . auto_thread_update = 'true' ; //default value
}
if ( window . Options && Options . get_tab ( 'general' ) ) {
Options . extend_tab ( "general" , "<fieldset id='auto-update-fs'><legend>" + _ ( "Auto update" ) + "</legend>"
+ ( '<label id="auto-thread-update"><input type="checkbox">' + _ ( 'Auto update thread' ) + '</label>' )
+ ( '<label id="auto_thread_desktop_notifications"><input type="checkbox">' + _ ( 'Show desktop notifications when users quote me' ) + '</label>' )
+ ( '<label id="auto_thread_desktop_notifications_all"><input type="checkbox">' + _ ( 'Show desktop notifications on all replies' ) + '</label>' )
+ '</fieldset>' ) ;
$ ( '#auto-thread-update>input' ) . on ( 'click' , function ( ) {
if ( $ ( '#auto-thread-update>input' ) . is ( ':checked' ) ) {
localStorage . auto_thread_update = 'true' ;
} else {
localStorage . auto_thread_update = 'false' ;
}
} ) ;
$ ( '#auto_thread_desktop_notifications>input,#auto_thread_desktop_notifications_all>input' ) . on ( 'click' , function ( ) {
if ( ! ( "Notification" in window ) ) return ;
var setting = $ ( this ) . parent ( ) . attr ( 'id' ) ;
if ( $ ( this ) . is ( ':checked' ) ) {
Notification . requestPermission ( function ( permission ) {
if ( permission === "granted" ) {
localStorage [ setting ] = 'true' ;
}
} ) ;
if ( Notification . permission === "granted" ) {
localStorage [ setting ] = 'true' ;
}
} else {
localStorage [ setting ] = 'false' ;
}
} ) ;
if ( localStorage . auto_thread_update === 'true' ) {
$ ( '#auto-thread-update>input' ) . prop ( 'checked' , true ) ;
}
if ( localStorage . auto_thread_desktop_notifications === 'true' ) {
$ ( '#auto_thread_desktop_notifications>input' ) . prop ( 'checked' , true ) ;
notify = "mention" ;
}
if ( localStorage . auto_thread_desktop_notifications_all === 'true' ) {
$ ( '#auto_thread_desktop_notifications_all>input' ) . prop ( 'checked' , true ) ;
notify = "all" ;
}
}
// not thread
if ( active_page != 'thread' )
return ;
var countdown_interval ;
// Add an update link
$ ( ".threadlinks span:last-child" ) . append ( "<span id='updater'><a href='#' id='update_thread'>[" + _ ( "Update" ) + "]</a> (<input type='checkbox' id='auto_update_status'> " + _ ( "Auto" ) + ") <span id='update_secs'></span></span>" ) ;
// Set the updater checkbox according to user setting
if ( localStorage . auto_thread_update === 'true' ) {
$ ( '#auto_update_status' ) . prop ( 'checked' , true ) ;
}
// Grab the settings
var settings = new script_settings ( 'auto-reload' ) ;
var poll_interval_mindelay = settings . get ( 'min_delay_bottom' , 5000 ) ;
var poll_interval_maxdelay = settings . get ( 'max_delay' , 600000 ) ;
var poll_interval_errordelay = settings . get ( 'error_delay' , 30000 ) ;
// number of ms to wait before reloading
var poll_interval_delay = poll_interval_mindelay ;
var poll_current_time = poll_interval_delay ;
var end_of_page = false ;
var new_posts = 0 ;
var first_new_post = null ;
var title = document . title ;
if ( typeof update_title == "undefined" ) {
var update_title = function ( ) {
if ( new_posts ) {
document . title = "(" + new_posts + ") " + title ;
} else {
document . title = title ;
makeIcon ( false ) ;
}
} ;
}
if ( typeof add_title_collector != "undefined" )
add_title_collector ( function ( ) {
return new_posts ;
} ) ;
var window_active = true ;
$ ( window ) . focus ( function ( ) {
window_active = true ;
recheck_activated ( ) ;
// Reset the delay if needed
if ( settings . get ( 'reset_focus' , true ) ) {
poll_interval_delay = poll_interval_mindelay ;
}
} ) ;
$ ( window ) . blur ( function ( ) {
window_active = false ;
} ) ;
$ ( '#auto_update_status' ) . click ( function ( ) {
if ( $ ( "#auto_update_status" ) . is ( ':checked' ) ) {
auto_update ( poll_interval_mindelay ) ;
} else {
stop_auto_update ( ) ;
$ ( '#update_secs' ) . text ( "" ) ;
}
} ) ;
var decrement_timer = function ( ) {
poll_current_time = poll_current_time - 1000 ;
$ ( '#update_secs' ) . text ( poll_current_time / 1000 ) ;
if ( poll_current_time <= 0 ) {
poll ( manualUpdate = false ) ;
}
}
var recheck_activated = function ( end_of_page ) {
if ( typeof end_of_page == "undefined" ) var end_of_page = false ;
if ( end_of_page || ( new_posts && window_active &&
$ ( window ) . scrollTop ( ) + $ ( window ) . height ( ) >=
$ ( 'div.boardlist.bottom' ) . position ( ) . top ) ) {
new_posts = 0 ;
}
update_title ( ) ;
first_new_post = null ;
} ;
// automatically updates the thread after a specified delay
var auto_update = function ( delay ) {
clearInterval ( countdown_interval ) ;
poll_current_time = delay ;
countdown_interval = setInterval ( decrement_timer , 1000 ) ;
$ ( '#update_secs' ) . text ( poll_current_time / 1000 ) ;
}
var stop_auto_update = function ( ) {
clearInterval ( countdown_interval ) ;
}
var epoch = ( new Date ) . getTime ( ) ;
var epochold = epoch ;
var timeDiff = function ( delay ) {
if ( ( epoch - epochold ) > delay ) {
epochold = epoch = ( new Date ) . getTime ( ) ;
return true ;
} else {
epoch = ( new Date ) . getTime ( ) ;
return ;
}
}
var poll = function ( manualUpdate ) {
stop_auto_update ( ) ;
$ ( '#update_secs' ) . text ( _ ( "Updating..." ) ) ;
$ . ajax ( {
url : document . location ,
success : function ( data ) {
var loaded_posts = 0 ; // the number of new posts loaded in this update
$ ( data ) . find ( 'div.post.reply' ) . each ( function ( ) {
var id = $ ( this ) . attr ( 'id' ) ;
// check that this post doesn't already exist
if ( $ ( '#' + id ) . length == 0 ) {
if ( ! new_posts ) {
first_new_post = this ;
makeIcon ( 'reply' ) ;
if ( notify === "all" || ( notify === "mention" && $ ( this ) . find ( '.own_post' ) . length ) ) {
var body = $ ( this ) . children ( '.body' ) . html ( ) . replace ( /<br\s*[\/]?>/gi , "\n" ) ;
var n = new Notification ( "New reply to " + $ ( 'title' ) . text ( ) , { body : $ ( '<div/>' ) . html ( body ) . text ( ) } ) ;
}
}
if ( $ ( "div.post" ) . length > 1 ) {
$ ( this ) . parent ( ) . insertAfter ( $ ( 'div.post:not(.post-hover):last' ) . parent ( ) . next ( ) ) . after ( '<br class="clear">' ) ;
}
else {
$ ( this ) . insertAfter ( $ ( 'div.post:not(.post-hover):last' ) ) . after ( '<br class="clear">' ) ;
}
new_posts ++ ;
loaded_posts ++ ;
$ ( document ) . trigger ( 'new_post' , this ) ;
recheck_activated ( ) ;
}
} ) ;
time_loaded = Date . now ( ) ; // interop with watch.js
if ( $ ( '#auto_update_status' ) . is ( ':checked' ) ) {
// If there are no new posts, double the delay. Otherwise set it to the min.
if ( loaded_posts == 0 ) {
// if the update was manual, don't increase the delay
if ( manualUpdate == false ) {
poll_interval_delay *= 2 ;
// Don't increase the delay beyond the maximum
if ( poll_interval_delay > poll_interval_maxdelay ) {
poll_interval_delay = poll_interval_maxdelay ;
}
}
} else {
poll_interval_delay = poll_interval_mindelay ;
}
auto_update ( poll_interval_delay ) ;
} else {
// Decide the message to show if auto update is disabled
if ( loaded_posts > 0 )
$ ( '#update_secs' ) . text ( fmt ( _ ( "Thread updated with {0} new post(s)" ) , [ loaded_posts ] ) ) ;
else
$ ( '#update_secs' ) . text ( _ ( "No new posts found" ) ) ;
}
} ,
error : function ( xhr , status_text , error_text ) {
if ( status_text == "error" ) {
if ( error_text == "Not Found" ) {
$ ( '#update_secs' ) . text ( _ ( "Thread deleted or pruned" ) ) ;
$ ( '#auto_update_status' ) . prop ( 'checked' , false ) ;
$ ( '#auto_update_status' ) . prop ( 'disabled' , true ) ; // disable updates if thread is deleted
return ;
} else {
$ ( '#update_secs' ) . text ( "Error: " + error_text ) ;
}
} else if ( status_text ) {
$ ( '#update_secs' ) . text ( _ ( "Error: " ) + status_text ) ;
} else {
$ ( '#update_secs' ) . text ( _ ( "Unknown error" ) ) ;
}
// Keep trying to update
if ( $ ( '#auto_update_status' ) . is ( ':checked' ) ) {
poll_interval_delay = poll_interval_errordelay ;
auto_update ( poll_interval_delay ) ;
}
}
} ) ;
return false ;
} ;
$ ( post ) . on ( 'submit' , function ( e ) {
setTimeout (
function ( ) {
poll ( manualUpdate = true )
} ,
500
) ;
} ) ;
$ ( window ) . scrollStopped ( function ( ) {
// if the newest post is not visible
if ( $ ( this ) . scrollTop ( ) + $ ( this ) . height ( ) <
$ ( 'div.post:last' ) . position ( ) . top + $ ( 'div.post:last' ) . height ( ) ) {
end_of_page = false ;
} else {
if ( $ ( "#auto_update_status" ) . is ( ':checked' ) && timeDiff ( poll_interval_mindelay ) ) {
poll ( manualUpdate = true ) ;
}
end_of_page = true ;
}
recheck_activated ( end_of_page ) ;
} ) ;
$ ( '#update_thread' ) . on ( 'click' , function ( ) { poll ( manualUpdate = true ) ; return false ; } ) ;
if ( $ ( "#auto_update_status" ) . is ( ':checked' ) ) {
auto_update ( poll_interval_delay ) ;
}
} ) ;
} ( ) ;