##// END OF EJS Templates
Allow resetting form manually
neko259 -
r1880:3ff4ab75 default
parent child Browse files
Show More
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -1,592 +1,592 b''
1 # SOME DESCRIPTIVE TITLE.
1 # SOME DESCRIPTIVE TITLE.
2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 # This file is distributed under the same license as the PACKAGE package.
3 # This file is distributed under the same license as the PACKAGE package.
4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5 #
5 #
6 msgid ""
6 msgid ""
7 msgstr ""
7 msgstr ""
8 "Project-Id-Version: PACKAGE VERSION\n"
8 "Project-Id-Version: PACKAGE VERSION\n"
9 "Report-Msgid-Bugs-To: \n"
9 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2015-10-09 23:21+0300\n"
10 "POT-Creation-Date: 2015-10-09 23:21+0300\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language: ru\n"
14 "Language: ru\n"
15 "MIME-Version: 1.0\n"
15 "MIME-Version: 1.0\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n"
17 "Content-Transfer-Encoding: 8bit\n"
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20
20
21 #: admin.py:22
21 #: admin.py:22
22 msgid "{} posters were banned"
22 msgid "{} posters were banned"
23 msgstr ""
23 msgstr ""
24
24
25 #: authors.py:9
25 #: authors.py:9
26 msgid "author"
26 msgid "author"
27 msgstr "автор"
27 msgstr "автор"
28
28
29 #: authors.py:10
29 #: authors.py:10
30 msgid "developer"
30 msgid "developer"
31 msgstr "разработчик"
31 msgstr "разработчик"
32
32
33 #: authors.py:11
33 #: authors.py:11
34 msgid "javascript developer"
34 msgid "javascript developer"
35 msgstr "разработчик javascript"
35 msgstr "разработчик javascript"
36
36
37 #: authors.py:12
37 #: authors.py:12
38 msgid "designer"
38 msgid "designer"
39 msgstr "дизайнер"
39 msgstr "дизайнер"
40
40
41 #: forms.py:30
41 #: forms.py:30
42 msgid "Type message here. Use formatting panel for more advanced usage."
42 msgid "Type message here. Use formatting panel for more advanced usage."
43 msgstr ""
43 msgstr ""
44 "Вводите сообщение сюда. Используйте панель для более сложного форматирования."
44 "Вводите сообщение сюда. Используйте панель для более сложного форматирования."
45
45
46 #: forms.py:31
46 #: forms.py:31
47 msgid "music images i_dont_like_tags"
47 msgid "music images i_dont_like_tags"
48 msgstr "музыка картинки теги_не_нужны"
48 msgstr "музыка картинки теги_не_нужны"
49
49
50 #: forms.py:33
50 #: forms.py:33
51 msgid "Title"
51 msgid "Title"
52 msgstr "Заголовок"
52 msgstr "Заголовок"
53
53
54 #: forms.py:34
54 #: forms.py:34
55 msgid "Text"
55 msgid "Text"
56 msgstr "Текст"
56 msgstr "Текст"
57
57
58 #: forms.py:35
58 #: forms.py:35
59 msgid "Tag"
59 msgid "Tag"
60 msgstr "Метка"
60 msgstr "Метка"
61
61
62 #: forms.py:36 templates/boards/base.html:40 templates/search/search.html:7
62 #: forms.py:36 templates/boards/base.html:40 templates/search/search.html:7
63 msgid "Search"
63 msgid "Search"
64 msgstr "Поиск"
64 msgstr "Поиск"
65
65
66 #: forms.py:48
66 #: forms.py:48
67 msgid "File 1"
67 msgid "File 1"
68 msgstr "Файл 1"
68 msgstr "Файл 1"
69
69
70 #: forms.py:48
70 #: forms.py:48
71 msgid "File 2"
71 msgid "File 2"
72 msgstr "Файл 2"
72 msgstr "Файл 2"
73
73
74 #: forms.py:142
74 #: forms.py:142
75 msgid "File URL"
75 msgid "File URL"
76 msgstr "URL файла"
76 msgstr "URL файла"
77
77
78 #: forms.py:148
78 #: forms.py:148
79 msgid "e-mail"
79 msgid "e-mail"
80 msgstr ""
80 msgstr ""
81
81
82 #: forms.py:151
82 #: forms.py:151
83 msgid "Additional threads"
83 msgid "Additional threads"
84 msgstr "Дополнительные темы"
84 msgstr "Дополнительные темы"
85
85
86 #: forms.py:162
86 #: forms.py:162
87 #, python-format
87 #, python-format
88 msgid "Title must have less than %s characters"
88 msgid "Title must have less than %s characters"
89 msgstr "Заголовок должен иметь меньше %s символов"
89 msgstr "Заголовок должен иметь меньше %s символов"
90
90
91 #: forms.py:172
91 #: forms.py:172
92 #, python-format
92 #, python-format
93 msgid "Text must have less than %s characters"
93 msgid "Text must have less than %s characters"
94 msgstr "Текст должен быть короче %s символов"
94 msgstr "Текст должен быть короче %s символов"
95
95
96 #: forms.py:192
96 #: forms.py:192
97 msgid "Invalid URL"
97 msgid "Invalid URL"
98 msgstr "Неверный URL"
98 msgstr "Неверный URL"
99
99
100 #: forms.py:213
100 #: forms.py:213
101 msgid "Invalid additional thread list"
101 msgid "Invalid additional thread list"
102 msgstr "Неверный список дополнительных тем"
102 msgstr "Неверный список дополнительных тем"
103
103
104 #: forms.py:258
104 #: forms.py:258
105 msgid "Either text or file must be entered."
105 msgid "Either text or file must be entered."
106 msgstr "Текст или файл должны быть введены."
106 msgstr "Текст или файл должны быть введены."
107
107
108 #: forms.py:317 templates/boards/all_threads.html:153
108 #: forms.py:317 templates/boards/all_threads.html:153
109 #: templates/boards/rss/post.html:10 templates/boards/tags.html:6
109 #: templates/boards/rss/post.html:10 templates/boards/tags.html:6
110 msgid "Tags"
110 msgid "Tags"
111 msgstr "Метки"
111 msgstr "Метки"
112
112
113 #: forms.py:324
113 #: forms.py:324
114 msgid "Inappropriate characters in tags."
114 msgid "Inappropriate characters in tags."
115 msgstr "Недопустимые символы в метках."
115 msgstr "Недопустимые символы в метках."
116
116
117 #: forms.py:344
117 #: forms.py:344
118 msgid "Need at least one section."
118 msgid "Need at least one section."
119 msgstr "Нужен хотя бы один раздел."
119 msgstr "Нужен хотя бы один раздел."
120
120
121 #: forms.py:356
121 #: forms.py:356
122 msgid "Theme"
122 msgid "Theme"
123 msgstr "Тема"
123 msgstr "Тема"
124
124
125 #: forms.py:357
125 #: forms.py:357
126 msgid "Image view mode"
126 msgid "Image view mode"
127 msgstr "Режим просмотра изображений"
127 msgstr "Режим просмотра изображений"
128
128
129 #: forms.py:358
129 #: forms.py:358
130 msgid "User name"
130 msgid "User name"
131 msgstr "Имя пользователя"
131 msgstr "Имя пользователя"
132
132
133 #: forms.py:359
133 #: forms.py:359
134 msgid "Time zone"
134 msgid "Time zone"
135 msgstr "Часовой пояс"
135 msgstr "Часовой пояс"
136
136
137 #: forms.py:365
137 #: forms.py:365
138 msgid "Inappropriate characters."
138 msgid "Inappropriate characters."
139 msgstr "Недопустимые символы."
139 msgstr "Недопустимые символы."
140
140
141 #: templates/boards/404.html:6
141 #: templates/boards/404.html:6
142 msgid "Not found"
142 msgid "Not found"
143 msgstr "Не найдено"
143 msgstr "Не найдено"
144
144
145 #: templates/boards/404.html:12
145 #: templates/boards/404.html:12
146 msgid "This page does not exist"
146 msgid "This page does not exist"
147 msgstr "Этой страницы не существует"
147 msgstr "Этой страницы не существует"
148
148
149 #: templates/boards/all_threads.html:35
149 #: templates/boards/all_threads.html:35
150 msgid "Details"
150 msgid "Details"
151 msgstr "Подробности"
151 msgstr "Подробности"
152
152
153 #: templates/boards/all_threads.html:69
153 #: templates/boards/all_threads.html:69
154 msgid "Edit tag"
154 msgid "Edit tag"
155 msgstr "Изменить метку"
155 msgstr "Изменить метку"
156
156
157 #: templates/boards/all_threads.html:76
157 #: templates/boards/all_threads.html:76
158 #, python-format
158 #, python-format
159 msgid "%(count)s active thread"
159 msgid "%(count)s active thread"
160 msgid_plural "%(count)s active threads"
160 msgid_plural "%(count)s active threads"
161 msgstr[0] "%(count)s активная тема"
161 msgstr[0] "%(count)s активная тема"
162 msgstr[1] "%(count)s активные темы"
162 msgstr[1] "%(count)s активные темы"
163 msgstr[2] "%(count)s активных тем"
163 msgstr[2] "%(count)s активных тем"
164
164
165 #: templates/boards/all_threads.html:76
165 #: templates/boards/all_threads.html:76
166 #, python-format
166 #, python-format
167 msgid "%(count)s thread in bumplimit"
167 msgid "%(count)s thread in bumplimit"
168 msgid_plural "%(count)s threads in bumplimit"
168 msgid_plural "%(count)s threads in bumplimit"
169 msgstr[0] "%(count)s тема в бамплимите"
169 msgstr[0] "%(count)s тема в бамплимите"
170 msgstr[1] "%(count)s темы в бамплимите"
170 msgstr[1] "%(count)s темы в бамплимите"
171 msgstr[2] "%(count)s тем в бамплимите"
171 msgstr[2] "%(count)s тем в бамплимите"
172
172
173 #: templates/boards/all_threads.html:77
173 #: templates/boards/all_threads.html:77
174 #, python-format
174 #, python-format
175 msgid "%(count)s archived thread"
175 msgid "%(count)s archived thread"
176 msgid_plural "%(count)s archived thread"
176 msgid_plural "%(count)s archived thread"
177 msgstr[0] "%(count)s архивная тема"
177 msgstr[0] "%(count)s архивная тема"
178 msgstr[1] "%(count)s архивные темы"
178 msgstr[1] "%(count)s архивные темы"
179 msgstr[2] "%(count)s архивных тем"
179 msgstr[2] "%(count)s архивных тем"
180
180
181 #: templates/boards/all_threads.html:78 templates/boards/post.html:102
181 #: templates/boards/all_threads.html:78 templates/boards/post.html:102
182 #, python-format
182 #, python-format
183 #| msgid "%(count)s message"
183 #| msgid "%(count)s message"
184 #| msgid_plural "%(count)s messages"
184 #| msgid_plural "%(count)s messages"
185 msgid "%(count)s message"
185 msgid "%(count)s message"
186 msgid_plural "%(count)s messages"
186 msgid_plural "%(count)s messages"
187 msgstr[0] "%(count)s сообщение"
187 msgstr[0] "%(count)s сообщение"
188 msgstr[1] "%(count)s сообщения"
188 msgstr[1] "%(count)s сообщения"
189 msgstr[2] "%(count)s сообщений"
189 msgstr[2] "%(count)s сообщений"
190
190
191 #: templates/boards/all_threads.html:95 templates/boards/feed.html:30
191 #: templates/boards/all_threads.html:95 templates/boards/feed.html:30
192 #: templates/boards/notifications.html:17 templates/search/search.html:26
192 #: templates/boards/notifications.html:17 templates/search/search.html:26
193 msgid "Previous page"
193 msgid "Previous page"
194 msgstr "Предыдущая страница"
194 msgstr "Предыдущая страница"
195
195
196 #: templates/boards/all_threads.html:109
196 #: templates/boards/all_threads.html:109
197 #, python-format
197 #, python-format
198 msgid "Skipped %(count)s reply. Open thread to see all replies."
198 msgid "Skipped %(count)s reply. Open thread to see all replies."
199 msgid_plural "Skipped %(count)s replies. Open thread to see all replies."
199 msgid_plural "Skipped %(count)s replies. Open thread to see all replies."
200 msgstr[0] "Пропущен %(count)s ответ. Откройте тред, чтобы увидеть все ответы."
200 msgstr[0] "Пропущен %(count)s ответ. Откройте тред, чтобы увидеть все ответы."
201 msgstr[1] ""
201 msgstr[1] ""
202 "Пропущено %(count)s ответа. Откройте тред, чтобы увидеть все ответы."
202 "Пропущено %(count)s ответа. Откройте тред, чтобы увидеть все ответы."
203 msgstr[2] ""
203 msgstr[2] ""
204 "Пропущено %(count)s ответов. Откройте тред, чтобы увидеть все ответы."
204 "Пропущено %(count)s ответов. Откройте тред, чтобы увидеть все ответы."
205
205
206 #: templates/boards/all_threads.html:127 templates/boards/feed.html:40
206 #: templates/boards/all_threads.html:127 templates/boards/feed.html:40
207 #: templates/boards/notifications.html:27 templates/search/search.html:37
207 #: templates/boards/notifications.html:27 templates/search/search.html:37
208 msgid "Next page"
208 msgid "Next page"
209 msgstr "Следующая страница"
209 msgstr "Следующая страница"
210
210
211 #: templates/boards/all_threads.html:132
211 #: templates/boards/all_threads.html:132
212 msgid "No threads exist. Create the first one!"
212 msgid "No threads exist. Create the first one!"
213 msgstr "Нет тем. Создайте первую!"
213 msgstr "Нет тем. Создайте первую!"
214
214
215 #: templates/boards/all_threads.html:138
215 #: templates/boards/all_threads.html:138
216 msgid "Create new thread"
216 msgid "Create new thread"
217 msgstr "Создать новую тему"
217 msgstr "Создать новую тему"
218
218
219 #: templates/boards/all_threads.html:143 templates/boards/preview.html:16
219 #: templates/boards/all_threads.html:143 templates/boards/preview.html:16
220 #: templates/boards/thread_normal.html:51
220 #: templates/boards/thread_normal.html:51
221 msgid "Post"
221 msgid "Post"
222 msgstr "Отправить"
222 msgstr "Отправить"
223
223
224 #: templates/boards/all_threads.html:144 templates/boards/preview.html:6
224 #: templates/boards/all_threads.html:144 templates/boards/preview.html:6
225 #: templates/boards/staticpages/help.html:21
225 #: templates/boards/staticpages/help.html:21
226 #: templates/boards/thread_normal.html:52
226 #: templates/boards/thread_normal.html:52
227 msgid "Preview"
227 msgid "Preview"
228 msgstr "Предпросмотр"
228 msgstr "Предпросмотр"
229
229
230 #: templates/boards/all_threads.html:149
230 #: templates/boards/all_threads.html:149
231 msgid "Tags must be delimited by spaces. Text or image is required."
231 msgid "Tags must be delimited by spaces. Text or image is required."
232 msgstr ""
232 msgstr ""
233 "Метки должны быть разделены пробелами. Текст или изображение обязательны."
233 "Метки должны быть разделены пробелами. Текст или изображение обязательны."
234
234
235 #: templates/boards/all_threads.html:152 templates/boards/thread_normal.html:58
235 #: templates/boards/all_threads.html:152 templates/boards/thread_normal.html:58
236 msgid "Text syntax"
236 msgid "Text syntax"
237 msgstr "Синтаксис текста"
237 msgstr "Синтаксис текста"
238
238
239 #: templates/boards/all_threads.html:166 templates/boards/feed.html:53
239 #: templates/boards/all_threads.html:166 templates/boards/feed.html:53
240 msgid "Pages:"
240 msgid "Pages:"
241 msgstr "Страницы: "
241 msgstr "Страницы: "
242
242
243 #: templates/boards/authors.html:6 templates/boards/authors.html.py:12
243 #: templates/boards/authors.html:6 templates/boards/authors.html.py:12
244 msgid "Authors"
244 msgid "Authors"
245 msgstr "Авторы"
245 msgstr "Авторы"
246
246
247 #: templates/boards/authors.html:26
247 #: templates/boards/authors.html:26
248 msgid "Distributed under the"
248 msgid "Distributed under the"
249 msgstr "Распространяется под"
249 msgstr "Распространяется под"
250
250
251 #: templates/boards/authors.html:28
251 #: templates/boards/authors.html:28
252 msgid "license"
252 msgid "license"
253 msgstr "лицензией"
253 msgstr "лицензией"
254
254
255 #: templates/boards/authors.html:30
255 #: templates/boards/authors.html:30
256 msgid "Repository"
256 msgid "Repository"
257 msgstr "Репозиторий"
257 msgstr "Репозиторий"
258
258
259 #: templates/boards/base.html:14 templates/boards/base.html.py:41
259 #: templates/boards/base.html:14 templates/boards/base.html.py:41
260 msgid "Feed"
260 msgid "Feed"
261 msgstr "Лента"
261 msgstr "Лента"
262
262
263 #: templates/boards/base.html:31
263 #: templates/boards/base.html:31
264 msgid "All threads"
264 msgid "All threads"
265 msgstr "Все темы"
265 msgstr "Все темы"
266
266
267 #: templates/boards/base.html:37
267 #: templates/boards/base.html:37
268 msgid "Add tags"
268 msgid "Add tags"
269 msgstr "Добавить метки"
269 msgstr "Добавить метки"
270
270
271 #: templates/boards/base.html:39
271 #: templates/boards/base.html:39
272 msgid "Tag management"
272 msgid "Tag management"
273 msgstr "Управление метками"
273 msgstr "Управление метками"
274
274
275 #: templates/boards/base.html:39
275 #: templates/boards/base.html:39
276 msgid "tags"
276 msgid "tags"
277 msgstr "метки"
277 msgstr "метки"
278
278
279 #: templates/boards/base.html:40
279 #: templates/boards/base.html:40
280 msgid "search"
280 msgid "search"
281 msgstr "поиск"
281 msgstr "поиск"
282
282
283 #: templates/boards/base.html:41 templates/boards/feed.html:11
283 #: templates/boards/base.html:41 templates/boards/feed.html:11
284 msgid "feed"
284 msgid "feed"
285 msgstr "лента"
285 msgstr "лента"
286
286
287 #: templates/boards/base.html:42 templates/boards/random.html:6
287 #: templates/boards/base.html:42 templates/boards/random.html:6
288 msgid "Random images"
288 msgid "Random images"
289 msgstr "Случайные изображения"
289 msgstr "Случайные изображения"
290
290
291 #: templates/boards/base.html:42
291 #: templates/boards/base.html:42
292 msgid "random"
292 msgid "random"
293 msgstr "случайные"
293 msgstr "случайные"
294
294
295 #: templates/boards/base.html:44
295 #: templates/boards/base.html:44
296 msgid "favorites"
296 msgid "favorites"
297 msgstr "избранное"
297 msgstr "избранное"
298
298
299 #: templates/boards/base.html:48 templates/boards/base.html.py:49
299 #: templates/boards/base.html:48 templates/boards/base.html.py:49
300 #: templates/boards/notifications.html:8
300 #: templates/boards/notifications.html:8
301 msgid "Notifications"
301 msgid "Notifications"
302 msgstr "Уведомления"
302 msgstr "Уведомления"
303
303
304 #: templates/boards/base.html:56 templates/boards/settings.html:8
304 #: templates/boards/base.html:56 templates/boards/settings.html:8
305 msgid "Settings"
305 msgid "Settings"
306 msgstr "Настройки"
306 msgstr "Настройки"
307
307
308 #: templates/boards/base.html:59
308 #: templates/boards/base.html:59
309 msgid "Loading..."
309 msgid "Loading..."
310 msgstr "Загрузка..."
310 msgstr "Загрузка..."
311
311
312 #: templates/boards/base.html:71
312 #: templates/boards/base.html:71
313 msgid "Admin"
313 msgid "Admin"
314 msgstr "Администрирование"
314 msgstr "Администрирование"
315
315
316 #: templates/boards/base.html:73
316 #: templates/boards/base.html:73
317 #, python-format
317 #, python-format
318 msgid "Speed: %(ppd)s posts per day"
318 msgid "Speed: %(ppd)s posts per day"
319 msgstr "Скорость: %(ppd)s сообщений в день"
319 msgstr "Скорость: %(ppd)s сообщений в день"
320
320
321 #: templates/boards/base.html:75
321 #: templates/boards/base.html:75
322 msgid "Up"
322 msgid "Up"
323 msgstr "Вверх"
323 msgstr "Вверх"
324
324
325 #: templates/boards/feed.html:45
325 #: templates/boards/feed.html:45
326 msgid "No posts exist. Create the first one!"
326 msgid "No posts exist. Create the first one!"
327 msgstr "Нет сообщений. Создайте первое!"
327 msgstr "Нет сообщений. Создайте первое!"
328
328
329 #: templates/boards/post.html:33
329 #: templates/boards/post.html:33
330 msgid "Open"
330 msgid "Open"
331 msgstr "Открыть"
331 msgstr "Открыть"
332
332
333 #: templates/boards/post.html:35 templates/boards/post.html.py:46
333 #: templates/boards/post.html:35 templates/boards/post.html.py:46
334 msgid "Reply"
334 msgid "Reply"
335 msgstr "Ответить"
335 msgstr "Ответить"
336
336
337 #: templates/boards/post.html:41
337 #: templates/boards/post.html:41
338 msgid " in "
338 msgid " in "
339 msgstr " в "
339 msgstr " в "
340
340
341 #: templates/boards/post.html:51
341 #: templates/boards/post.html:51
342 msgid "Edit"
342 msgid "Edit"
343 msgstr "Изменить"
343 msgstr "Изменить"
344
344
345 #: templates/boards/post.html:53
345 #: templates/boards/post.html:53
346 msgid "Edit thread"
346 msgid "Edit thread"
347 msgstr "Изменить тему"
347 msgstr "Изменить тему"
348
348
349 #: templates/boards/post.html:91
349 #: templates/boards/post.html:91
350 msgid "Replies"
350 msgid "Replies"
351 msgstr "Ответы"
351 msgstr "Ответы"
352
352
353 #: templates/boards/post.html:103
353 #: templates/boards/post.html:103
354 #, python-format
354 #, python-format
355 msgid "%(count)s image"
355 msgid "%(count)s image"
356 msgid_plural "%(count)s images"
356 msgid_plural "%(count)s images"
357 msgstr[0] "%(count)s изображение"
357 msgstr[0] "%(count)s изображение"
358 msgstr[1] "%(count)s изображения"
358 msgstr[1] "%(count)s изображения"
359 msgstr[2] "%(count)s изображений"
359 msgstr[2] "%(count)s изображений"
360
360
361 #: templates/boards/rss/post.html:5
361 #: templates/boards/rss/post.html:5
362 msgid "Post image"
362 msgid "Post image"
363 msgstr "Изображение сообщения"
363 msgstr "Изображение сообщения"
364
364
365 #: templates/boards/settings.html:15
365 #: templates/boards/settings.html:15
366 msgid "You are moderator."
366 msgid "You are moderator."
367 msgstr "Вы модератор."
367 msgstr "Вы модератор."
368
368
369 #: templates/boards/settings.html:19
369 #: templates/boards/settings.html:19
370 msgid "Hidden tags:"
370 msgid "Hidden tags:"
371 msgstr "Скрытые метки:"
371 msgstr "Скрытые метки:"
372
372
373 #: templates/boards/settings.html:25
373 #: templates/boards/settings.html:25
374 msgid "No hidden tags."
374 msgid "No hidden tags."
375 msgstr "Нет скрытых меток."
375 msgstr "Нет скрытых меток."
376
376
377 #: templates/boards/settings.html:34
377 #: templates/boards/settings.html:34
378 msgid "Save"
378 msgid "Save"
379 msgstr "Сохранить"
379 msgstr "Сохранить"
380
380
381 #: templates/boards/staticpages/banned.html:6
381 #: templates/boards/staticpages/banned.html:6
382 msgid "Banned"
382 msgid "Banned"
383 msgstr "Заблокирован"
383 msgstr "Заблокирован"
384
384
385 #: templates/boards/staticpages/banned.html:11
385 #: templates/boards/staticpages/banned.html:11
386 msgid "Your IP address has been banned. Contact the administrator"
386 msgid "Your IP address has been banned. Contact the administrator"
387 msgstr "Ваш IP адрес был заблокирован. Свяжитесь с администратором"
387 msgstr "Ваш IP адрес был заблокирован. Свяжитесь с администратором"
388
388
389 #: templates/boards/staticpages/help.html:6
389 #: templates/boards/staticpages/help.html:6
390 #: templates/boards/staticpages/help.html:10
390 #: templates/boards/staticpages/help.html:10
391 msgid "Syntax"
391 msgid "Syntax"
392 msgstr "Синтаксис"
392 msgstr "Синтаксис"
393
393
394 #: templates/boards/staticpages/help.html:11
394 #: templates/boards/staticpages/help.html:11
395 msgid "Italic text"
395 msgid "Italic text"
396 msgstr "Курсивный текст"
396 msgstr "Курсивный текст"
397
397
398 #: templates/boards/staticpages/help.html:12
398 #: templates/boards/staticpages/help.html:12
399 msgid "Bold text"
399 msgid "Bold text"
400 msgstr "Полужирный текст"
400 msgstr "Полужирный текст"
401
401
402 #: templates/boards/staticpages/help.html:13
402 #: templates/boards/staticpages/help.html:13
403 msgid "Spoiler"
403 msgid "Spoiler"
404 msgstr "Спойлер"
404 msgstr "Спойлер"
405
405
406 #: templates/boards/staticpages/help.html:14
406 #: templates/boards/staticpages/help.html:14
407 msgid "Link to a post"
407 msgid "Link to a post"
408 msgstr "Ссылка на сообщение"
408 msgstr "Ссылка на сообщение"
409
409
410 #: templates/boards/staticpages/help.html:15
410 #: templates/boards/staticpages/help.html:15
411 msgid "Strikethrough text"
411 msgid "Strikethrough text"
412 msgstr "Зачеркнутый текст"
412 msgstr "Зачеркнутый текст"
413
413
414 #: templates/boards/staticpages/help.html:16
414 #: templates/boards/staticpages/help.html:16
415 msgid "Comment"
415 msgid "Comment"
416 msgstr "Комментарий"
416 msgstr "Комментарий"
417
417
418 #: templates/boards/staticpages/help.html:17
418 #: templates/boards/staticpages/help.html:17
419 #: templates/boards/staticpages/help.html:18
419 #: templates/boards/staticpages/help.html:18
420 msgid "Quote"
420 msgid "Quote"
421 msgstr "Цитата"
421 msgstr "Цитата"
422
422
423 #: templates/boards/staticpages/help.html:21
423 #: templates/boards/staticpages/help.html:21
424 msgid "You can try pasting the text and previewing the result here:"
424 msgid "You can try pasting the text and previewing the result here:"
425 msgstr "Вы можете попробовать вставить текст и проверить результат здесь:"
425 msgstr "Вы можете попробовать вставить текст и проверить результат здесь:"
426
426
427 #: templates/boards/tags.html:17
427 #: templates/boards/tags.html:17
428 msgid "Sections:"
428 msgid "Sections:"
429 msgstr "Разделы:"
429 msgstr "Разделы:"
430
430
431 #: templates/boards/tags.html:30
431 #: templates/boards/tags.html:30
432 msgid "Other tags:"
432 msgid "Other tags:"
433 msgstr "Другие метки:"
433 msgstr "Другие метки:"
434
434
435 #: templates/boards/tags.html:43
435 #: templates/boards/tags.html:43
436 msgid "All tags..."
436 msgid "All tags..."
437 msgstr "Все метки..."
437 msgstr "Все метки..."
438
438
439 #: templates/boards/thread.html:14
439 #: templates/boards/thread.html:14
440 msgid "Normal"
440 msgid "Normal"
441 msgstr "Нормальный"
441 msgstr "Нормальный"
442
442
443 #: templates/boards/thread.html:15
443 #: templates/boards/thread.html:15
444 msgid "Gallery"
444 msgid "Gallery"
445 msgstr "Галерея"
445 msgstr "Галерея"
446
446
447 #: templates/boards/thread.html:16
447 #: templates/boards/thread.html:16
448 msgid "Tree"
448 msgid "Tree"
449 msgstr "Дерево"
449 msgstr "Дерево"
450
450
451 #: templates/boards/thread.html:35
451 #: templates/boards/thread.html:35
452 msgid "message"
452 msgid "message"
453 msgid_plural "messages"
453 msgid_plural "messages"
454 msgstr[0] "сообщение"
454 msgstr[0] "сообщение"
455 msgstr[1] "сообщения"
455 msgstr[1] "сообщения"
456 msgstr[2] "сообщений"
456 msgstr[2] "сообщений"
457
457
458 #: templates/boards/thread.html:38
458 #: templates/boards/thread.html:38
459 msgid "image"
459 msgid "image"
460 msgid_plural "images"
460 msgid_plural "images"
461 msgstr[0] "изображение"
461 msgstr[0] "изображение"
462 msgstr[1] "изображения"
462 msgstr[1] "изображения"
463 msgstr[2] "изображений"
463 msgstr[2] "изображений"
464
464
465 #: templates/boards/thread.html:40
465 #: templates/boards/thread.html:40
466 msgid "Last update: "
466 msgid "Last update: "
467 msgstr "Последнее обновление: "
467 msgstr "Последнее обновление: "
468
468
469 #: templates/boards/thread_gallery.html:36
469 #: templates/boards/thread_gallery.html:36
470 msgid "No images."
470 msgid "No images."
471 msgstr "Нет изображений."
471 msgstr "Нет изображений."
472
472
473 #: templates/boards/thread_normal.html:30
473 #: templates/boards/thread_normal.html:30
474 msgid "posts to bumplimit"
474 msgid "posts to bumplimit"
475 msgstr "сообщений до бамплимита"
475 msgstr "сообщений до бамплимита"
476
476
477 #: templates/boards/thread_normal.html:44
477 #: templates/boards/thread_normal.html:44
478 msgid "Reply to thread"
478 msgid "Reply to thread"
479 msgstr "Ответить в тему"
479 msgstr "Ответить в тему"
480
480
481 #: templates/boards/thread_normal.html:44
481 #: templates/boards/thread_normal.html:44
482 msgid "to message "
482 msgid "to message "
483 msgstr "на сообщение"
483 msgstr "на сообщение"
484
484
485 #: templates/boards/thread_normal.html:59
485 #: templates/boards/thread_normal.html:59
486 msgid "Close form"
486 msgid "Reset form"
487 msgstr "Закрыть форму"
487 msgstr "Сбросить форму"
488
488
489 #: templates/search/search.html:17
489 #: templates/search/search.html:17
490 msgid "Ok"
490 msgid "Ok"
491 msgstr "Ок"
491 msgstr "Ок"
492
492
493 #: utils.py:120
493 #: utils.py:120
494 #, python-format
494 #, python-format
495 msgid "File must be less than %s but is %s."
495 msgid "File must be less than %s but is %s."
496 msgstr "Файл должен быть менее %s, но его размер %s."
496 msgstr "Файл должен быть менее %s, но его размер %s."
497
497
498 msgid "Please wait %(delay)d second before sending message"
498 msgid "Please wait %(delay)d second before sending message"
499 msgid_plural "Please wait %(delay)d seconds before sending message"
499 msgid_plural "Please wait %(delay)d seconds before sending message"
500 msgstr[0] "Пожалуйста подождите %(delay)d секунду перед отправкой сообщения"
500 msgstr[0] "Пожалуйста подождите %(delay)d секунду перед отправкой сообщения"
501 msgstr[1] "Пожалуйста подождите %(delay)d секунды перед отправкой сообщения"
501 msgstr[1] "Пожалуйста подождите %(delay)d секунды перед отправкой сообщения"
502 msgstr[2] "Пожалуйста подождите %(delay)d секунд перед отправкой сообщения"
502 msgstr[2] "Пожалуйста подождите %(delay)d секунд перед отправкой сообщения"
503
503
504 msgid "New threads"
504 msgid "New threads"
505 msgstr "Новые темы"
505 msgstr "Новые темы"
506
506
507 #, python-format
507 #, python-format
508 msgid "Max file size is %(size)s."
508 msgid "Max file size is %(size)s."
509 msgstr "Максимальный размер файла %(size)s."
509 msgstr "Максимальный размер файла %(size)s."
510
510
511 msgid "Size of media:"
511 msgid "Size of media:"
512 msgstr "Размер медиа:"
512 msgstr "Размер медиа:"
513
513
514 msgid "Statistics"
514 msgid "Statistics"
515 msgstr "Статистика"
515 msgstr "Статистика"
516
516
517 msgid "Invalid PoW."
517 msgid "Invalid PoW."
518 msgstr "Неверный PoW."
518 msgstr "Неверный PoW."
519
519
520 msgid "Stale PoW."
520 msgid "Stale PoW."
521 msgstr "PoW устарел."
521 msgstr "PoW устарел."
522
522
523 msgid "Show"
523 msgid "Show"
524 msgstr "Показывать"
524 msgstr "Показывать"
525
525
526 msgid "Hide"
526 msgid "Hide"
527 msgstr "Скрывать"
527 msgstr "Скрывать"
528
528
529 msgid "Add to favorites"
529 msgid "Add to favorites"
530 msgstr "Добавить в избранное"
530 msgstr "Добавить в избранное"
531
531
532 msgid "Remove from favorites"
532 msgid "Remove from favorites"
533 msgstr "Убрать из избранного"
533 msgstr "Убрать из избранного"
534
534
535 msgid "Monochrome"
535 msgid "Monochrome"
536 msgstr "Монохромный"
536 msgstr "Монохромный"
537
537
538 msgid "Subsections: "
538 msgid "Subsections: "
539 msgstr "Подразделы: "
539 msgstr "Подразделы: "
540
540
541 msgid "Change file source"
541 msgid "Change file source"
542 msgstr "Изменить источник файла"
542 msgstr "Изменить источник файла"
543
543
544 msgid "interesting"
544 msgid "interesting"
545 msgstr "интересное"
545 msgstr "интересное"
546
546
547 msgid "images"
547 msgid "images"
548 msgstr "изображения"
548 msgstr "изображения"
549
549
550 msgid "Delete post"
550 msgid "Delete post"
551 msgstr "Удалить пост"
551 msgstr "Удалить пост"
552
552
553 msgid "Delete thread"
553 msgid "Delete thread"
554 msgstr "Удалить тему"
554 msgstr "Удалить тему"
555
555
556 msgid "Messages per day/week/month:"
556 msgid "Messages per day/week/month:"
557 msgstr "Сообщений за день/неделю/месяц:"
557 msgstr "Сообщений за день/неделю/месяц:"
558
558
559 msgid "Subscribe to thread"
559 msgid "Subscribe to thread"
560 msgstr "Подписаться на тему"
560 msgstr "Подписаться на тему"
561
561
562 msgid "Active threads:"
562 msgid "Active threads:"
563 msgstr "Активные темы:"
563 msgstr "Активные темы:"
564
564
565 msgid "No active threads today."
565 msgid "No active threads today."
566 msgstr "Сегодня нет активных тем."
566 msgstr "Сегодня нет активных тем."
567
567
568 msgid "Insert URLs on separate lines."
568 msgid "Insert URLs on separate lines."
569 msgstr "Вставляйте ссылки на отдельных строках."
569 msgstr "Вставляйте ссылки на отдельных строках."
570
570
571 msgid "You can post no more than %(files)d file."
571 msgid "You can post no more than %(files)d file."
572 msgid_plural "You can post no more than %(files)d files."
572 msgid_plural "You can post no more than %(files)d files."
573 msgstr[0] "Вы можете отправить не более %(files)d файла."
573 msgstr[0] "Вы можете отправить не более %(files)d файла."
574 msgstr[1] "Вы можете отправить не более %(files)d файлов."
574 msgstr[1] "Вы можете отправить не более %(files)d файлов."
575 msgstr[2] "Вы можете отправить не более %(files)d файлов."
575 msgstr[2] "Вы можете отправить не более %(files)d файлов."
576
576
577 #, python-format
577 #, python-format
578 msgid "Max file number is %(max_files)s."
578 msgid "Max file number is %(max_files)s."
579 msgstr "Максимальное количество файлов %(max_files)s."
579 msgstr "Максимальное количество файлов %(max_files)s."
580
580
581 msgid "Moderation"
581 msgid "Moderation"
582 msgstr "Модерация"
582 msgstr "Модерация"
583
583
584 msgid "Check for duplicates"
584 msgid "Check for duplicates"
585 msgstr "Проверять на дубликаты"
585 msgstr "Проверять на дубликаты"
586
586
587 msgid "Some files are already present on the board."
587 msgid "Some files are already present on the board."
588 msgstr "Некоторые файлы уже присутствуют на борде."
588 msgstr "Некоторые файлы уже присутствуют на борде."
589
589
590 msgid "Do not download URLs"
590 msgid "Do not download URLs"
591 msgstr "Не загружать ссылки"
591 msgstr "Не загружать ссылки"
592
592
@@ -1,203 +1,199 b''
1 .ui-button {
1 .ui-button {
2 display: none;
2 display: none;
3 }
3 }
4
4
5 .ui-dialog-content {
5 .ui-dialog-content {
6 padding: 0;
6 padding: 0;
7 min-height: 0;
7 min-height: 0;
8 }
8 }
9
9
10 .mark_btn {
10 .mark_btn {
11 cursor: pointer;
11 cursor: pointer;
12 }
12 }
13
13
14 .img-full {
14 .img-full {
15 position: fixed;
15 position: fixed;
16 background-color: #CCC;
16 background-color: #CCC;
17 border: 1px solid #000;
17 border: 1px solid #000;
18 cursor: pointer;
18 cursor: pointer;
19 }
19 }
20
20
21 .strikethrough {
21 .strikethrough {
22 text-decoration: line-through;
22 text-decoration: line-through;
23 }
23 }
24
24
25 .post_preview {
25 .post_preview {
26 z-index: 300;
26 z-index: 300;
27 position:absolute;
27 position:absolute;
28 }
28 }
29
29
30 .gallery_image {
30 .gallery_image {
31 display: inline-block;
31 display: inline-block;
32 }
32 }
33
33
34 @media print {
34 @media print {
35 .post-form-w {
35 .post-form-w {
36 display: none;
36 display: none;
37 }
37 }
38 }
38 }
39
39
40 input[name="image"] {
40 input[name="image"] {
41 display: block;
41 display: block;
42 width: 100px;
42 width: 100px;
43 height: 100px;
43 height: 100px;
44 cursor: pointer;
44 cursor: pointer;
45 position: absolute;
45 position: absolute;
46 opacity: 0;
46 opacity: 0;
47 z-index: 1;
47 z-index: 1;
48 }
48 }
49
49
50 .file_wrap {
50 .file_wrap {
51 width: 100px;
51 width: 100px;
52 height: 100px;
52 height: 100px;
53 border: solid 1px white;
53 border: solid 1px white;
54 display: inline-block;
54 display: inline-block;
55 }
55 }
56
56
57 form > .file_wrap {
57 form > .file_wrap {
58 float: left;
58 float: left;
59 }
59 }
60
60
61 .file-thumb {
61 .file-thumb {
62 width: 100px;
62 width: 100px;
63 height: 100px;
63 height: 100px;
64 background-size: cover;
64 background-size: cover;
65 background-position: center;
65 background-position: center;
66 }
66 }
67
67
68 .compact-form-text {
68 .compact-form-text {
69 margin-left:110px;
69 margin-left:110px;
70 }
70 }
71
71
72 textarea, input {
72 textarea, input {
73 -moz-box-sizing: border-box;
73 -moz-box-sizing: border-box;
74 -webkit-box-sizing: border-box;
74 -webkit-box-sizing: border-box;
75 box-sizing: border-box;
75 box-sizing: border-box;
76 }
76 }
77
77
78 .compact-form-text > textarea {
78 .compact-form-text > textarea {
79 height: 100px;
79 height: 100px;
80 width: 100%;
80 width: 100%;
81 }
81 }
82
82
83 .post-button-form {
83 .post-button-form {
84 display: inline;
84 display: inline;
85 }
85 }
86
86
87 .post-button-form > button, #autoupdate {
87 .post-button-form > button, #autoupdate {
88 border: none;
88 border: none;
89 margin: inherit;
89 margin: inherit;
90 padding: inherit;
90 padding: inherit;
91 background: none;
91 background: none;
92 font-size: inherit;
92 font-size: inherit;
93 cursor: pointer;
93 cursor: pointer;
94 }
94 }
95
95
96 #form-close-button {
97 display: none;
98 }
99
100 .post-image-full {
96 .post-image-full {
101 width: 100%;
97 width: 100%;
102 height: auto;
98 height: auto;
103 }
99 }
104
100
105 #preview-text {
101 #preview-text {
106 display: none;
102 display: none;
107 }
103 }
108
104
109 .random-images-table {
105 .random-images-table {
110 text-align: center;
106 text-align: center;
111 }
107 }
112
108
113 .random-images-table > div {
109 .random-images-table > div {
114 margin-left: auto;
110 margin-left: auto;
115 margin-right: auto;
111 margin-right: auto;
116 }
112 }
117
113
118 .tag-image, .tag-text-data {
114 .tag-image, .tag-text-data {
119 display: inline-block;
115 display: inline-block;
120 }
116 }
121
117
122 .tag-text-data > h2 {
118 .tag-text-data > h2 {
123 margin: 0;
119 margin: 0;
124 }
120 }
125
121
126 .tag-image {
122 .tag-image {
127 margin-right: 5px;
123 margin-right: 5px;
128 }
124 }
129
125
130 .reply-to-message {
126 .reply-to-message {
131 display: none;
127 display: none;
132 }
128 }
133
129
134 .tripcode {
130 .tripcode {
135 padding: 2px;
131 padding: 2px;
136 }
132 }
137
133
138 #fav-panel {
134 #fav-panel {
139 display: none;
135 display: none;
140 margin: 1ex;
136 margin: 1ex;
141 }
137 }
142
138
143 .hidden_post {
139 .hidden_post {
144 opacity: 0.2;
140 opacity: 0.2;
145 }
141 }
146
142
147 .hidden_post:hover {
143 .hidden_post:hover {
148 opacity: 1;
144 opacity: 1;
149 }
145 }
150
146
151 .monochrome > .image > .thumb > img {
147 .monochrome > .image > .thumb > img {
152 filter: grayscale(100%);
148 filter: grayscale(100%);
153 -webkit-filter: grayscale(100%);
149 -webkit-filter: grayscale(100%);
154 }
150 }
155
151
156 #quote-button {
152 #quote-button {
157 position: absolute;
153 position: absolute;
158 display: none;
154 display: none;
159 cursor: pointer;
155 cursor: pointer;
160 z-index: 400;
156 z-index: 400;
161 }
157 }
162
158
163 .required-field:before {
159 .required-field:before {
164 content: '* ';
160 content: '* ';
165 }
161 }
166
162
167 .hint {
163 .hint {
168 border-bottom: dashed 1px;
164 border-bottom: dashed 1px;
169 cursor: help;
165 cursor: help;
170 }
166 }
171
167
172 .url-image:hover {
168 .url-image:hover {
173 filter: invert(100%);
169 filter: invert(100%);
174 }
170 }
175
171
176 .landing-tags, .landing-images {
172 .landing-tags, .landing-images {
177 max-width: 800px;
173 max-width: 800px;
178 margin-left: auto;
174 margin-left: auto;
179 margin-right: auto;
175 margin-right: auto;
180 }
176 }
181
177
182 .landing-images {
178 .landing-images {
183 text-align: center;
179 text-align: center;
184 }
180 }
185
181
186 .landing-threads {
182 .landing-threads {
187 margin-left: auto;
183 margin-left: auto;
188 margin-right: auto;
184 margin-right: auto;
189 text-align: center;
185 text-align: center;
190 display: flex;
186 display: flex;
191 flex-wrap: wrap;
187 flex-wrap: wrap;
192 justify-content: space-around;
188 justify-content: space-around;
193 }
189 }
194
190
195 .landing-threads > .thread-short {
191 .landing-threads > .thread-short {
196 display: inline-block;
192 display: inline-block;
197 width: 240px;
193 width: 240px;
198 }
194 }
199
195
200 audio {
196 audio {
201 width: 200px;
197 width: 200px;
202 }
198 }
203
199
@@ -1,155 +1,165 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 CLOSE_BUTTON = '#form-close-button';
27 var REPLY_TO_MSG = '.reply-to-message';
26 var REPLY_TO_MSG = '.reply-to-message';
28 var REPLY_TO_MSG_ID = '#reply-to-message-id';
27 var REPLY_TO_MSG_ID = '#reply-to-message-id';
29
28
30 var $html = $("html, body");
29 var $html = $("html, body");
31
30
32 function moveCaretToEnd(el) {
31 function moveCaretToEnd(el) {
33 var newPos = el.val().length;
32 var newPos = el.val().length;
34 el[0].setSelectionRange(newPos, newPos);
33 el[0].setSelectionRange(newPos, newPos);
35 }
34 }
36
35
37 function getForm() {
36 function getForm() {
38 return $('.post-form-w');
37 return $('.post-form-w');
39 }
38 }
40
39
41 function resetFormPosition() {
40 /**
41 * Clear all entered values in the form fields
42 */
43 function resetForm() {
42 var form = getForm();
44 var form = getForm();
45
46 form.find('input:text, input:password, input:file, select, textarea').val('');
47 form.find('input:radio, input:checkbox').removeAttr('checked').removeAttr('selected');
48 $('.file_wrap').find('.file-thumb').remove();
49 $('#preview-text').hide();
50
51 resetFormPosition(form);
52 }
53
54 function resetFormPosition(form) {
43 form.insertAfter($('.thread'));
55 form.insertAfter($('.thread'));
44
56
45 $(CLOSE_BUTTON).hide();
46 $(REPLY_TO_MSG).hide();
57 $(REPLY_TO_MSG).hide();
47 }
58 }
48
59
49 function showFormAfter(blockToInsertAfter) {
60 function showFormAfter(blockToInsertAfter) {
50 var form = getForm();
61 var form = getForm();
51 form.insertAfter(blockToInsertAfter);
62 form.insertAfter(blockToInsertAfter);
52
63
53 $(CLOSE_BUTTON).show();
54 form.show();
64 form.show();
55 $(REPLY_TO_MSG_ID).text(blockToInsertAfter.attr('id'));
65 $(REPLY_TO_MSG_ID).text(blockToInsertAfter.attr('id'));
56 $(REPLY_TO_MSG).show();
66 $(REPLY_TO_MSG).show();
57 }
67 }
58
68
59 function addQuickReply(postId) {
69 function addQuickReply(postId) {
60 var blockToInsert = null;
70 var blockToInsert = null;
61 var textAreaJq = getPostTextarea();
71 var textAreaJq = getPostTextarea();
62 var postLinkRaw = '[post]' + postId + '[/post]'
72 var postLinkRaw = '[post]' + postId + '[/post]'
63 var textToAdd = '';
73 var textToAdd = '';
64
74
65 if (postId != null) {
75 if (postId != null) {
66 var post = $('#' + postId);
76 var post = $('#' + postId);
67
77
68 // If this is not OP, add reflink to the post. If there already is
78 // If this is not OP, add reflink to the post. If there already is
69 // the same reflink, don't add it again.
79 // the same reflink, don't add it again.
70 var postText = textAreaJq.val();
80 var postText = textAreaJq.val();
71 if (!post.is(':first-child') && postText.indexOf(postLinkRaw) < 0) {
81 if (!post.is(':first-child') && postText.indexOf(postLinkRaw) < 0) {
72 // Insert line break if none is present.
82 // Insert line break if none is present.
73 if (postText.length > 0 && !postText.endsWith('\n') && !postText.endsWith('\r')) {
83 if (postText.length > 0 && !postText.endsWith('\n') && !postText.endsWith('\r')) {
74 textToAdd += '\n';
84 textToAdd += '\n';
75 }
85 }
76 textToAdd += postLinkRaw + '\n';
86 textToAdd += postLinkRaw + '\n';
77 }
87 }
78
88
79 textAreaJq.val(textAreaJq.val()+ textToAdd);
89 textAreaJq.val(textAreaJq.val()+ textToAdd);
80 blockToInsert = post;
90 blockToInsert = post;
81 } else {
91 } else {
82 blockToInsert = $('.thread');
92 blockToInsert = $('.thread');
83 }
93 }
84 showFormAfter(blockToInsert);
94 showFormAfter(blockToInsert);
85
95
86 textAreaJq.focus();
96 textAreaJq.focus();
87
97
88 moveCaretToEnd(textAreaJq);
98 moveCaretToEnd(textAreaJq);
89 }
99 }
90
100
91 function addQuickQuote() {
101 function addQuickQuote() {
92 var textAreaJq = getPostTextarea();
102 var textAreaJq = getPostTextarea();
93
103
94 var quoteButton = $("#quote-button");
104 var quoteButton = $("#quote-button");
95 var postId = quoteButton.attr('data-post-id');
105 var postId = quoteButton.attr('data-post-id');
96 if (postId != null) {
106 if (postId != null) {
97 addQuickReply(postId);
107 addQuickReply(postId);
98 }
108 }
99
109
100 var textToAdd = '';
110 var textToAdd = '';
101 var selection = window.getSelection().toString();
111 var selection = window.getSelection().toString();
102 if (selection.length == 0) {
112 if (selection.length == 0) {
103 selection = quoteButton.attr('data-text');
113 selection = quoteButton.attr('data-text');
104 }
114 }
105 if (selection.length > 0) {
115 if (selection.length > 0) {
106 textToAdd += '[quote]' + selection + '[/quote]\n';
116 textToAdd += '[quote]' + selection + '[/quote]\n';
107 }
117 }
108
118
109 textAreaJq.val(textAreaJq.val() + textToAdd);
119 textAreaJq.val(textAreaJq.val() + textToAdd);
110
120
111 textAreaJq.focus();
121 textAreaJq.focus();
112
122
113 moveCaretToEnd(textAreaJq);
123 moveCaretToEnd(textAreaJq);
114 }
124 }
115
125
116 function scrollToBottom() {
126 function scrollToBottom() {
117 $html.animate({scrollTop: $html.height()}, "fast");
127 $html.animate({scrollTop: $html.height()}, "fast");
118 }
128 }
119
129
120 function showQuoteButton() {
130 function showQuoteButton() {
121 var selection = window.getSelection().getRangeAt(0).getBoundingClientRect();
131 var selection = window.getSelection().getRangeAt(0).getBoundingClientRect();
122 var quoteButton = $("#quote-button");
132 var quoteButton = $("#quote-button");
123 if (selection.width > 0) {
133 if (selection.width > 0) {
124 // quoteButton.offset({ top: selection.top - selection.height, left: selection.left });
134 // quoteButton.offset({ top: selection.top - selection.height, left: selection.left });
125 quoteButton.css({top: selection.top + $(window).scrollTop() - 30, left: selection.left});
135 quoteButton.css({top: selection.top + $(window).scrollTop() - 30, left: selection.left});
126 quoteButton.show();
136 quoteButton.show();
127
137
128 var text = window.getSelection().toString();
138 var text = window.getSelection().toString();
129 quoteButton.attr('data-text', text);
139 quoteButton.attr('data-text', text);
130
140
131 var rect = window.getSelection().getRangeAt(0).getBoundingClientRect();
141 var rect = window.getSelection().getRangeAt(0).getBoundingClientRect();
132 var element = $(document.elementFromPoint(rect.x, rect.y));
142 var element = $(document.elementFromPoint(rect.x, rect.y));
133 var postId = null;
143 var postId = null;
134 if (element.hasClass('post')) {
144 if (element.hasClass('post')) {
135 postId = element.attr('id');
145 postId = element.attr('id');
136 } else {
146 } else {
137 var postParent = element.parents('.post');
147 var postParent = element.parents('.post');
138 if (postParent.length > 0) {
148 if (postParent.length > 0) {
139 postId = postParent.attr('id');
149 postId = postParent.attr('id');
140 }
150 }
141 }
151 }
142 quoteButton.attr('data-post-id', postId);
152 quoteButton.attr('data-post-id', postId);
143 } else {
153 } else {
144 quoteButton.hide();
154 quoteButton.hide();
145 }
155 }
146 }
156 }
147
157
148 $(document).ready(function() {
158 $(document).ready(function() {
149 $('body').on('mouseup', function() {
159 $('body').on('mouseup', function() {
150 showQuoteButton();
160 showQuoteButton();
151 });
161 });
152 $("#quote-button").click(function() {
162 $("#quote-button").click(function() {
153 addQuickQuote();
163 addQuickQuote();
154 })
164 })
155 });
165 });
@@ -1,399 +1,388 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 // TODO These need to be syncronized with board settings.
32 var JS_AUTOUPDATE_PERIOD = 20000;
32 var JS_AUTOUPDATE_PERIOD = 20000;
33 // TODO This needs to be the same for attachment download time limit.
33 // TODO This needs to be the same for attachment download time limit.
34 var POST_AJAX_TIMEOUT = 30000;
34 var POST_AJAX_TIMEOUT = 30000;
35 var BLINK_SPEED = 500;
35 var BLINK_SPEED = 500;
36
36
37 var ALLOWED_FOR_PARTIAL_UPDATE = [
37 var ALLOWED_FOR_PARTIAL_UPDATE = [
38 'refmap',
38 'refmap',
39 'post-info'
39 'post-info'
40 ];
40 ];
41
41
42 var ATTR_CLASS = 'class';
42 var ATTR_CLASS = 'class';
43 var ATTR_UID = 'data-uid';
43 var ATTR_UID = 'data-uid';
44
44
45 var unreadPosts = 0;
45 var unreadPosts = 0;
46 var documentOriginalTitle = '';
46 var documentOriginalTitle = '';
47
47
48 // Thread ID does not change, can be stored one time
48 // Thread ID does not change, can be stored one time
49 var threadId = $('div.thread').children(CLASS_POST).first().attr('id');
49 var threadId = $('div.thread').children(CLASS_POST).first().attr('id');
50 var blinkColor = $('<div class="post-blink"></div>').css('background-color');
50 var blinkColor = $('<div class="post-blink"></div>').css('background-color');
51
51
52 /**
52 /**
53 * Get diff of the posts from the current thread timestamp.
53 * Get diff of the posts from the current thread timestamp.
54 * This is required if the browser was closed and some post updates were
54 * This is required if the browser was closed and some post updates were
55 * missed.
55 * missed.
56 */
56 */
57 function getThreadDiff() {
57 function getThreadDiff() {
58 var all_posts = $('.post');
58 var all_posts = $('.post');
59
59
60 var uids = '';
60 var uids = '';
61 var posts = all_posts;
61 var posts = all_posts;
62 for (var i = 0; i < posts.length; i++) {
62 for (var i = 0; i < posts.length; i++) {
63 uids += posts[i].getAttribute('data-uid') + ' ';
63 uids += posts[i].getAttribute('data-uid') + ' ';
64 }
64 }
65
65
66 var data = {
66 var data = {
67 uids: uids,
67 uids: uids,
68 thread: threadId
68 thread: threadId
69 };
69 };
70
70
71 var diffUrl = '/api/diff_thread/';
71 var diffUrl = '/api/diff_thread/';
72
72
73 $.post(diffUrl,
73 $.post(diffUrl,
74 data,
74 data,
75 function(data) {
75 function(data) {
76 var updatedPosts = data.updated;
76 var updatedPosts = data.updated;
77 var addedPostCount = 0;
77 var addedPostCount = 0;
78
78
79 for (var i = 0; i < updatedPosts.length; i++) {
79 for (var i = 0; i < updatedPosts.length; i++) {
80 var postText = updatedPosts[i];
80 var postText = updatedPosts[i];
81 var post = $(postText);
81 var post = $(postText);
82
82
83 if (updatePost(post) == POST_ADDED) {
83 if (updatePost(post) == POST_ADDED) {
84 addedPostCount++;
84 addedPostCount++;
85 }
85 }
86 }
86 }
87
87
88 var hasMetaUpdates = updatedPosts.length > 0;
88 var hasMetaUpdates = updatedPosts.length > 0;
89 if (hasMetaUpdates) {
89 if (hasMetaUpdates) {
90 updateMetadataPanel();
90 updateMetadataPanel();
91 }
91 }
92
92
93 if (addedPostCount > 0) {
93 if (addedPostCount > 0) {
94 updateBumplimitProgress(addedPostCount);
94 updateBumplimitProgress(addedPostCount);
95 }
95 }
96
96
97 if (updatedPosts.length > 0) {
97 if (updatedPosts.length > 0) {
98 showNewPostsTitle(addedPostCount);
98 showNewPostsTitle(addedPostCount);
99 }
99 }
100
100
101 // TODO Process removed posts if any
101 // TODO Process removed posts if any
102 $('.metapanel').attr('data-last-update', data.last_update);
102 $('.metapanel').attr('data-last-update', data.last_update);
103
103
104 if (data.subscribed == 'True') {
104 if (data.subscribed == 'True') {
105 var favButton = $('#thread-fav-button .not_fav');
105 var favButton = $('#thread-fav-button .not_fav');
106
106
107 if (favButton.length > 0) {
107 if (favButton.length > 0) {
108 favButton.attr('value', 'unsubscribe');
108 favButton.attr('value', 'unsubscribe');
109 favButton.removeClass('not_fav');
109 favButton.removeClass('not_fav');
110 favButton.addClass('fav');
110 favButton.addClass('fav');
111 }
111 }
112 }
112 }
113 },
113 },
114 'json'
114 'json'
115 )
115 )
116 }
116 }
117
117
118 /**
118 /**
119 * Add or update the post on html page.
119 * Add or update the post on html page.
120 */
120 */
121 function updatePost(postHtml) {
121 function updatePost(postHtml) {
122 // This needs to be set on start because the page is scrolled after posts
122 // This needs to be set on start because the page is scrolled after posts
123 // are added or updated
123 // are added or updated
124 var bottom = isPageBottom();
124 var bottom = isPageBottom();
125
125
126 var post = $(postHtml);
126 var post = $(postHtml);
127
127
128 var threadBlock = $('div.thread');
128 var threadBlock = $('div.thread');
129
129
130 var postId = post.attr('id');
130 var postId = post.attr('id');
131
131
132 // If the post already exists, replace it. Otherwise add as a new one.
132 // If the post already exists, replace it. Otherwise add as a new one.
133 var existingPosts = threadBlock.children('.post[id=' + postId + ']');
133 var existingPosts = threadBlock.children('.post[id=' + postId + ']');
134
134
135 var type;
135 var type;
136
136
137 if (existingPosts.size() > 0) {
137 if (existingPosts.size() > 0) {
138 replacePartial(existingPosts.first(), post, false);
138 replacePartial(existingPosts.first(), post, false);
139 post = existingPosts.first();
139 post = existingPosts.first();
140
140
141 type = POST_UPDATED;
141 type = POST_UPDATED;
142 } else {
142 } else {
143 post.appendTo(threadBlock);
143 post.appendTo(threadBlock);
144
144
145 if (bottom) {
145 if (bottom) {
146 scrollToBottom();
146 scrollToBottom();
147 }
147 }
148
148
149 type = POST_ADDED;
149 type = POST_ADDED;
150 }
150 }
151
151
152 processNewPost(post);
152 processNewPost(post);
153
153
154 return type;
154 return type;
155 }
155 }
156
156
157 /**
157 /**
158 * Initiate a blinking animation on a node to show it was updated.
158 * Initiate a blinking animation on a node to show it was updated.
159 */
159 */
160 function blink(node) {
160 function blink(node) {
161 node.effect('highlight', { color: blinkColor }, BLINK_SPEED);
161 node.effect('highlight', { color: blinkColor }, BLINK_SPEED);
162 }
162 }
163
163
164 function isPageBottom() {
164 function isPageBottom() {
165 var scroll = $(window).scrollTop() / ($(document).height()
165 var scroll = $(window).scrollTop() / ($(document).height()
166 - $(window).height());
166 - $(window).height());
167
167
168 return scroll == 1
168 return scroll == 1
169 }
169 }
170
170
171 function enableJsUpdate() {
171 function enableJsUpdate() {
172 setInterval(getThreadDiff, JS_AUTOUPDATE_PERIOD);
172 setInterval(getThreadDiff, JS_AUTOUPDATE_PERIOD);
173 return true;
173 return true;
174 }
174 }
175
175
176 function initAutoupdate() {
176 function initAutoupdate() {
177 return enableJsUpdate();
177 return enableJsUpdate();
178 }
178 }
179
179
180 function getReplyCount() {
180 function getReplyCount() {
181 return $('.thread').children(CLASS_POST).length
181 return $('.thread').children(CLASS_POST).length
182 }
182 }
183
183
184 function getImageCount() {
184 function getImageCount() {
185 return $('.thread').find('img').length
185 return $('.thread').find('img').length
186 }
186 }
187
187
188 /**
188 /**
189 * Update post count, images count and last update time in the metadata
189 * Update post count, images count and last update time in the metadata
190 * panel.
190 * panel.
191 */
191 */
192 function updateMetadataPanel() {
192 function updateMetadataPanel() {
193 var replyCountField = $('#reply-count');
193 var replyCountField = $('#reply-count');
194 var imageCountField = $('#image-count');
194 var imageCountField = $('#image-count');
195
195
196 var replyCount = getReplyCount();
196 var replyCount = getReplyCount();
197 replyCountField.text(replyCount);
197 replyCountField.text(replyCount);
198 var imageCount = getImageCount();
198 var imageCount = getImageCount();
199 imageCountField.text(imageCount);
199 imageCountField.text(imageCount);
200
200
201 var lastUpdate = $('.post:last').children('.post-info').first()
201 var lastUpdate = $('.post:last').children('.post-info').first()
202 .children('.pub_time').first().html();
202 .children('.pub_time').first().html();
203 if (lastUpdate !== '') {
203 if (lastUpdate !== '') {
204 var lastUpdateField = $('#last-update');
204 var lastUpdateField = $('#last-update');
205 lastUpdateField.html(lastUpdate);
205 lastUpdateField.html(lastUpdate);
206 blink(lastUpdateField);
206 blink(lastUpdateField);
207 }
207 }
208
208
209 blink(replyCountField);
209 blink(replyCountField);
210 blink(imageCountField);
210 blink(imageCountField);
211 }
211 }
212
212
213 /**
213 /**
214 * Update bumplimit progress bar
214 * Update bumplimit progress bar
215 */
215 */
216 function updateBumplimitProgress(postDelta) {
216 function updateBumplimitProgress(postDelta) {
217 var progressBar = $('#bumplimit_progress');
217 var progressBar = $('#bumplimit_progress');
218 if (progressBar) {
218 if (progressBar) {
219 var postsToLimitElement = $('#left_to_limit');
219 var postsToLimitElement = $('#left_to_limit');
220
220
221 var oldPostsToLimit = parseInt(postsToLimitElement.text());
221 var oldPostsToLimit = parseInt(postsToLimitElement.text());
222 var postCount = getReplyCount();
222 var postCount = getReplyCount();
223 var bumplimit = postCount - postDelta + oldPostsToLimit;
223 var bumplimit = postCount - postDelta + oldPostsToLimit;
224
224
225 var newPostsToLimit = bumplimit - postCount;
225 var newPostsToLimit = bumplimit - postCount;
226 if (newPostsToLimit <= 0) {
226 if (newPostsToLimit <= 0) {
227 $('.bar-bg').remove();
227 $('.bar-bg').remove();
228 } else {
228 } else {
229 postsToLimitElement.text(newPostsToLimit);
229 postsToLimitElement.text(newPostsToLimit);
230 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
230 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
231 }
231 }
232 }
232 }
233 }
233 }
234
234
235 /**
235 /**
236 * Show 'new posts' text in the title if the document is not visible to a user
236 * Show 'new posts' text in the title if the document is not visible to a user
237 */
237 */
238 function showNewPostsTitle(newPostCount) {
238 function showNewPostsTitle(newPostCount) {
239 if (document.hidden) {
239 if (document.hidden) {
240 if (documentOriginalTitle === '') {
240 if (documentOriginalTitle === '') {
241 documentOriginalTitle = document.title;
241 documentOriginalTitle = document.title;
242 }
242 }
243 unreadPosts = unreadPosts + newPostCount;
243 unreadPosts = unreadPosts + newPostCount;
244
244
245 var newTitle = null;
245 var newTitle = null;
246 if (unreadPosts > 0) {
246 if (unreadPosts > 0) {
247 newTitle = '[' + unreadPosts + '] ';
247 newTitle = '[' + unreadPosts + '] ';
248 } else {
248 } else {
249 newTitle = '* ';
249 newTitle = '* ';
250 }
250 }
251 newTitle += documentOriginalTitle;
251 newTitle += documentOriginalTitle;
252
252
253 document.title = newTitle;
253 document.title = newTitle;
254
254
255 document.addEventListener('visibilitychange', function() {
255 document.addEventListener('visibilitychange', function() {
256 if (documentOriginalTitle !== '') {
256 if (documentOriginalTitle !== '') {
257 document.title = documentOriginalTitle;
257 document.title = documentOriginalTitle;
258 documentOriginalTitle = '';
258 documentOriginalTitle = '';
259 unreadPosts = 0;
259 unreadPosts = 0;
260 }
260 }
261
261
262 document.removeEventListener('visibilitychange', null);
262 document.removeEventListener('visibilitychange', null);
263 });
263 });
264 }
264 }
265 }
265 }
266
266
267 /**
268 * Clear all entered values in the form fields
269 */
270 function resetForm(form) {
271 form.find('input:text, input:password, input:file, select, textarea').val('');
272 form.find('input:radio, input:checkbox')
273 .removeAttr('checked').removeAttr('selected');
274 $('.file_wrap').find('.file-thumb').remove();
275 $('#preview-text').hide();
276 }
277
267
278 /**
268 /**
279 * When the form is posted, this method will be run as a callback
269 * When the form is posted, this method will be run as a callback
280 */
270 */
281 function updateOnPost(response, statusText, xhr, form) {
271 function updateOnPost(response, statusText, xhr, form) {
282 var json = $.parseJSON(response);
272 var json = $.parseJSON(response);
283 var status = json.status;
273 var status = json.status;
284
274
285 showAsErrors(form, '');
275 showAsErrors(form, '');
286 $('.post-form-w').unblock();
276 $('.post-form-w').unblock();
287
277
288 if (status === 'ok') {
278 if (status === 'ok') {
289 resetFormPosition();
279 resetForm();
290 resetForm(form);
291 getThreadDiff();
280 getThreadDiff();
292 scrollToBottom();
281 scrollToBottom();
293 } else {
282 } else {
294 var errors = json.errors;
283 var errors = json.errors;
295 for (var i = 0; i < errors.length; i++) {
284 for (var i = 0; i < errors.length; i++) {
296 var fieldErrors = errors[i];
285 var fieldErrors = errors[i];
297
286
298 var error = fieldErrors.errors;
287 var error = fieldErrors.errors;
299
288
300 showAsErrors(form, error);
289 showAsErrors(form, error);
301 }
290 }
302 }
291 }
303 }
292 }
304
293
305
294
306 /**
295 /**
307 * Run js methods that are usually run on the document, on the new post
296 * Run js methods that are usually run on the document, on the new post
308 */
297 */
309 function processNewPost(post) {
298 function processNewPost(post) {
310 addScriptsToPost(post);
299 addScriptsToPost(post);
311 blink(post);
300 blink(post);
312 }
301 }
313
302
314 function replacePartial(oldNode, newNode, recursive) {
303 function replacePartial(oldNode, newNode, recursive) {
315 if (!equalNodes(oldNode, newNode)) {
304 if (!equalNodes(oldNode, newNode)) {
316 // Update parent node attributes
305 // Update parent node attributes
317 updateNodeAttr(oldNode, newNode, ATTR_CLASS);
306 updateNodeAttr(oldNode, newNode, ATTR_CLASS);
318 updateNodeAttr(oldNode, newNode, ATTR_UID);
307 updateNodeAttr(oldNode, newNode, ATTR_UID);
319
308
320 // Replace children
309 // Replace children
321 var children = oldNode.children();
310 var children = oldNode.children();
322 if (children.length == 0) {
311 if (children.length == 0) {
323 oldNode.replaceWith(newNode);
312 oldNode.replaceWith(newNode);
324 } else {
313 } else {
325 var newChildren = newNode.children();
314 var newChildren = newNode.children();
326 newChildren.each(function(i) {
315 newChildren.each(function(i) {
327 var newChild = newChildren.eq(i);
316 var newChild = newChildren.eq(i);
328 var newChildClass = newChild.attr(ATTR_CLASS);
317 var newChildClass = newChild.attr(ATTR_CLASS);
329
318
330 // Update only certain allowed blocks (e.g. not images)
319 // Update only certain allowed blocks (e.g. not images)
331 if (ALLOWED_FOR_PARTIAL_UPDATE.indexOf(newChildClass) > -1) {
320 if (ALLOWED_FOR_PARTIAL_UPDATE.indexOf(newChildClass) > -1) {
332 var oldChild = oldNode.children('.' + newChildClass);
321 var oldChild = oldNode.children('.' + newChildClass);
333
322
334 if (oldChild.length == 0) {
323 if (oldChild.length == 0) {
335 oldNode.append(newChild);
324 oldNode.append(newChild);
336 } else {
325 } else {
337 if (!equalNodes(oldChild, newChild)) {
326 if (!equalNodes(oldChild, newChild)) {
338 if (recursive) {
327 if (recursive) {
339 replacePartial(oldChild, newChild, false);
328 replacePartial(oldChild, newChild, false);
340 } else {
329 } else {
341 oldChild.replaceWith(newChild);
330 oldChild.replaceWith(newChild);
342 }
331 }
343 }
332 }
344 }
333 }
345 }
334 }
346 });
335 });
347 }
336 }
348 }
337 }
349 }
338 }
350
339
351 /**
340 /**
352 * Compare nodes by content
341 * Compare nodes by content
353 */
342 */
354 function equalNodes(node1, node2) {
343 function equalNodes(node1, node2) {
355 return node1[0].outerHTML == node2[0].outerHTML;
344 return node1[0].outerHTML == node2[0].outerHTML;
356 }
345 }
357
346
358 /**
347 /**
359 * Update attribute of a node if it has changed
348 * Update attribute of a node if it has changed
360 */
349 */
361 function updateNodeAttr(oldNode, newNode, attrName) {
350 function updateNodeAttr(oldNode, newNode, attrName) {
362 var oldAttr = oldNode.attr(attrName);
351 var oldAttr = oldNode.attr(attrName);
363 var newAttr = newNode.attr(attrName);
352 var newAttr = newNode.attr(attrName);
364 if (oldAttr != newAttr) {
353 if (oldAttr != newAttr) {
365 oldNode.attr(attrName, newAttr);
354 oldNode.attr(attrName, newAttr);
366 }
355 }
367 }
356 }
368
357
369 $(document).ready(function() {
358 $(document).ready(function() {
370 if (initAutoupdate()) {
359 if (initAutoupdate()) {
371 // Post form data over AJAX
360 // Post form data over AJAX
372 var threadId = $('div.thread').children('.post').first().attr('id');
361 var threadId = $('div.thread').children('.post').first().attr('id');
373
362
374 var form = $('#form');
363 var form = $('#form');
375
364
376 if (form.length > 0) {
365 if (form.length > 0) {
377 var options = {
366 var options = {
378 beforeSubmit: function(arr, form, options) {
367 beforeSubmit: function(arr, form, options) {
379 $('.post-form-w').block({ message: gettext('Sending message...') });
368 $('.post-form-w').block({ message: gettext('Sending message...') });
380 },
369 },
381 success: updateOnPost,
370 success: updateOnPost,
382 error: function(xhr, textStatus, errorString) {
371 error: function(xhr, textStatus, errorString) {
383 var errorText = gettext('Server error: ') + textStatus;
372 var errorText = gettext('Server error: ') + textStatus;
384 if (errorString) {
373 if (errorString) {
385 errorText += ' / ' + errorString;
374 errorText += ' / ' + errorString;
386 }
375 }
387 showAsErrors(form, errorText);
376 showAsErrors(form, errorText);
388 $('.post-form-w').unblock();
377 $('.post-form-w').unblock();
389 },
378 },
390 url: '/api/add_post/' + threadId + '/',
379 url: '/api/add_post/' + threadId + '/',
391 timeout: POST_AJAX_TIMEOUT
380 timeout: POST_AJAX_TIMEOUT
392 };
381 };
393
382
394 form.ajaxForm(options);
383 form.ajaxForm(options);
395
384
396 resetForm(form);
385 resetForm();
397 }
386 }
398 }
387 }
399 });
388 });
@@ -1,81 +1,81 b''
1 {% extends "boards/thread.html" %}
1 {% extends "boards/thread.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load static from staticfiles %}
4 {% load static from staticfiles %}
5 {% load board %}
5 {% load board %}
6 {% load tz %}
6 {% load tz %}
7
7
8 {% block thread_content %}
8 {% block thread_content %}
9 {% get_current_language as LANGUAGE_CODE %}
9 {% get_current_language as LANGUAGE_CODE %}
10 {% get_current_timezone as TIME_ZONE %}
10 {% get_current_timezone as TIME_ZONE %}
11
11
12 <div id="quote-button">{% trans 'Quote' %}</div>
12 <div id="quote-button">{% trans 'Quote' %}</div>
13
13
14 <div class="tag_info">
14 <div class="tag_info">
15 <h2>
15 <h2>
16 <form action="{% url 'thread' opening_post.id %}" method="post" class="post-button-form">
16 <form action="{% url 'thread' opening_post.id %}" method="post" class="post-button-form">
17 {% csrf_token %}
17 {% csrf_token %}
18 {% if is_favorite %}
18 {% if is_favorite %}
19 <button id="thread-fav-button" name="method" value="unsubscribe" class="fav"></button>
19 <button id="thread-fav-button" name="method" value="unsubscribe" class="fav"></button>
20 {% else %}
20 {% else %}
21 <button id="thread-fav-button" name="method" value="subscribe" class="not_fav"></button>
21 <button id="thread-fav-button" name="method" value="subscribe" class="not_fav"></button>
22 {% endif %}
22 {% endif %}
23 </form>
23 </form>
24 {{ opening_post.get_title_or_text }}
24 {{ opening_post.get_title_or_text }}
25 </h2>
25 </h2>
26 </div>
26 </div>
27
27
28 {% if bumpable and thread.has_post_limit %}
28 {% if bumpable and thread.has_post_limit %}
29 <div class="bar-bg">
29 <div class="bar-bg">
30 <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress">
30 <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress">
31 </div>
31 </div>
32 <div class="bar-text">
32 <div class="bar-text">
33 <span id="left_to_limit">{{ posts_left }}</span> {% trans 'posts to bumplimit' %}
33 <span id="left_to_limit">{{ posts_left }}</span> {% trans 'posts to bumplimit' %}
34 </div>
34 </div>
35 </div>
35 </div>
36 {% endif %}
36 {% endif %}
37
37
38 <div class="thread">
38 <div class="thread">
39 {% for post in thread.get_viewable_replies %}
39 {% for post in thread.get_viewable_replies %}
40 {% post_view post reply_link=True thread=thread %}
40 {% post_view post reply_link=True thread=thread %}
41 {% endfor %}
41 {% endfor %}
42 </div>
42 </div>
43
43
44 {% if not thread.is_archived %}
44 {% if not thread.is_archived %}
45 <div class="post-form-w">
45 <div class="post-form-w">
46 <script src="{% static 'js/panel.js' %}"></script>
46 <script src="{% static 'js/panel.js' %}"></script>
47 <div class="form-title">{% trans "Reply to thread" %} #{{ opening_post.id }}<span class="reply-to-message"> {% trans "to message " %} #<span id="reply-to-message-id"></span></span></div>
47 <div class="form-title">{% trans "Reply to thread" %} #{{ opening_post.id }}<span class="reply-to-message"> {% trans "to message " %} #<span id="reply-to-message-id"></span></span></div>
48 <div class="post-form" id="compact-form" data-hasher="{% static 'js/3party/sha256.js' %}"
48 <div class="post-form" id="compact-form" data-hasher="{% static 'js/3party/sha256.js' %}"
49 data-pow-script="{% static 'js/proof_of_work.js' %}">
49 data-pow-script="{% static 'js/proof_of_work.js' %}">
50 <div class="swappable-form-full">
50 <div class="swappable-form-full">
51 <form enctype="multipart/form-data" method="post" id="form">{% csrf_token %}
51 <form enctype="multipart/form-data" method="post" id="form">{% csrf_token %}
52 <div class="compact-form-text"></div>
52 <div class="compact-form-text"></div>
53 {{ form.as_div }}
53 {{ form.as_div }}
54 <div class="form-submit">
54 <div class="form-submit">
55 <input type="submit" value="{% trans "Post" %}"/>
55 <input type="submit" value="{% trans "Post" %}"/>
56 <button id="preview-button" type="button" onclick="return false;">{% trans 'Preview' %}</button>
56 <button id="preview-button" type="button" onclick="return false;">{% trans 'Preview' %}</button>
57 </div>
57 </div>
58 </form>
58 </form>
59 </div>
59 </div>
60 <div id="preview-text"></div>
60 <div id="preview-text"></div>
61 <div>
61 <div>
62 {% with size=max_file_size|filesizeformat %}
62 {% with size=max_file_size|filesizeformat %}
63 {% blocktrans %}Max file size is {{ size }}.{% endblocktrans %}
63 {% blocktrans %}Max file size is {{ size }}.{% endblocktrans %}
64 {% endwith %}
64 {% endwith %}
65 {% blocktrans %}Max file number is {{ max_files }}.{% endblocktrans %}
65 {% blocktrans %}Max file number is {{ max_files }}.{% endblocktrans %}
66 </div>
66 </div>
67 <div><a href="{% url "staticpage" name="help" %}">
67 <div><a href="{% url "staticpage" name="help" %}">
68 {% trans 'Text syntax' %}</a></div>
68 {% trans 'Text syntax' %}</a></div>
69 <div><a id="form-close-button" href="#" onClick="resetFormPosition(); return false;">{% trans 'Close form' %}</a></div>
69 <div><a href="#" onClick="resetForm(); return false;">{% trans 'Reset form' %}</a></div>
70 </div>
70 </div>
71 </div>
71 </div>
72
72
73 <script src="{% static 'js/form.js' %}"></script>
73 <script src="{% static 'js/form.js' %}"></script>
74 <script src="{% static 'js/jquery.form.min.js' %}"></script>
74 <script src="{% static 'js/jquery.form.min.js' %}"></script>
75 <script src="{% static 'js/3party/jquery.blockUI.js' %}"></script>
75 <script src="{% static 'js/3party/jquery.blockUI.js' %}"></script>
76 <script src="{% static 'js/thread.js' %}"></script>
76 <script src="{% static 'js/thread.js' %}"></script>
77 <script src="{% static 'js/thread_update.js' %}"></script>
77 <script src="{% static 'js/thread_update.js' %}"></script>
78 {% endif %}
78 {% endif %}
79
79
80 <script src="{% static 'js/3party/centrifuge.js' %}"></script>
80 <script src="{% static 'js/3party/centrifuge.js' %}"></script>
81 {% endblock %}
81 {% endblock %}
General Comments 0
You need to be logged in to leave comments. Login now