]> git.wh0rd.org - tt-rss.git/blob - viewfeed.js
implement CDM auto-catchup for articles
[tt-rss.git] / viewfeed.js
1 var active_post_id = false;
2 var _catchup_callback_func = false;
3 var last_article_view = false;
4 var active_real_feed_id = false;
5
6 var _tag_active_post_id = false;
7 var _tag_active_feed_id = false;
8
9 // FIXME: kludge, needs proper implementation
10 var _reload_feedlist_after_view = false;
11
12 var _cdm_wd_timeout = false;
13 var _cdm_wd_vishist = new Array();
14
15 function catchup_callback() {
16 if (xmlhttp_rpc.readyState == 4) {
17 try {
18 debug("catchup_callback");
19 if (_catchup_callback_func) {
20 setTimeout(_catchup_callback_func, 100);
21 }
22 all_counters_callback();
23 } catch (e) {
24 exception_error("catchup_callback", e);
25 }
26 }
27 }
28
29 function headlines_callback() {
30 if (xmlhttp.readyState == 4) {
31 debug("headlines_callback");
32 var f = document.getElementById("headlines-frame");
33 try {
34 f.scrollTop = 0;
35 } catch (e) { };
36 f.innerHTML = xmlhttp.responseText;
37 update_all_counters();
38 if (typeof correctPNG != 'undefined') {
39 correctPNG();
40 }
41
42 if (_cdm_wd_timeout) window.clearTimeout(_cdm_wd_timeout);
43
44 if (!document.getElementById("headlinesList")) {
45 debug("starting CDM watchdog");
46 _cdm_wd_timeout = window.setTimeout("cdmWatchdog()", 5000);
47 _cdm_wd_vishist = new Array();
48 }
49
50 notify("");
51 }
52 }
53
54 function article_callback() {
55 if (xmlhttp.readyState == 4) {
56 debug("article_callback");
57 var f = document.getElementById("content-frame");
58 try {
59 f.scrollTop = 0;
60 } catch (e) { };
61 f.innerHTML = xmlhttp.responseText;
62
63 var date = new Date();
64 last_article_view = date.getTime() / 1000;
65
66 if (typeof correctPNG != 'undefined') {
67 correctPNG();
68 }
69
70 if (_reload_feedlist_after_view) {
71 setTimeout('updateFeedList(false, false)', 50);
72 _reload_feedlist_after_view = false;
73 } else {
74 update_all_counters();
75 }
76 }
77 }
78
79 function view(id, feed_id, skip_history) {
80
81 try {
82 debug("loading article: " + id + "/" + feed_id);
83
84 active_real_feed_id = feed_id;
85
86 if (!skip_history) {
87 history_push("ARTICLE:" + id + ":" + feed_id);
88 }
89
90 enableHotkeys();
91
92 active_post_id = id;
93 //setActiveFeedId(feed_id);
94
95 var query = "backend.php?op=view&id=" + param_escape(id) +
96 "&feed=" + param_escape(feed_id);
97
98 var date = new Date();
99
100 if (!xmlhttp_ready(xmlhttp) && last_article_view < date.getTime() / 1000 - 15) {
101 debug("<b>xmlhttp seems to be stuck at view, aborting</b>");
102 xmlhttp.abort();
103 }
104
105 if (xmlhttp_ready(xmlhttp)) {
106
107 cleanSelected("headlinesList");
108
109 var crow = document.getElementById("RROW-" + active_post_id);
110 crow.className = crow.className.replace("Unread", "");
111
112 var upd_img_pic = document.getElementById("FUPDPIC-" + active_post_id);
113
114 if (upd_img_pic) {
115 upd_img_pic.src = "images/blank_icon.gif";
116 }
117
118 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
119 markHeadline(active_post_id);
120
121 xmlhttp.open("GET", query, true);
122 xmlhttp.onreadystatechange=article_callback;
123 xmlhttp.send(null);
124 } else {
125 debug("xmlhttp busy (@view)");
126 printLockingError();
127 }
128
129 } catch (e) {
130 exception_error("view", e);
131 }
132 }
133
134 function toggleMark(id) {
135
136 if (!xmlhttp_ready(xmlhttp_rpc)) {
137 printLockingError();
138 return;
139 }
140
141 var query = "backend.php?op=rpc&id=" + id + "&subop=mark";
142
143 var mark_img = document.getElementById("FMARKPIC-" + id);
144 var vfeedu = document.getElementById("FEEDU--1");
145 var crow = document.getElementById("RROW-" + id);
146
147 if (mark_img.alt != "Reset mark") {
148 mark_img.src = "images/mark_set.png";
149 mark_img.alt = "Reset mark";
150 query = query + "&mark=1";
151
152 if (vfeedu && crow.className.match("Unread")) {
153 vfeedu.innerHTML = (+vfeedu.innerHTML) + 1;
154 }
155
156 } else {
157 mark_img.src = "images/mark_unset.png";
158 mark_img.alt = "Set mark";
159 query = query + "&mark=0";
160
161 if (vfeedu && crow.className.match("Unread")) {
162 vfeedu.innerHTML = (+vfeedu.innerHTML) - 1;
163 }
164
165 }
166
167 var vfeedctr = document.getElementById("FEEDCTR--1");
168 var vfeedr = document.getElementById("FEEDR--1");
169
170 if (vfeedu && vfeedctr) {
171 if ((+vfeedu.innerHTML) > 0) {
172 if (crow.className.match("Unread") && !vfeedr.className.match("Unread")) {
173 vfeedr.className = vfeedr.className + "Unread";
174 vfeedctr.className = "odd";
175 }
176 } else {
177 vfeedctr.className = "invisible";
178 vfeedr.className = vfeedr.className.replace("Unread", "");
179 }
180 }
181
182 debug("toggle starred for aid " + id);
183
184 new Ajax.Request(query);
185
186 }
187
188 function moveToPost(mode) {
189
190 // check for combined mode
191 if (!document.getElementById("headlinesList"))
192 return;
193
194 var rows = getVisibleHeadlineIds();
195
196 var prev_id;
197 var next_id;
198
199 if (!document.getElementById('RROW-' + active_post_id)) {
200 active_post_id = false;
201 }
202
203 if (active_post_id == false) {
204 next_id = getFirstVisibleHeadlineId();
205 prev_id = getLastVisibleHeadlineId();
206 } else {
207 for (var i = 0; i < rows.length; i++) {
208 if (rows[i] == active_post_id) {
209 prev_id = rows[i-1];
210 next_id = rows[i+1];
211 }
212 }
213 }
214
215 if (mode == "next") {
216 if (next_id != undefined) {
217 view(next_id, getActiveFeedId());
218 }
219 }
220
221 if (mode == "prev") {
222 if ( prev_id != undefined) {
223 view(prev_id, getActiveFeedId());
224 }
225 }
226 }
227
228 function toggleUnread(id, cmode) {
229 try {
230 if (!xmlhttp_ready(xmlhttp_rpc)) {
231 printLockingError();
232 return;
233 }
234
235 var row = document.getElementById("RROW-" + id);
236 if (row) {
237 var nc = row.className;
238 nc = nc.replace("Unread", "");
239 nc = nc.replace("Selected", "");
240
241 if (row.className.match("Unread")) {
242 row.className = nc;
243 } else {
244 row.className = nc + "Unread";
245 }
246
247 if (!cmode) cmode = 2;
248
249 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
250 param_escape(id) + "&cmode=" + param_escape(cmode);
251
252 xmlhttp_rpc.open("GET", query, true);
253 xmlhttp_rpc.onreadystatechange=all_counters_callback;
254 xmlhttp_rpc.send(null);
255
256 }
257
258
259 } catch (e) {
260 exception_error("toggleUnread", e);
261 }
262 }
263
264 function selectionToggleUnread(cdm_mode, set_state, callback_func) {
265 try {
266 if (!xmlhttp_ready(xmlhttp_rpc)) {
267 printLockingError();
268 return;
269 }
270
271 var rows;
272
273 if (cdm_mode) {
274 rows = cdmGetSelectedArticles();
275 } else {
276 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
277 }
278
279 for (i = 0; i < rows.length; i++) {
280 var row = document.getElementById("RROW-" + rows[i]);
281 if (row) {
282 var nc = row.className;
283 nc = nc.replace("Unread", "");
284 nc = nc.replace("Selected", "");
285
286 if (row.className.match("Unread")) {
287 row.className = nc + "Selected";
288 } else {
289 row.className = nc + "UnreadSelected";
290 }
291 }
292 }
293
294 if (rows.length > 0) {
295
296 var cmode = "";
297
298 if (set_state == undefined) {
299 cmode = "2";
300 } else if (set_state == true) {
301 cmode = "1";
302 } else if (set_state == false) {
303 cmode = "0";
304 }
305
306 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
307 param_escape(rows.toString()) + "&cmode=" + cmode;
308
309 _catchup_callback_func = callback_func;
310
311 xmlhttp_rpc.open("GET", query, true);
312 xmlhttp_rpc.onreadystatechange=catchup_callback;
313 xmlhttp_rpc.send(null);
314
315 }
316
317 } catch (e) {
318 exception_error("selectionToggleUnread", e);
319 }
320 }
321
322 function selectionToggleMarked(cdm_mode) {
323 try {
324 if (!xmlhttp_ready(xmlhttp_rpc)) {
325 printLockingError();
326 return;
327 }
328
329 var rows;
330
331 if (cdm_mode) {
332 rows = cdmGetSelectedArticles();
333 } else {
334 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
335 }
336
337 for (i = 0; i < rows.length; i++) {
338 var row = document.getElementById("RROW-" + rows[i]);
339 var mark_img = document.getElementById("FMARKPIC-" + rows[i]);
340
341 if (row && mark_img) {
342
343 if (mark_img.alt == "Set mark") {
344 mark_img.src = "images/mark_set.png";
345 mark_img.alt = "Reset mark";
346 mark_img.setAttribute('onclick',
347 'javascript:toggleMark('+rows[i]+', false)');
348
349 } else {
350 mark_img.src = "images/mark_unset.png";
351 mark_img.alt = "Set mark";
352 mark_img.setAttribute('onclick',
353 'javascript:toggleMark('+rows[i]+', true)');
354 }
355 }
356 }
357
358 if (rows.length > 0) {
359
360 var query = "backend.php?op=rpc&subop=markSelected&ids=" +
361 param_escape(rows.toString()) + "&cmode=2";
362
363 xmlhttp_rpc.open("GET", query, true);
364 xmlhttp_rpc.onreadystatechange=all_counters_callback;
365 xmlhttp_rpc.send(null);
366
367 }
368
369 } catch (e) {
370 exception_error("selectionToggleMarked", e);
371 }
372 }
373
374 function cdmGetSelectedArticles() {
375 var sel_articles = new Array();
376 var container = document.getElementById("headlinesInnerContainer");
377
378 for (i = 0; i < container.childNodes.length; i++) {
379 var child = container.childNodes[i];
380
381 if (child.id.match("RROW-") && child.className.match("Selected")) {
382 var c_id = child.id.replace("RROW-", "");
383 sel_articles.push(c_id);
384 }
385 }
386
387 return sel_articles;
388 }
389
390 // mode = all,none,unread
391 function cdmSelectArticles(mode) {
392 var container = document.getElementById("headlinesInnerContainer");
393
394 for (i = 0; i < container.childNodes.length; i++) {
395 var child = container.childNodes[i];
396
397 if (child.id.match("RROW-")) {
398 var aid = child.id.replace("RROW-", "");
399
400 var cb = document.getElementById("RCHK-" + aid);
401
402 if (mode == "all") {
403 if (!child.className.match("Selected")) {
404 child.className = child.className + "Selected";
405 cb.checked = true;
406 }
407 } else if (mode == "unread") {
408 if (child.className.match("Unread") && !child.className.match("Selected")) {
409 child.className = child.className + "Selected";
410 cb.checked = true;
411 }
412 } else {
413 child.className = child.className.replace("Selected", "");
414 cb.checked = false;
415 }
416 }
417 }
418 }
419
420 function catchupPage() {
421
422 if (document.getElementById("headlinesList")) {
423 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, 'Unread', true);
424 selectionToggleUnread(false, false, 'viewCurrentFeed()');
425 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
426 } else {
427 cdmSelectArticles('all');
428 selectionToggleUnread(true, false, 'viewCurrentFeed()')
429 cdmSelectArticles('none');
430 }
431 }
432
433 function labelFromSearch(search, search_mode, match_on, feed_id, is_cat) {
434
435 if (!xmlhttp_ready(xmlhttp_rpc)) {
436 printLockingError();
437 }
438
439 var title = prompt("Please enter label title:", "");
440
441 if (title) {
442
443 var query = "backend.php?op=labelFromSearch&search=" + param_escape(search) +
444 "&smode=" + param_escape(search_mode) + "&match=" + param_escape(match_on) +
445 "&feed=" + param_escape(feed_id) + "&is_cat=" + param_escape(is_cat) +
446 "&title=" + param_escape(title);
447
448 debug("LFS: " + query);
449
450 xmlhttp_rpc.open("GET", query, true);
451 xmlhttp_rpc.onreadystatechange=dlg_frefresh_callback;
452 xmlhttp_rpc.send(null);
453 }
454
455 }
456
457 function editArticleTags(id, feed_id) {
458 _tag_active_post_id = id;
459 _tag_active_feed_id = feed_id;
460 displayDlg('editArticleTags', id);
461 }
462
463
464 function tag_saved_callback() {
465 if (xmlhttp_rpc.readyState == 4) {
466 try {
467 debug("in tag_saved_callback");
468
469 closeInfoBox();
470 notify("");
471
472 if (tagsAreDisplayed()) {
473 _reload_feedlist_after_view = true;
474 }
475
476 if (active_post_id == _tag_active_post_id) {
477 debug("reloading current article");
478 view(_tag_active_post_id, _tag_active_feed_id);
479 }
480
481 } catch (e) {
482 exception_error("catchup_callback", e);
483 }
484 }
485 }
486
487 function editTagsSave() {
488
489 if (!xmlhttp_ready(xmlhttp_rpc)) {
490 printLockingError();
491 }
492
493 notify("Saving article tags...");
494
495 var form = document.forms["tag_edit_form"];
496
497 var query = Form.serialize("tag_edit_form");
498
499 xmlhttp_rpc.open("GET", "backend.php?op=rpc&subop=setArticleTags&" + query, true);
500 xmlhttp_rpc.onreadystatechange=tag_saved_callback;
501 xmlhttp_rpc.send(null);
502
503 }
504
505 function editTagsInsert() {
506 try {
507
508 var form = document.forms["tag_edit_form"];
509
510 var found_tags = form.found_tags;
511 var tags_str = form.tags_str;
512
513 var tag = found_tags[found_tags.selectedIndex].value;
514
515 if (tags_str.value.length > 0 &&
516 tags_str.value.lastIndexOf(", ") != tags_str.value.length - 2) {
517
518 tags_str.value = tags_str.value + ", ";
519 }
520
521 tags_str.value = tags_str.value + tag + ", ";
522
523 found_tags.selectedIndex = 0;
524
525 } catch (e) {
526 exception_error(e, "editTagsInsert");
527 }
528 }
529
530 function cdmWatchdog() {
531
532 try {
533
534 var ctr = document.getElementById("headlinesInnerContainer");
535
536 if (!ctr.hasChildNodes()) return;
537
538 var ids = new Array();
539
540 var e = ctr.firstChild;
541
542 while (e) {
543 if (e.className && e.className == "cdmArticleUnread" && e.id &&
544 e.id.match("RROW-")) {
545
546 // article fits in viewport OR article is longer than viewport and
547 // its bottom is visible
548
549 if (ctr.scrollTop <= e.offsetTop && e.offsetTop + e.offsetHeight <=
550 ctr.scrollTop + ctr.offsetHeight) {
551
552 // debug(e.id + " is visible " + e.offsetTop + "." +
553 // (e.offsetTop + e.offsetHeight) + " vs " + ctr.scrollTop + "." +
554 // (ctr.scrollTop + ctr.offsetHeight));
555
556 ids.push(e.id.replace("RROW-", ""));
557
558 } else if (e.offsetHeight > ctr.offsetHeight &&
559 e.offsetTop + e.offsetHeight >= ctr.scrollTop &&
560 e.offsetTop + e.offsetHeight <= ctr.scrollTop + ctr.offsetHeight) {
561
562 ids.push(e.id.replace("RROW-", ""));
563
564 }
565
566 }
567
568 e = e.nextSibling;
569 }
570
571 debug("cdmWatchdog, ids= " + ids.toString());
572
573 if (ids.length > 0 && xmlhttp_ready(xmlhttp_rpc)) {
574
575 for (var i = 0; i < ids.length; i++) {
576 var e = document.getElementById("RROW-" + ids[i]);
577 if (e) {
578 e.className = e.className.replace("Unread", "");
579 }
580 }
581
582 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
583 param_escape(ids.toString()) + "&cmode=0";
584
585 /* xmlhttp_rpc.open("GET", query, true);
586 xmlhttp_rpc.onreadystatechange=all_counters_callback;
587 xmlhttp_rpc.send(null); */
588
589 }
590
591 _cdm_wd_timeout = window.setTimeout("cdmWatchdog()", 5000);
592
593 } catch (e) {
594 exception_error(e, "cdmWatchdog");
595 }
596
597 }