##// END OF EJS Templates
Don't update metadata panel on thread opening
neko259 -
r1074:7609c920 default
parent child Browse files
Show More
@@ -1,331 +1,336
1 1 /*
2 2 @licstart The following is the entire license notice for the
3 3 JavaScript code in this page.
4 4
5 5
6 6 Copyright (C) 2013-2014 neko259
7 7
8 8 The JavaScript code in this page is free software: you can
9 9 redistribute it and/or modify it under the terms of the GNU
10 10 General Public License (GNU GPL) as published by the Free Software
11 11 Foundation, either version 3 of the License, or (at your option)
12 12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15 15
16 16 As additional permission under GNU GPL version 3 section 7, you
17 17 may distribute non-source (e.g., minimized or compacted) forms of
18 18 that code without the copy of the GNU GPL normally required by
19 19 section 4, provided you include this license notice and a URL
20 20 through which recipients can access the Corresponding Source.
21 21
22 22 @licend The above is the entire license notice
23 23 for the JavaScript code in this page.
24 24 */
25 25
26 26 var wsUser = '';
27 27
28 28 var unreadPosts = 0;
29 29 var documentOriginalTitle = '';
30 30
31 31 // Thread ID does not change, can be stored one time
32 32 var threadId = $('div.thread').children('.post').first().attr('id');
33 33
34 34 /**
35 35 * Connect to websocket server and subscribe to thread updates. On any update we
36 36 * request a thread diff.
37 37 *
38 38 * @returns {boolean} true if connected, false otherwise
39 39 */
40 40 function connectWebsocket() {
41 41 var metapanel = $('.metapanel')[0];
42 42
43 43 var wsHost = metapanel.getAttribute('data-ws-host');
44 44 var wsPort = metapanel.getAttribute('data-ws-port');
45 45
46 46 if (wsHost.length > 0 && wsPort.length > 0)
47 47 var centrifuge = new Centrifuge({
48 48 "url": 'ws://' + wsHost + ':' + wsPort + "/connection/websocket",
49 49 "project": metapanel.getAttribute('data-ws-project'),
50 50 "user": wsUser,
51 51 "timestamp": metapanel.getAttribute('data-last-update'),
52 52 "token": metapanel.getAttribute('data-ws-token'),
53 53 "debug": false
54 54 });
55 55
56 56 centrifuge.on('error', function(error_message) {
57 57 console.log("Error connecting to websocket server.");
58 58 return false;
59 59 });
60 60
61 61 centrifuge.on('connect', function() {
62 62 var channelName = 'thread:' + threadId;
63 63 centrifuge.subscribe(channelName, function(message) {
64 64 getThreadDiff();
65 65 });
66 66
67 67 // For the case we closed the browser and missed some updates
68 68 getThreadDiff();
69 69 $('#autoupdate').hide();
70 70 });
71 71
72 72 centrifuge.connect();
73 73
74 74 return true;
75 75 }
76 76
77 77 /**
78 78 * Get diff of the posts from the current thread timestamp.
79 79 * This is required if the browser was closed and some post updates were
80 80 * missed.
81 81 */
82 82 function getThreadDiff() {
83 83 var lastUpdateTime = $('.metapanel').attr('data-last-update');
84 84
85 85 var diffUrl = '/api/diff_thread/' + threadId + '/' + lastUpdateTime + '/';
86 86
87 87 $.getJSON(diffUrl)
88 88 .success(function(data) {
89 89 var addedPosts = data.added;
90 var hasMetaUpdates = false;
90 91
91 92 for (var i = 0; i < addedPosts.length; i++) {
92 93 var postText = addedPosts[i];
93 94 var post = $(postText);
94 95
95 updatePost(post)
96 updatePost(post);
97 hasMetaUpdates = true;
96 98 }
97 99
98 100 var updatedPosts = data.updated;
99 101
100 102 for (var i = 0; i < updatedPosts.length; i++) {
101 103 var postText = updatedPosts[i];
102 104 var post = $(postText);
103 105
104 updatePost(post)
106 updatePost(post);
107 hasMetaUpdates = true;
105 108 }
106 109
107 updateMetadataPanel();
110 if (hasMetaUpdates) {
111 updateMetadataPanel();
112 }
108 113
109 114 // TODO Process removed posts if any
110 115 $('.metapanel').attr('data-last-update', data.last_update);
111 116 })
112 117 }
113 118
114 119 /**
115 120 * Add or update the post on html page.
116 121 */
117 122 function updatePost(postHtml) {
118 123 // This needs to be set on start because the page is scrolled after posts
119 124 // are added or updated
120 125 var bottom = isPageBottom();
121 126
122 127 var post = $(postHtml);
123 128
124 129 var threadBlock = $('div.thread');
125 130
126 131 var postId = post.attr('id');
127 132
128 133 // If the post already exists, replace it. Otherwise add as a new one.
129 134 var existingPosts = threadBlock.children('.post[id=' + postId + ']');
130 135
131 136 if (existingPosts.size() > 0) {
132 137 existingPosts.replaceWith(post);
133 138 } else {
134 139 var threadPosts = threadBlock.children('.post');
135 140 var lastPost = threadPosts.last();
136 141
137 142 post.appendTo(lastPost.parent());
138 143
139 144 updateBumplimitProgress(1);
140 145 showNewPostsTitle(1);
141 146
142 147 if (bottom) {
143 148 scrollToBottom();
144 149 }
145 150 }
146 151
147 152 processNewPost(post);
148 153 }
149 154
150 155 /**
151 156 * Initiate a blinking animation on a node to show it was updated.
152 157 */
153 158 function blink(node) {
154 159 var blinkCount = 2;
155 160
156 161 var nodeToAnimate = node;
157 162 for (var i = 0; i < blinkCount; i++) {
158 163 nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0);
159 164 }
160 165 }
161 166
162 167 function isPageBottom() {
163 168 var scroll = $(window).scrollTop() / ($(document).height()
164 169 - $(window).height());
165 170
166 171 return scroll == 1
167 172 }
168 173
169 174 function initAutoupdate() {
170 175 return connectWebsocket();
171 176 }
172 177
173 178 function getReplyCount() {
174 179 return $('.thread').children('.post').length
175 180 }
176 181
177 182 function getImageCount() {
178 183 return $('.thread').find('img').length
179 184 }
180 185
181 186 /**
182 187 * Update post count, images count and last update time in the metadata
183 188 * panel.
184 189 */
185 190 function updateMetadataPanel() {
186 191 var replyCountField = $('#reply-count');
187 192 var imageCountField = $('#image-count');
188 193
189 194 replyCountField.text(getReplyCount());
190 195 imageCountField.text(getImageCount());
191 196
192 197 var lastUpdate = $('.post:last').children('.post-info').first()
193 198 .children('.pub_time').first().html();
194 199 if (lastUpdate !== '') {
195 200 var lastUpdateField = $('#last-update');
196 201 lastUpdateField.html(lastUpdate);
197 202 blink(lastUpdateField);
198 203 }
199 204
200 205 blink(replyCountField);
201 206 blink(imageCountField);
202 207 }
203 208
204 209 /**
205 210 * Update bumplimit progress bar
206 211 */
207 212 function updateBumplimitProgress(postDelta) {
208 213 var progressBar = $('#bumplimit_progress');
209 214 if (progressBar) {
210 215 var postsToLimitElement = $('#left_to_limit');
211 216
212 217 var oldPostsToLimit = parseInt(postsToLimitElement.text());
213 218 var postCount = getReplyCount();
214 219 var bumplimit = postCount - postDelta + oldPostsToLimit;
215 220
216 221 var newPostsToLimit = bumplimit - postCount;
217 222 if (newPostsToLimit <= 0) {
218 223 $('.bar-bg').remove();
219 224 } else {
220 225 postsToLimitElement.text(newPostsToLimit);
221 226 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
222 227 }
223 228 }
224 229 }
225 230
226 231 /**
227 232 * Show 'new posts' text in the title if the document is not visible to a user
228 233 */
229 234 function showNewPostsTitle(newPostCount) {
230 235 if (document.hidden) {
231 236 if (documentOriginalTitle === '') {
232 237 documentOriginalTitle = document.title;
233 238 }
234 239 unreadPosts = unreadPosts + newPostCount;
235 240 document.title = '[' + unreadPosts + '] ' + documentOriginalTitle;
236 241
237 242 document.addEventListener('visibilitychange', function() {
238 243 if (documentOriginalTitle !== '') {
239 244 document.title = documentOriginalTitle;
240 245 documentOriginalTitle = '';
241 246 unreadPosts = 0;
242 247 }
243 248
244 249 document.removeEventListener('visibilitychange', null);
245 250 });
246 251 }
247 252 }
248 253
249 254 /**
250 255 * Clear all entered values in the form fields
251 256 */
252 257 function resetForm(form) {
253 258 form.find('input:text, input:password, input:file, select, textarea').val('');
254 259 form.find('input:radio, input:checkbox')
255 260 .removeAttr('checked').removeAttr('selected');
256 261 $('.file_wrap').find('.file-thumb').remove();
257 262 }
258 263
259 264 /**
260 265 * When the form is posted, this method will be run as a callback
261 266 */
262 267 function updateOnPost(response, statusText, xhr, form) {
263 268 var json = $.parseJSON(response);
264 269 var status = json.status;
265 270
266 271 showAsErrors(form, '');
267 272
268 273 if (status === 'ok') {
269 274 resetFormPosition();
270 275 resetForm(form);
271 276 getThreadDiff();
272 277 scrollToBottom();
273 278 } else {
274 279 var errors = json.errors;
275 280 for (var i = 0; i < errors.length; i++) {
276 281 var fieldErrors = errors[i];
277 282
278 283 var error = fieldErrors.errors;
279 284
280 285 showAsErrors(form, error);
281 286 }
282 287 }
283 288 }
284 289
285 290 /**
286 291 * Show text in the errors row of the form.
287 292 * @param form
288 293 * @param text
289 294 */
290 295 function showAsErrors(form, text) {
291 296 form.children('.form-errors').remove();
292 297
293 298 if (text.length > 0) {
294 299 var errorList = $('<div class="form-errors">' + text + '<div>');
295 300 errorList.appendTo(form);
296 301 }
297 302 }
298 303
299 304 /**
300 305 * Run js methods that are usually run on the document, on the new post
301 306 */
302 307 function processNewPost(post) {
303 308 addRefLinkPreview(post[0]);
304 309 highlightCode(post);
305 310 blink(post);
306 311 }
307 312
308 313 $(document).ready(function(){
309 314 if (initAutoupdate()) {
310 315 // Post form data over AJAX
311 316 var threadId = $('div.thread').children('.post').first().attr('id');
312 317
313 318 var form = $('#form');
314 319
315 320 if (form.length > 0) {
316 321 var options = {
317 322 beforeSubmit: function(arr, $form, options) {
318 323 showAsErrors($('form'), gettext('Sending message...'));
319 324 },
320 325 success: updateOnPost,
321 326 url: '/api/add_post/' + threadId + '/'
322 327 };
323 328
324 329 form.ajaxForm(options);
325 330
326 331 resetForm(form);
327 332 }
328 333 }
329 334
330 335 $('#autoupdate').click(getThreadDiff);
331 336 });
General Comments 0
You need to be logged in to leave comments. Login now