##// END OF EJS Templates
Increased posting AJAX timeout to prevent server errors when downloading a...
neko259 -
r1410:451d5821 default
parent child Browse files
Show More
@@ -1,457 +1,461 b''
1 /*
1 /*
2 @licstart The following is the entire license notice for the
2 @licstart The following is the entire license notice for the
3 JavaScript code in this page.
3 JavaScript code in this page.
4
4
5
5
6 Copyright (C) 2013-2014 neko259
6 Copyright (C) 2013-2014 neko259
7
7
8 The JavaScript code in this page is free software: you can
8 The JavaScript code in this page is free software: you can
9 redistribute it and/or modify it under the terms of the GNU
9 redistribute it and/or modify it under the terms of the GNU
10 General Public License (GNU GPL) as published by the Free Software
10 General Public License (GNU GPL) as published by the Free Software
11 Foundation, either version 3 of the License, or (at your option)
11 Foundation, either version 3 of the License, or (at your option)
12 any later version. The code is distributed WITHOUT ANY WARRANTY;
12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 without even the implied warranty of MERCHANTABILITY or FITNESS
13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15
15
16 As additional permission under GNU GPL version 3 section 7, you
16 As additional permission under GNU GPL version 3 section 7, you
17 may distribute non-source (e.g., minimized or compacted) forms of
17 may distribute non-source (e.g., minimized or compacted) forms of
18 that code without the copy of the GNU GPL normally required by
18 that code without the copy of the GNU GPL normally required by
19 section 4, provided you include this license notice and a URL
19 section 4, provided you include this license notice and a URL
20 through which recipients can access the Corresponding Source.
20 through which recipients can access the Corresponding Source.
21
21
22 @licend The above is the entire license notice
22 @licend The above is the entire license notice
23 for the JavaScript code in this page.
23 for the JavaScript code in this page.
24 */
24 */
25
25
26 var CLASS_POST = '.post'
26 var CLASS_POST = '.post'
27
27
28 var POST_ADDED = 0;
28 var POST_ADDED = 0;
29 var POST_UPDATED = 1;
29 var POST_UPDATED = 1;
30
30
31 // TODO These need to be syncronized with board settings.
31 var JS_AUTOUPDATE_PERIOD = 20000;
32 var JS_AUTOUPDATE_PERIOD = 20000;
33 // TODO This needs to be the same for attachment download time limit.
34 var POST_AJAX_TIMEOUT = 30000;
32
35
33 var ALLOWED_FOR_PARTIAL_UPDATE = [
36 var ALLOWED_FOR_PARTIAL_UPDATE = [
34 'refmap',
37 'refmap',
35 'post-info'
38 'post-info'
36 ];
39 ];
37
40
38 var ATTR_CLASS = 'class';
41 var ATTR_CLASS = 'class';
39 var ATTR_UID = 'data-uid';
42 var ATTR_UID = 'data-uid';
40
43
41 var wsUser = '';
44 var wsUser = '';
42
45
43 var unreadPosts = 0;
46 var unreadPosts = 0;
44 var documentOriginalTitle = '';
47 var documentOriginalTitle = '';
45
48
46 // Thread ID does not change, can be stored one time
49 // Thread ID does not change, can be stored one time
47 var threadId = $('div.thread').children(CLASS_POST).first().attr('id');
50 var threadId = $('div.thread').children(CLASS_POST).first().attr('id');
48
51
49 /**
52 /**
50 * Connect to websocket server and subscribe to thread updates. On any update we
53 * Connect to websocket server and subscribe to thread updates. On any update we
51 * request a thread diff.
54 * request a thread diff.
52 *
55 *
53 * @returns {boolean} true if connected, false otherwise
56 * @returns {boolean} true if connected, false otherwise
54 */
57 */
55 function connectWebsocket() {
58 function connectWebsocket() {
56 var metapanel = $('.metapanel')[0];
59 var metapanel = $('.metapanel')[0];
57
60
58 var wsHost = metapanel.getAttribute('data-ws-host');
61 var wsHost = metapanel.getAttribute('data-ws-host');
59 var wsPort = metapanel.getAttribute('data-ws-port');
62 var wsPort = metapanel.getAttribute('data-ws-port');
60
63
61 if (wsHost.length > 0 && wsPort.length > 0) {
64 if (wsHost.length > 0 && wsPort.length > 0) {
62 var centrifuge = new Centrifuge({
65 var centrifuge = new Centrifuge({
63 "url": 'ws://' + wsHost + ':' + wsPort + "/connection/websocket",
66 "url": 'ws://' + wsHost + ':' + wsPort + "/connection/websocket",
64 "project": metapanel.getAttribute('data-ws-project'),
67 "project": metapanel.getAttribute('data-ws-project'),
65 "user": wsUser,
68 "user": wsUser,
66 "timestamp": metapanel.getAttribute('data-ws-token-time'),
69 "timestamp": metapanel.getAttribute('data-ws-token-time'),
67 "token": metapanel.getAttribute('data-ws-token'),
70 "token": metapanel.getAttribute('data-ws-token'),
68 "debug": false
71 "debug": false
69 });
72 });
70
73
71 centrifuge.on('error', function(error_message) {
74 centrifuge.on('error', function(error_message) {
72 console.log("Error connecting to websocket server.");
75 console.log("Error connecting to websocket server.");
73 console.log(error_message);
76 console.log(error_message);
74 console.log("Using javascript update instead.");
77 console.log("Using javascript update instead.");
75
78
76 // If websockets don't work, enable JS update instead
79 // If websockets don't work, enable JS update instead
77 enableJsUpdate()
80 enableJsUpdate()
78 });
81 });
79
82
80 centrifuge.on('connect', function() {
83 centrifuge.on('connect', function() {
81 var channelName = 'thread:' + threadId;
84 var channelName = 'thread:' + threadId;
82 centrifuge.subscribe(channelName, function(message) {
85 centrifuge.subscribe(channelName, function(message) {
83 getThreadDiff();
86 getThreadDiff();
84 });
87 });
85
88
86 // For the case we closed the browser and missed some updates
89 // For the case we closed the browser and missed some updates
87 getThreadDiff();
90 getThreadDiff();
88 $('#autoupdate').hide();
91 $('#autoupdate').hide();
89 });
92 });
90
93
91 centrifuge.connect();
94 centrifuge.connect();
92
95
93 return true;
96 return true;
94 } else {
97 } else {
95 return false;
98 return false;
96 }
99 }
97 }
100 }
98
101
99 /**
102 /**
100 * Get diff of the posts from the current thread timestamp.
103 * Get diff of the posts from the current thread timestamp.
101 * This is required if the browser was closed and some post updates were
104 * This is required if the browser was closed and some post updates were
102 * missed.
105 * missed.
103 */
106 */
104 function getThreadDiff() {
107 function getThreadDiff() {
105 var all_posts = $('.post');
108 var all_posts = $('.post');
106
109
107 var uids = '';
110 var uids = '';
108 var posts = all_posts;
111 var posts = all_posts;
109 for (var i = 0; i < posts.length; i++) {
112 for (var i = 0; i < posts.length; i++) {
110 uids += posts[i].getAttribute('data-uid') + ' ';
113 uids += posts[i].getAttribute('data-uid') + ' ';
111 }
114 }
112
115
113 var data = {
116 var data = {
114 uids: uids,
117 uids: uids,
115 thread: threadId
118 thread: threadId
116 };
119 };
117
120
118 var diffUrl = '/api/diff_thread/';
121 var diffUrl = '/api/diff_thread/';
119
122
120 $.post(diffUrl,
123 $.post(diffUrl,
121 data,
124 data,
122 function(data) {
125 function(data) {
123 var updatedPosts = data.updated;
126 var updatedPosts = data.updated;
124 var addedPostCount = 0;
127 var addedPostCount = 0;
125
128
126 for (var i = 0; i < updatedPosts.length; i++) {
129 for (var i = 0; i < updatedPosts.length; i++) {
127 var postText = updatedPosts[i];
130 var postText = updatedPosts[i];
128 var post = $(postText);
131 var post = $(postText);
129
132
130 if (updatePost(post) == POST_ADDED) {
133 if (updatePost(post) == POST_ADDED) {
131 addedPostCount++;
134 addedPostCount++;
132 }
135 }
133 }
136 }
134
137
135 var hasMetaUpdates = updatedPosts.length > 0;
138 var hasMetaUpdates = updatedPosts.length > 0;
136 if (hasMetaUpdates) {
139 if (hasMetaUpdates) {
137 updateMetadataPanel();
140 updateMetadataPanel();
138 }
141 }
139
142
140 if (addedPostCount > 0) {
143 if (addedPostCount > 0) {
141 updateBumplimitProgress(addedPostCount);
144 updateBumplimitProgress(addedPostCount);
142 }
145 }
143
146
144 if (updatedPosts.length > 0) {
147 if (updatedPosts.length > 0) {
145 showNewPostsTitle(addedPostCount);
148 showNewPostsTitle(addedPostCount);
146 }
149 }
147
150
148 // TODO Process removed posts if any
151 // TODO Process removed posts if any
149 $('.metapanel').attr('data-last-update', data.last_update);
152 $('.metapanel').attr('data-last-update', data.last_update);
150 },
153 },
151 'json'
154 'json'
152 )
155 )
153 }
156 }
154
157
155 /**
158 /**
156 * Add or update the post on html page.
159 * Add or update the post on html page.
157 */
160 */
158 function updatePost(postHtml) {
161 function updatePost(postHtml) {
159 // This needs to be set on start because the page is scrolled after posts
162 // This needs to be set on start because the page is scrolled after posts
160 // are added or updated
163 // are added or updated
161 var bottom = isPageBottom();
164 var bottom = isPageBottom();
162
165
163 var post = $(postHtml);
166 var post = $(postHtml);
164
167
165 var threadBlock = $('div.thread');
168 var threadBlock = $('div.thread');
166
169
167 var postId = post.attr('id');
170 var postId = post.attr('id');
168
171
169 // If the post already exists, replace it. Otherwise add as a new one.
172 // If the post already exists, replace it. Otherwise add as a new one.
170 var existingPosts = threadBlock.children('.post[id=' + postId + ']');
173 var existingPosts = threadBlock.children('.post[id=' + postId + ']');
171
174
172 var type;
175 var type;
173
176
174 if (existingPosts.size() > 0) {
177 if (existingPosts.size() > 0) {
175 replacePartial(existingPosts.first(), post, false);
178 replacePartial(existingPosts.first(), post, false);
176 post = existingPosts.first();
179 post = existingPosts.first();
177
180
178 type = POST_UPDATED;
181 type = POST_UPDATED;
179 } else {
182 } else {
180 post.appendTo(threadBlock);
183 post.appendTo(threadBlock);
181
184
182 if (bottom) {
185 if (bottom) {
183 scrollToBottom();
186 scrollToBottom();
184 }
187 }
185
188
186 type = POST_ADDED;
189 type = POST_ADDED;
187 }
190 }
188
191
189 processNewPost(post);
192 processNewPost(post);
190
193
191 return type;
194 return type;
192 }
195 }
193
196
194 /**
197 /**
195 * Initiate a blinking animation on a node to show it was updated.
198 * Initiate a blinking animation on a node to show it was updated.
196 */
199 */
197 function blink(node) {
200 function blink(node) {
198 var blinkCount = 2;
201 var blinkCount = 2;
199
202
200 var nodeToAnimate = node;
203 var nodeToAnimate = node;
201 for (var i = 0; i < blinkCount; i++) {
204 for (var i = 0; i < blinkCount; i++) {
202 nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0);
205 nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0);
203 }
206 }
204 }
207 }
205
208
206 function isPageBottom() {
209 function isPageBottom() {
207 var scroll = $(window).scrollTop() / ($(document).height()
210 var scroll = $(window).scrollTop() / ($(document).height()
208 - $(window).height());
211 - $(window).height());
209
212
210 return scroll == 1
213 return scroll == 1
211 }
214 }
212
215
213 function enableJsUpdate() {
216 function enableJsUpdate() {
214 setInterval(getThreadDiff, JS_AUTOUPDATE_PERIOD);
217 setInterval(getThreadDiff, JS_AUTOUPDATE_PERIOD);
215 return true;
218 return true;
216 }
219 }
217
220
218 function initAutoupdate() {
221 function initAutoupdate() {
219 if (location.protocol === 'https:') {
222 if (location.protocol === 'https:') {
220 return enableJsUpdate();
223 return enableJsUpdate();
221 } else {
224 } else {
222 if (connectWebsocket()) {
225 if (connectWebsocket()) {
223 return true;
226 return true;
224 } else {
227 } else {
225 return enableJsUpdate();
228 return enableJsUpdate();
226 }
229 }
227 }
230 }
228 }
231 }
229
232
230 function getReplyCount() {
233 function getReplyCount() {
231 return $('.thread').children(CLASS_POST).length
234 return $('.thread').children(CLASS_POST).length
232 }
235 }
233
236
234 function getImageCount() {
237 function getImageCount() {
235 return $('.thread').find('img').length
238 return $('.thread').find('img').length
236 }
239 }
237
240
238 /**
241 /**
239 * Update post count, images count and last update time in the metadata
242 * Update post count, images count and last update time in the metadata
240 * panel.
243 * panel.
241 */
244 */
242 function updateMetadataPanel() {
245 function updateMetadataPanel() {
243 var replyCountField = $('#reply-count');
246 var replyCountField = $('#reply-count');
244 var imageCountField = $('#image-count');
247 var imageCountField = $('#image-count');
245
248
246 var replyCount = getReplyCount();
249 var replyCount = getReplyCount();
247 replyCountField.text(replyCount);
250 replyCountField.text(replyCount);
248 var imageCount = getImageCount();
251 var imageCount = getImageCount();
249 imageCountField.text(imageCount);
252 imageCountField.text(imageCount);
250
253
251 var lastUpdate = $('.post:last').children('.post-info').first()
254 var lastUpdate = $('.post:last').children('.post-info').first()
252 .children('.pub_time').first().html();
255 .children('.pub_time').first().html();
253 if (lastUpdate !== '') {
256 if (lastUpdate !== '') {
254 var lastUpdateField = $('#last-update');
257 var lastUpdateField = $('#last-update');
255 lastUpdateField.html(lastUpdate);
258 lastUpdateField.html(lastUpdate);
256 blink(lastUpdateField);
259 blink(lastUpdateField);
257 }
260 }
258
261
259 blink(replyCountField);
262 blink(replyCountField);
260 blink(imageCountField);
263 blink(imageCountField);
261
264
262 $('#message-count-text').text(ngettext('message', 'messages', replyCount));
265 $('#message-count-text').text(ngettext('message', 'messages', replyCount));
263 $('#image-count-text').text(ngettext('image', 'images', imageCount));
266 $('#image-count-text').text(ngettext('image', 'images', imageCount));
264 }
267 }
265
268
266 /**
269 /**
267 * Update bumplimit progress bar
270 * Update bumplimit progress bar
268 */
271 */
269 function updateBumplimitProgress(postDelta) {
272 function updateBumplimitProgress(postDelta) {
270 var progressBar = $('#bumplimit_progress');
273 var progressBar = $('#bumplimit_progress');
271 if (progressBar) {
274 if (progressBar) {
272 var postsToLimitElement = $('#left_to_limit');
275 var postsToLimitElement = $('#left_to_limit');
273
276
274 var oldPostsToLimit = parseInt(postsToLimitElement.text());
277 var oldPostsToLimit = parseInt(postsToLimitElement.text());
275 var postCount = getReplyCount();
278 var postCount = getReplyCount();
276 var bumplimit = postCount - postDelta + oldPostsToLimit;
279 var bumplimit = postCount - postDelta + oldPostsToLimit;
277
280
278 var newPostsToLimit = bumplimit - postCount;
281 var newPostsToLimit = bumplimit - postCount;
279 if (newPostsToLimit <= 0) {
282 if (newPostsToLimit <= 0) {
280 $('.bar-bg').remove();
283 $('.bar-bg').remove();
281 } else {
284 } else {
282 postsToLimitElement.text(newPostsToLimit);
285 postsToLimitElement.text(newPostsToLimit);
283 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
286 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
284 }
287 }
285 }
288 }
286 }
289 }
287
290
288 /**
291 /**
289 * Show 'new posts' text in the title if the document is not visible to a user
292 * Show 'new posts' text in the title if the document is not visible to a user
290 */
293 */
291 function showNewPostsTitle(newPostCount) {
294 function showNewPostsTitle(newPostCount) {
292 if (document.hidden) {
295 if (document.hidden) {
293 if (documentOriginalTitle === '') {
296 if (documentOriginalTitle === '') {
294 documentOriginalTitle = document.title;
297 documentOriginalTitle = document.title;
295 }
298 }
296 unreadPosts = unreadPosts + newPostCount;
299 unreadPosts = unreadPosts + newPostCount;
297
300
298 var newTitle = '* ';
301 var newTitle = '* ';
299 if (unreadPosts > 0) {
302 if (unreadPosts > 0) {
300 newTitle += '[' + unreadPosts + '] ';
303 newTitle += '[' + unreadPosts + '] ';
301 }
304 }
302 newTitle += documentOriginalTitle;
305 newTitle += documentOriginalTitle;
303
306
304 document.title = newTitle;
307 document.title = newTitle;
305
308
306 document.addEventListener('visibilitychange', function() {
309 document.addEventListener('visibilitychange', function() {
307 if (documentOriginalTitle !== '') {
310 if (documentOriginalTitle !== '') {
308 document.title = documentOriginalTitle;
311 document.title = documentOriginalTitle;
309 documentOriginalTitle = '';
312 documentOriginalTitle = '';
310 unreadPosts = 0;
313 unreadPosts = 0;
311 }
314 }
312
315
313 document.removeEventListener('visibilitychange', null);
316 document.removeEventListener('visibilitychange', null);
314 });
317 });
315 }
318 }
316 }
319 }
317
320
318 /**
321 /**
319 * Clear all entered values in the form fields
322 * Clear all entered values in the form fields
320 */
323 */
321 function resetForm(form) {
324 function resetForm(form) {
322 form.find('input:text, input:password, input:file, select, textarea').val('');
325 form.find('input:text, input:password, input:file, select, textarea').val('');
323 form.find('input:radio, input:checkbox')
326 form.find('input:radio, input:checkbox')
324 .removeAttr('checked').removeAttr('selected');
327 .removeAttr('checked').removeAttr('selected');
325 $('.file_wrap').find('.file-thumb').remove();
328 $('.file_wrap').find('.file-thumb').remove();
326 $('#preview-text').hide();
329 $('#preview-text').hide();
327 }
330 }
328
331
329 /**
332 /**
330 * When the form is posted, this method will be run as a callback
333 * When the form is posted, this method will be run as a callback
331 */
334 */
332 function updateOnPost(response, statusText, xhr, form) {
335 function updateOnPost(response, statusText, xhr, form) {
333 var json = $.parseJSON(response);
336 var json = $.parseJSON(response);
334 var status = json.status;
337 var status = json.status;
335
338
336 showAsErrors(form, '');
339 showAsErrors(form, '');
337
340
338 if (status === 'ok') {
341 if (status === 'ok') {
339 resetFormPosition();
342 resetFormPosition();
340 resetForm(form);
343 resetForm(form);
341 getThreadDiff();
344 getThreadDiff();
342 scrollToBottom();
345 scrollToBottom();
343 } else {
346 } else {
344 var errors = json.errors;
347 var errors = json.errors;
345 for (var i = 0; i < errors.length; i++) {
348 for (var i = 0; i < errors.length; i++) {
346 var fieldErrors = errors[i];
349 var fieldErrors = errors[i];
347
350
348 var error = fieldErrors.errors;
351 var error = fieldErrors.errors;
349
352
350 showAsErrors(form, error);
353 showAsErrors(form, error);
351 }
354 }
352 }
355 }
353 }
356 }
354
357
355 /**
358 /**
356 * Show text in the errors row of the form.
359 * Show text in the errors row of the form.
357 * @param form
360 * @param form
358 * @param text
361 * @param text
359 */
362 */
360 function showAsErrors(form, text) {
363 function showAsErrors(form, text) {
361 form.children('.form-errors').remove();
364 form.children('.form-errors').remove();
362
365
363 if (text.length > 0) {
366 if (text.length > 0) {
364 var errorList = $('<div class="form-errors">' + text + '<div>');
367 var errorList = $('<div class="form-errors">' + text + '<div>');
365 errorList.appendTo(form);
368 errorList.appendTo(form);
366 }
369 }
367 }
370 }
368
371
369 /**
372 /**
370 * Run js methods that are usually run on the document, on the new post
373 * Run js methods that are usually run on the document, on the new post
371 */
374 */
372 function processNewPost(post) {
375 function processNewPost(post) {
373 addRefLinkPreview(post[0]);
376 addRefLinkPreview(post[0]);
374 highlightCode(post);
377 highlightCode(post);
375 blink(post);
378 blink(post);
376 }
379 }
377
380
378 function replacePartial(oldNode, newNode, recursive) {
381 function replacePartial(oldNode, newNode, recursive) {
379 if (!equalNodes(oldNode, newNode)) {
382 if (!equalNodes(oldNode, newNode)) {
380 // Update parent node attributes
383 // Update parent node attributes
381 updateNodeAttr(oldNode, newNode, ATTR_CLASS);
384 updateNodeAttr(oldNode, newNode, ATTR_CLASS);
382 updateNodeAttr(oldNode, newNode, ATTR_UID);
385 updateNodeAttr(oldNode, newNode, ATTR_UID);
383
386
384 // Replace children
387 // Replace children
385 var children = oldNode.children();
388 var children = oldNode.children();
386 if (children.length == 0) {
389 if (children.length == 0) {
387 oldNode.replaceWith(newNode);
390 oldNode.replaceWith(newNode);
388 } else {
391 } else {
389 var newChildren = newNode.children();
392 var newChildren = newNode.children();
390 newChildren.each(function(i) {
393 newChildren.each(function(i) {
391 var newChild = newChildren.eq(i);
394 var newChild = newChildren.eq(i);
392 var newChildClass = newChild.attr(ATTR_CLASS);
395 var newChildClass = newChild.attr(ATTR_CLASS);
393
396
394 // Update only certain allowed blocks (e.g. not images)
397 // Update only certain allowed blocks (e.g. not images)
395 if (ALLOWED_FOR_PARTIAL_UPDATE.indexOf(newChildClass) > -1) {
398 if (ALLOWED_FOR_PARTIAL_UPDATE.indexOf(newChildClass) > -1) {
396 var oldChild = oldNode.children('.' + newChildClass);
399 var oldChild = oldNode.children('.' + newChildClass);
397
400
398 if (oldChild.length == 0) {
401 if (oldChild.length == 0) {
399 oldNode.append(newChild);
402 oldNode.append(newChild);
400 } else {
403 } else {
401 if (!equalNodes(oldChild, newChild)) {
404 if (!equalNodes(oldChild, newChild)) {
402 if (recursive) {
405 if (recursive) {
403 replacePartial(oldChild, newChild, false);
406 replacePartial(oldChild, newChild, false);
404 } else {
407 } else {
405 oldChild.replaceWith(newChild);
408 oldChild.replaceWith(newChild);
406 }
409 }
407 }
410 }
408 }
411 }
409 }
412 }
410 });
413 });
411 }
414 }
412 }
415 }
413 }
416 }
414
417
415 /**
418 /**
416 * Compare nodes by content
419 * Compare nodes by content
417 */
420 */
418 function equalNodes(node1, node2) {
421 function equalNodes(node1, node2) {
419 return node1[0].outerHTML == node2[0].outerHTML;
422 return node1[0].outerHTML == node2[0].outerHTML;
420 }
423 }
421
424
422 /**
425 /**
423 * Update attribute of a node if it has changed
426 * Update attribute of a node if it has changed
424 */
427 */
425 function updateNodeAttr(oldNode, newNode, attrName) {
428 function updateNodeAttr(oldNode, newNode, attrName) {
426 var oldAttr = oldNode.attr(attrName);
429 var oldAttr = oldNode.attr(attrName);
427 var newAttr = newNode.attr(attrName);
430 var newAttr = newNode.attr(attrName);
428 if (oldAttr != newAttr) {
431 if (oldAttr != newAttr) {
429 oldNode.attr(attrName, newAttr);
432 oldNode.attr(attrName, newAttr);
430 }
433 }
431 }
434 }
432
435
433 $(document).ready(function(){
436 $(document).ready(function(){
434 if (initAutoupdate()) {
437 if (initAutoupdate()) {
435 // Post form data over AJAX
438 // Post form data over AJAX
436 var threadId = $('div.thread').children('.post').first().attr('id');
439 var threadId = $('div.thread').children('.post').first().attr('id');
437
440
438 var form = $('#form');
441 var form = $('#form');
439
442
440 if (form.length > 0) {
443 if (form.length > 0) {
441 var options = {
444 var options = {
442 beforeSubmit: function(arr, $form, options) {
445 beforeSubmit: function(arr, $form, options) {
443 showAsErrors($('#form'), gettext('Sending message...'));
446 showAsErrors($('#form'), gettext('Sending message...'));
444 },
447 },
445 success: updateOnPost,
448 success: updateOnPost,
446 error: function() {
449 error: function() {
447 showAsErrors($('#form'), gettext('Server error!'));
450 showAsErrors($('#form'), gettext('Server error!'));
448 },
451 },
449 url: '/api/add_post/' + threadId + '/'
452 url: '/api/add_post/' + threadId + '/',
453 timeout: POST_AJAX_TIMEOUT
450 };
454 };
451
455
452 form.ajaxForm(options);
456 form.ajaxForm(options);
453
457
454 resetForm(form);
458 resetForm(form);
455 }
459 }
456 }
460 }
457 });
461 });
General Comments 0
You need to be logged in to leave comments. Login now