##// END OF EJS Templates
Fixed adding dead_post class to posts after bumplimit reached
neko259 -
r585:af8fdac8 default
parent child Browse files
Show More
@@ -1,270 +1,259 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 neko259
6 Copyright (C) 2013 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 THREAD_UPDATE_DELAY = 10000;
26 var THREAD_UPDATE_DELAY = 10000;
27
27
28 var loading = false;
28 var loading = false;
29 var lastUpdateTime = null;
29 var lastUpdateTime = null;
30 var unreadPosts = 0
30 var unreadPosts = 0
31
31
32 function blink(node) {
32 function blink(node) {
33 var blinkCount = 2;
33 var blinkCount = 2;
34
34
35 var nodeToAnimate = node;
35 var nodeToAnimate = node;
36 for (var i = 0; i < blinkCount; i++) {
36 for (var i = 0; i < blinkCount; i++) {
37 nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0);
37 nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0);
38 }
38 }
39 }
39 }
40
40
41 function updateThread() {
41 function updateThread() {
42 if (loading) {
42 if (loading) {
43 return;
43 return;
44 }
44 }
45
45
46 loading = true;
46 loading = true;
47
47
48 var threadPosts = $('div.thread').children('.post');
48 var threadPosts = $('div.thread').children('.post');
49
49
50 var lastPost = threadPosts.last();
50 var lastPost = threadPosts.last();
51 var threadId = threadPosts.first().attr('id');
51 var threadId = threadPosts.first().attr('id');
52
52
53 var diffUrl = '/api/diff_thread/' + threadId + '/' + lastUpdateTime + '/';
53 var diffUrl = '/api/diff_thread/' + threadId + '/' + lastUpdateTime + '/';
54 $.getJSON(diffUrl)
54 $.getJSON(diffUrl)
55 .success(function(data) {
55 .success(function(data) {
56 var bottom = isPageBottom();
56 var bottom = isPageBottom();
57
57
58 var lastUpdate = '';
58 var lastUpdate = '';
59
59
60 var addedPosts = data.added;
60 var addedPosts = data.added;
61 for (var i = 0; i < addedPosts.length; i++) {
61 for (var i = 0; i < addedPosts.length; i++) {
62 var postText = addedPosts[i];
62 var postText = addedPosts[i];
63
63
64 var post = $(postText);
64 var post = $(postText);
65
65
66 if (lastUpdate === '') {
66 if (lastUpdate === '') {
67 lastUpdate = post.find('.pub_time').text();
67 lastUpdate = post.find('.pub_time').text();
68 }
68 }
69
69
70 post.appendTo(lastPost.parent());
70 post.appendTo(lastPost.parent());
71 addRefLinkPreview(post[0]);
71 addRefLinkPreview(post[0]);
72
72
73 lastPost = post;
73 lastPost = post;
74 blink(post);
74 blink(post);
75 }
75 }
76
76
77 var updatedPosts = data.updated;
77 var updatedPosts = data.updated;
78 for (var i = 0; i < updatedPosts.length; i++) {
78 for (var i = 0; i < updatedPosts.length; i++) {
79 var postText = updatedPosts[i];
79 var postText = updatedPosts[i];
80
80
81 var post = $(postText);
81 var post = $(postText);
82
82
83 if (lastUpdate === '') {
83 if (lastUpdate === '') {
84 lastUpdate = post.find('.pub_time').text();
84 lastUpdate = post.find('.pub_time').text();
85 }
85 }
86
86
87 var postId = post.attr('id');
87 var postId = post.attr('id');
88
88
89 var oldPost = $('div.thread').children('.post[id=' + postId + ']');
89 var oldPost = $('div.thread').children('.post[id=' + postId + ']');
90
90
91 oldPost.replaceWith(post);
91 oldPost.replaceWith(post);
92 addRefLinkPreview(post[0]);
92 addRefLinkPreview(post[0]);
93
93
94 blink(post);
94 blink(post);
95 }
95 }
96
96
97 // TODO Process deleted posts
97 // TODO Process deleted posts
98
98
99 lastUpdateTime = data.last_update;
99 lastUpdateTime = data.last_update;
100 loading = false;
100 loading = false;
101
101
102 if (bottom) {
102 if (bottom) {
103 var $target = $('html,body');
103 var $target = $('html,body');
104 $target.animate({scrollTop: $target.height()}, 1000);
104 $target.animate({scrollTop: $target.height()}, 1000);
105 }
105 }
106
106
107 var hasPostChanges = (updatedPosts.length > 0)
107 var hasPostChanges = (updatedPosts.length > 0)
108 || (addedPosts.length > 0);
108 || (addedPosts.length > 0);
109 if (hasPostChanges) {
109 if (hasPostChanges) {
110 updateMetadataPanel(lastUpdate);
110 updateMetadataPanel(lastUpdate);
111 }
111 }
112
112
113 updateBumplimitProgress(data.added.length);
113 updateBumplimitProgress(data.added.length);
114 updatePostBumpableStatus();
115
114
116 if (data.added.length + data.updated.length > 0) {
115 if (data.added.length + data.updated.length > 0) {
117 showNewPostsTitle(data.added.length);
116 showNewPostsTitle(data.added.length);
118 }
117 }
119 })
118 })
120 .error(function(data) {
119 .error(function(data) {
121 // TODO Show error message that server is unavailable?
120 // TODO Show error message that server is unavailable?
122
121
123 loading = false;
122 loading = false;
124 });
123 });
125 }
124 }
126
125
127 function isPageBottom() {
126 function isPageBottom() {
128 var scroll = $(window).scrollTop() / ($(document).height()
127 var scroll = $(window).scrollTop() / ($(document).height()
129 - $(window).height())
128 - $(window).height())
130
129
131 return scroll == 1
130 return scroll == 1
132 }
131 }
133
132
134 function initAutoupdate() {
133 function initAutoupdate() {
135 loading = false;
134 loading = false;
136
135
137 lastUpdateTime = $('.metapanel').attr('data-last-update');
136 lastUpdateTime = $('.metapanel').attr('data-last-update');
138
137
139 setInterval(updateThread, THREAD_UPDATE_DELAY);
138 setInterval(updateThread, THREAD_UPDATE_DELAY);
140 }
139 }
141
140
142 function getReplyCount() {
141 function getReplyCount() {
143 return $('.thread').children('.post').length
142 return $('.thread').children('.post').length
144 }
143 }
145
144
146 function getImageCount() {
145 function getImageCount() {
147 return $('.thread').find('img').length
146 return $('.thread').find('img').length
148 }
147 }
149
148
150 function updateMetadataPanel(lastUpdate) {
149 function updateMetadataPanel(lastUpdate) {
151 var replyCountField = $('#reply-count');
150 var replyCountField = $('#reply-count');
152 var imageCountField = $('#image-count');
151 var imageCountField = $('#image-count');
153
152
154 replyCountField.text(getReplyCount());
153 replyCountField.text(getReplyCount());
155 imageCountField.text(getImageCount());
154 imageCountField.text(getImageCount());
156
155
157 if (lastUpdate !== '') {
156 if (lastUpdate !== '') {
158 var lastUpdateField = $('#last-update');
157 var lastUpdateField = $('#last-update');
159 lastUpdateField.text(lastUpdate);
158 lastUpdateField.text(lastUpdate);
160 blink(lastUpdateField);
159 blink(lastUpdateField);
161 }
160 }
162
161
163 blink(replyCountField);
162 blink(replyCountField);
164 blink(imageCountField);
163 blink(imageCountField);
165 }
164 }
166
165
167 /**
166 /**
168 * Update bumplimit progress bar
167 * Update bumplimit progress bar
169 */
168 */
170 function updateBumplimitProgress(postDelta) {
169 function updateBumplimitProgress(postDelta) {
171 var progressBar = $('#bumplimit_progress');
170 var progressBar = $('#bumplimit_progress');
172 if (progressBar) {
171 if (progressBar) {
173 var postsToLimitElement = $('#left_to_limit');
172 var postsToLimitElement = $('#left_to_limit');
174
173
175 var oldPostsToLimit = parseInt(postsToLimitElement.text());
174 var oldPostsToLimit = parseInt(postsToLimitElement.text());
176 var postCount = getReplyCount();
175 var postCount = getReplyCount();
177 var bumplimit = postCount - postDelta + oldPostsToLimit;
176 var bumplimit = postCount - postDelta + oldPostsToLimit;
178
177
179 var newPostsToLimit = bumplimit - postCount;
178 var newPostsToLimit = bumplimit - postCount;
180 if (newPostsToLimit <= 0) {
179 if (newPostsToLimit <= 0) {
181 $('.bar-bg').remove();
180 $('.bar-bg').remove();
181 $('.thread').children('.post').addClass('dead_post');
182 } else {
182 } else {
183 postsToLimitElement.text(newPostsToLimit);
183 postsToLimitElement.text(newPostsToLimit);
184 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
184 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
185 }
185 }
186 }
186 }
187 }
187 }
188
188
189 /**
190 * If the bumplimit is reached, add dead_post class to all posts
191 */
192 function updatePostBumpableStatus() {
193 var postsToLimitElement = $('#left_to_limit');
194
195 if (postsToLimitElement === null) {
196 $('.thread').children('.post').addClass('dead_post');
197 }
198 }
199
200 var documentOriginalTitle = '';
189 var documentOriginalTitle = '';
201 /**
190 /**
202 * Show 'new posts' text in the title if the document is not visible to a user
191 * Show 'new posts' text in the title if the document is not visible to a user
203 */
192 */
204 function showNewPostsTitle(newPostCount) {
193 function showNewPostsTitle(newPostCount) {
205 if (document.hidden) {
194 if (document.hidden) {
206 if (documentOriginalTitle === '') {
195 if (documentOriginalTitle === '') {
207 documentOriginalTitle = document.title;
196 documentOriginalTitle = document.title;
208 }
197 }
209 unreadPosts = unreadPosts + newPostCount;
198 unreadPosts = unreadPosts + newPostCount;
210 document.title = '[' + unreadPosts + '] ' + documentOriginalTitle;
199 document.title = '[' + unreadPosts + '] ' + documentOriginalTitle;
211
200
212 document.addEventListener('visibilitychange', function() {
201 document.addEventListener('visibilitychange', function() {
213 if (documentOriginalTitle !== '') {
202 if (documentOriginalTitle !== '') {
214 document.title = documentOriginalTitle;
203 document.title = documentOriginalTitle;
215 documentOriginalTitle = '';
204 documentOriginalTitle = '';
216 unreadPosts = 0;
205 unreadPosts = 0;
217 }
206 }
218
207
219 document.removeEventListener('visibilitychange', null);
208 document.removeEventListener('visibilitychange', null);
220 });
209 });
221 }
210 }
222 }
211 }
223
212
224 /**
213 /**
225 * Clear all entered values in the form fields
214 * Clear all entered values in the form fields
226 */
215 */
227 function resetForm(form) {
216 function resetForm(form) {
228 form.find('input:text, input:password, input:file, select, textarea').val('');
217 form.find('input:text, input:password, input:file, select, textarea').val('');
229 form.find('input:radio, input:checkbox')
218 form.find('input:radio, input:checkbox')
230 .removeAttr('checked').removeAttr('selected');
219 .removeAttr('checked').removeAttr('selected');
231 }
220 }
232
221
233
222
234 $(document).ready(function(){
223 $(document).ready(function(){
235 initAutoupdate();
224 initAutoupdate();
236
225
237 // Post form data over AJAX
226 // Post form data over AJAX
238 var threadId = $('div.thread').children('.post').first().attr('id');;
227 var threadId = $('div.thread').children('.post').first().attr('id');;
239
228
240 var form = $('#form');
229 var form = $('#form');
241 var options = {
230 var options = {
242 success: updateOnPost,
231 success: updateOnPost,
243 url: '/api/add_post/' + threadId + '/',
232 url: '/api/add_post/' + threadId + '/',
244 };
233 };
245
234
246 form.ajaxForm(options);
235 form.ajaxForm(options);
247
236
248 function updateOnPost(response, statusText, xhr, $form) {
237 function updateOnPost(response, statusText, xhr, $form) {
249 var json = $.parseJSON(response);
238 var json = $.parseJSON(response);
250 var status = json.status;
239 var status = json.status;
251
240
252 form.children('.form-errors').remove();
241 form.children('.form-errors').remove();
253
242
254 if (status === 'ok') {
243 if (status === 'ok') {
255 resetForm(form);
244 resetForm(form);
256 updateThread();
245 updateThread();
257 } else {
246 } else {
258 var errors = json.errors;
247 var errors = json.errors;
259 for (var i = 0; i < errors.length; i++) {
248 for (var i = 0; i < errors.length; i++) {
260 var fieldErrors = errors[i];
249 var fieldErrors = errors[i];
261
250
262 var error = fieldErrors.errors;
251 var error = fieldErrors.errors;
263
252
264 var errorList = $('<div class="form-errors">' + error
253 var errorList = $('<div class="form-errors">' + error
265 + '<div>');
254 + '<div>');
266 errorList.appendTo(form);
255 errorList.appendTo(form);
267 }
256 }
268 }
257 }
269 }
258 }
270 });
259 });
General Comments 0
You need to be logged in to leave comments. Login now