##// END OF EJS Templates
Use thread autoupdate only if websockets available
neko259 -
r856:a65846d0 default
parent child Browse files
Show More
@@ -1,278 +1,280 b''
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 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 wsUrl = 'ws://localhost:9090/connection/websocket';
27 27 var wsUser = '';
28 28
29 29 var loading = false;
30 30 var lastUpdateTime = null;
31 31 var unreadPosts = 0;
32 32
33 33 // Thread ID does not change, can be stored one time
34 34 var threadId = $('div.thread').children('.post').first().attr('id');
35 35
36 36 function connectWebsocket() {
37 37 var metapanel = $('.metapanel')[0];
38 38
39 39 var wsHost = metapanel.getAttribute('data-ws-host');
40 40 var wsPort = metapanel.getAttribute('data-ws-port');
41 41
42 42 if (wsHost.length > 0 && wsPort.length > 0)
43 43 var centrifuge = new Centrifuge({
44 44 "url": 'ws://' + wsHost + ':' + wsPort + "/connection/websocket",
45 45 "project": metapanel.getAttribute('data-ws-project'),
46 46 "user": wsUser,
47 47 "timestamp": metapanel.getAttribute('data-last-update'),
48 48 "token": metapanel.getAttribute('data-ws-token'),
49 49 "debug": false
50 50 });
51 51
52 52 centrifuge.on('error', function(error_message) {
53 53 alert("Error connecting to websocket server.");
54 54 });
55 55
56 56 centrifuge.on('connect', function() {
57 57 var channelName = 'thread:' + threadId;
58 58 centrifuge.subscribe(channelName, function(message) {
59 59 var postHtml = message.data['html'];
60 60 var isAdded = (message.data['diff_type'] === 'added');
61 61
62 62 if (postHtml) {
63 63 updatePost(postHtml, isAdded);
64 64 }
65 65 });
66 66
67 67 $('#autoupdate').text('[+]');
68 68 });
69 69
70 70 centrifuge.connect();
71 71 }
72 72
73 73 function updatePost(postHtml, isAdded) {
74 74 // This needs to be set on start because the page is scrolled after posts
75 75 // are added or updated
76 76 var bottom = isPageBottom();
77 77
78 78 var post = $(postHtml);
79 79
80 80 var threadPosts = $('div.thread').children('.post');
81 81
82 82 var lastUpdate = '';
83 83
84 84 if (isAdded) {
85 85 var lastPost = threadPosts.last();
86 86
87 87 post.appendTo(lastPost.parent());
88 88
89 89 updateBumplimitProgress(1);
90 90 showNewPostsTitle(1);
91 91
92 92 lastUpdate = post.children('.post-info').first()
93 93 .children('.pub_time').first().text();
94 94
95 95 if (bottom) {
96 96 scrollToBottom();
97 97 }
98 98 } else {
99 99 var postId = post.attr('id');
100 100
101 101 var oldPost = $('div.thread').children('.post[id=' + postId + ']');
102 102
103 103 oldPost.replaceWith(post);
104 104 }
105 105
106 106 processNewPost(post);
107 107 updateMetadataPanel(lastUpdate)
108 108 }
109 109
110 110 function blink(node) {
111 111 var blinkCount = 2;
112 112
113 113 var nodeToAnimate = node;
114 114 for (var i = 0; i < blinkCount; i++) {
115 115 nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0);
116 116 }
117 117 }
118 118
119 119 function isPageBottom() {
120 120 var scroll = $(window).scrollTop() / ($(document).height()
121 121 - $(window).height());
122 122
123 123 return scroll == 1
124 124 }
125 125
126 126 function initAutoupdate() {
127 connectWebsocket()
127 connectWebsocket();
128 128 }
129 129
130 130 function getReplyCount() {
131 131 return $('.thread').children('.post').length
132 132 }
133 133
134 134 function getImageCount() {
135 135 return $('.thread').find('img').length
136 136 }
137 137
138 138 function updateMetadataPanel(lastUpdate) {
139 139 var replyCountField = $('#reply-count');
140 140 var imageCountField = $('#image-count');
141 141
142 142 replyCountField.text(getReplyCount());
143 143 imageCountField.text(getImageCount());
144 144
145 145 if (lastUpdate !== '') {
146 146 var lastUpdateField = $('#last-update');
147 147 lastUpdateField.text(lastUpdate);
148 148 blink(lastUpdateField);
149 149 }
150 150
151 151 blink(replyCountField);
152 152 blink(imageCountField);
153 153 }
154 154
155 155 /**
156 156 * Update bumplimit progress bar
157 157 */
158 158 function updateBumplimitProgress(postDelta) {
159 159 var progressBar = $('#bumplimit_progress');
160 160 if (progressBar) {
161 161 var postsToLimitElement = $('#left_to_limit');
162 162
163 163 var oldPostsToLimit = parseInt(postsToLimitElement.text());
164 164 var postCount = getReplyCount();
165 165 var bumplimit = postCount - postDelta + oldPostsToLimit;
166 166
167 167 var newPostsToLimit = bumplimit - postCount;
168 168 if (newPostsToLimit <= 0) {
169 169 $('.bar-bg').remove();
170 170 $('.thread').children('.post').addClass('dead_post');
171 171 } else {
172 172 postsToLimitElement.text(newPostsToLimit);
173 173 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
174 174 }
175 175 }
176 176 }
177 177
178 178 var documentOriginalTitle = '';
179 179 /**
180 180 * Show 'new posts' text in the title if the document is not visible to a user
181 181 */
182 182 function showNewPostsTitle(newPostCount) {
183 183 if (document.hidden) {
184 184 if (documentOriginalTitle === '') {
185 185 documentOriginalTitle = document.title;
186 186 }
187 187 unreadPosts = unreadPosts + newPostCount;
188 188 document.title = '[' + unreadPosts + '] ' + documentOriginalTitle;
189 189
190 190 document.addEventListener('visibilitychange', function() {
191 191 if (documentOriginalTitle !== '') {
192 192 document.title = documentOriginalTitle;
193 193 documentOriginalTitle = '';
194 194 unreadPosts = 0;
195 195 }
196 196
197 197 document.removeEventListener('visibilitychange', null);
198 198 });
199 199 }
200 200 }
201 201
202 202 /**
203 203 * Clear all entered values in the form fields
204 204 */
205 205 function resetForm(form) {
206 206 form.find('input:text, input:password, input:file, select, textarea').val('');
207 207 form.find('input:radio, input:checkbox')
208 208 .removeAttr('checked').removeAttr('selected');
209 209 $('.file_wrap').find('.file-thumb').remove();
210 210 }
211 211
212 212 /**
213 213 * When the form is posted, this method will be run as a callback
214 214 */
215 215 function updateOnPost(response, statusText, xhr, form) {
216 216 var json = $.parseJSON(response);
217 217 var status = json.status;
218 218
219 219 showAsErrors(form, '');
220 220
221 221 if (status === 'ok') {
222 222 resetForm(form);
223 223 } else {
224 224 var errors = json.errors;
225 225 for (var i = 0; i < errors.length; i++) {
226 226 var fieldErrors = errors[i];
227 227
228 228 var error = fieldErrors.errors;
229 229
230 230 showAsErrors(form, error);
231 231 }
232 232 }
233 233 }
234 234
235 235 /**
236 236 * Show text in the errors row of the form.
237 237 * @param form
238 238 * @param text
239 239 */
240 240 function showAsErrors(form, text) {
241 241 form.children('.form-errors').remove();
242 242
243 243 if (text.length > 0) {
244 244 var errorList = $('<div class="form-errors">' + text
245 245 + '<div>');
246 246 errorList.appendTo(form);
247 247 }
248 248 }
249 249
250 250 /**
251 251 * Run js methods that are usually run on the document, on the new post
252 252 */
253 253 function processNewPost(post) {
254 254 addRefLinkPreview(post[0]);
255 255 highlightCode(post);
256 256 blink(post);
257 257 }
258 258
259 259 $(document).ready(function(){
260 initAutoupdate();
260 if ('WebSocket' in window) {
261 initAutoupdate();
261 262
262 // Post form data over AJAX
263 var threadId = $('div.thread').children('.post').first().attr('id');
263 // Post form data over AJAX
264 var threadId = $('div.thread').children('.post').first().attr('id');
264 265
265 var form = $('#form');
266 var form = $('#form');
266 267
267 var options = {
268 beforeSubmit: function(arr, $form, options) {
269 showAsErrors($('form'), gettext('Sending message...'));
270 },
271 success: updateOnPost,
272 url: '/api/add_post/' + threadId + '/'
273 };
268 var options = {
269 beforeSubmit: function(arr, $form, options) {
270 showAsErrors($('form'), gettext('Sending message...'));
271 },
272 success: updateOnPost,
273 url: '/api/add_post/' + threadId + '/'
274 };
274 275
275 form.ajaxForm(options);
276 form.ajaxForm(options);
276 277
277 resetForm(form);
278 resetForm(form);
279 }
278 280 });
General Comments 0
You need to be logged in to leave comments. Login now