##// END OF EJS Templates
Use thread autoupdate only if websockets available
Use thread autoupdate only if websockets available

File last commit:

r856:a65846d0 default
r856:a65846d0 default
Show More
thread_update.js
280 lines | 7.6 KiB | application/javascript | JavascriptLexer
/*
@licstart The following is the entire license notice for the
JavaScript code in this page.
Copyright (C) 2013 neko259
The JavaScript code in this page is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this page.
*/
var wsUrl = 'ws://localhost:9090/connection/websocket';
var wsUser = '';
var loading = false;
var lastUpdateTime = null;
var unreadPosts = 0;
// Thread ID does not change, can be stored one time
var threadId = $('div.thread').children('.post').first().attr('id');
function connectWebsocket() {
var metapanel = $('.metapanel')[0];
var wsHost = metapanel.getAttribute('data-ws-host');
var wsPort = metapanel.getAttribute('data-ws-port');
if (wsHost.length > 0 && wsPort.length > 0)
var centrifuge = new Centrifuge({
"url": 'ws://' + wsHost + ':' + wsPort + "/connection/websocket",
"project": metapanel.getAttribute('data-ws-project'),
"user": wsUser,
"timestamp": metapanel.getAttribute('data-last-update'),
"token": metapanel.getAttribute('data-ws-token'),
"debug": false
});
centrifuge.on('error', function(error_message) {
alert("Error connecting to websocket server.");
});
centrifuge.on('connect', function() {
var channelName = 'thread:' + threadId;
centrifuge.subscribe(channelName, function(message) {
var postHtml = message.data['html'];
var isAdded = (message.data['diff_type'] === 'added');
if (postHtml) {
updatePost(postHtml, isAdded);
}
});
$('#autoupdate').text('[+]');
});
centrifuge.connect();
}
function updatePost(postHtml, isAdded) {
// This needs to be set on start because the page is scrolled after posts
// are added or updated
var bottom = isPageBottom();
var post = $(postHtml);
var threadPosts = $('div.thread').children('.post');
var lastUpdate = '';
if (isAdded) {
var lastPost = threadPosts.last();
post.appendTo(lastPost.parent());
updateBumplimitProgress(1);
showNewPostsTitle(1);
lastUpdate = post.children('.post-info').first()
.children('.pub_time').first().text();
if (bottom) {
scrollToBottom();
}
} else {
var postId = post.attr('id');
var oldPost = $('div.thread').children('.post[id=' + postId + ']');
oldPost.replaceWith(post);
}
processNewPost(post);
updateMetadataPanel(lastUpdate)
}
function blink(node) {
var blinkCount = 2;
var nodeToAnimate = node;
for (var i = 0; i < blinkCount; i++) {
nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0);
}
}
function isPageBottom() {
var scroll = $(window).scrollTop() / ($(document).height()
- $(window).height());
return scroll == 1
}
function initAutoupdate() {
connectWebsocket();
}
function getReplyCount() {
return $('.thread').children('.post').length
}
function getImageCount() {
return $('.thread').find('img').length
}
function updateMetadataPanel(lastUpdate) {
var replyCountField = $('#reply-count');
var imageCountField = $('#image-count');
replyCountField.text(getReplyCount());
imageCountField.text(getImageCount());
if (lastUpdate !== '') {
var lastUpdateField = $('#last-update');
lastUpdateField.text(lastUpdate);
blink(lastUpdateField);
}
blink(replyCountField);
blink(imageCountField);
}
/**
* Update bumplimit progress bar
*/
function updateBumplimitProgress(postDelta) {
var progressBar = $('#bumplimit_progress');
if (progressBar) {
var postsToLimitElement = $('#left_to_limit');
var oldPostsToLimit = parseInt(postsToLimitElement.text());
var postCount = getReplyCount();
var bumplimit = postCount - postDelta + oldPostsToLimit;
var newPostsToLimit = bumplimit - postCount;
if (newPostsToLimit <= 0) {
$('.bar-bg').remove();
$('.thread').children('.post').addClass('dead_post');
} else {
postsToLimitElement.text(newPostsToLimit);
progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
}
}
}
var documentOriginalTitle = '';
/**
* Show 'new posts' text in the title if the document is not visible to a user
*/
function showNewPostsTitle(newPostCount) {
if (document.hidden) {
if (documentOriginalTitle === '') {
documentOriginalTitle = document.title;
}
unreadPosts = unreadPosts + newPostCount;
document.title = '[' + unreadPosts + '] ' + documentOriginalTitle;
document.addEventListener('visibilitychange', function() {
if (documentOriginalTitle !== '') {
document.title = documentOriginalTitle;
documentOriginalTitle = '';
unreadPosts = 0;
}
document.removeEventListener('visibilitychange', null);
});
}
}
/**
* Clear all entered values in the form fields
*/
function resetForm(form) {
form.find('input:text, input:password, input:file, select, textarea').val('');
form.find('input:radio, input:checkbox')
.removeAttr('checked').removeAttr('selected');
$('.file_wrap').find('.file-thumb').remove();
}
/**
* When the form is posted, this method will be run as a callback
*/
function updateOnPost(response, statusText, xhr, form) {
var json = $.parseJSON(response);
var status = json.status;
showAsErrors(form, '');
if (status === 'ok') {
resetForm(form);
} else {
var errors = json.errors;
for (var i = 0; i < errors.length; i++) {
var fieldErrors = errors[i];
var error = fieldErrors.errors;
showAsErrors(form, error);
}
}
}
/**
* Show text in the errors row of the form.
* @param form
* @param text
*/
function showAsErrors(form, text) {
form.children('.form-errors').remove();
if (text.length > 0) {
var errorList = $('<div class="form-errors">' + text
+ '<div>');
errorList.appendTo(form);
}
}
/**
* Run js methods that are usually run on the document, on the new post
*/
function processNewPost(post) {
addRefLinkPreview(post[0]);
highlightCode(post);
blink(post);
}
$(document).ready(function(){
if ('WebSocket' in window) {
initAutoupdate();
// Post form data over AJAX
var threadId = $('div.thread').children('.post').first().attr('id');
var form = $('#form');
var options = {
beforeSubmit: function(arr, $form, options) {
showAsErrors($('form'), gettext('Sending message...'));
},
success: updateOnPost,
url: '/api/add_post/' + threadId + '/'
};
form.ajaxForm(options);
resetForm(form);
}
});