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