]> git.wh0rd.org - tt-rss.git/blob - viewfeed.js
disable infinite scrolling when Limit == 0 (closes #143)
[tt-rss.git] / viewfeed.js
1 var active_post_id = false;
2 var last_article_view = false;
3 var active_real_feed_id = false;
4
5 var _tag_active_post_id = false;
6 var _tag_active_feed_id = false;
7 var _tag_active_cdm = false;
8
9 // FIXME: kludge, to restore scrollTop after tag editor terminates
10 var _tag_cdm_scroll = false;
11
12 // FIXME: kludges, needs proper implementation
13 var _reload_feedlist_after_view = false;
14
15 var _cdm_wd_timeout = false;
16 var _cdm_wd_vishist = new Array();
17
18 var article_cache = new Array();
19
20 function catchup_callback() {
21 if (xmlhttp_rpc.readyState == 4) {
22 try {
23 debug("catchup_callback");
24 notify("");
25 all_counters_callback2(xmlhttp_rpc);
26 if (_catchup_callback_func) {
27 setTimeout(_catchup_callback_func, 10);
28 }
29 } catch (e) {
30 exception_error("catchup_callback", e);
31 }
32 }
33 }
34
35 function catchup_callback2(transport, callback) {
36 try {
37 debug("catchup_callback2 " + transport + ", " + callback);
38 notify("");
39 all_counters_callback2(transport);
40 if (callback) {
41 setTimeout(callback, 10);
42 }
43 } catch (e) {
44 exception_error("catchup_callback2", e);
45 }
46 }
47
48 function headlines_callback2(transport, active_feed_id, is_cat, feed_cur_page) {
49 try {
50
51 debug("headlines_callback2 [page=" + feed_cur_page + "]");
52
53 var feeds = document.getElementById("feedList").getElementsByTagName("LI");
54
55 for (var i = 0; i < feeds.length; i++) {
56 if (feeds[i].id && feeds[i].id.match("FEEDR-")) {
57 feeds[i].className = feeds[i].className.replace("Selected", "");
58 }
59 }
60
61 setActiveFeedId(active_feed_id);
62
63 if (is_cat != undefined) {
64 active_feed_is_cat = is_cat;
65 }
66
67 if (!is_cat) {
68 var feedr = document.getElementById("FEEDR-" + active_feed_id);
69 if (feedr && !feedr.className.match("Selected")) {
70 feedr.className = feedr.className + "Selected";
71 }
72 }
73
74 var f = document.getElementById("headlines-frame");
75 try {
76 if (feed_cur_page == 0) {
77 debug("resetting headlines scrollTop");
78 f.scrollTop = 0;
79 }
80 } catch (e) { };
81
82 if (transport.responseXML) {
83 var headlines = transport.responseXML.getElementsByTagName("headlines")[0];
84 var headlines_count_obj = transport.responseXML.getElementsByTagName("headlines-count")[0];
85
86 var headlines_count = headlines_count_obj.getAttribute("value");
87
88 if (headlines_count == 0) _infscroll_disable = 1;
89
90 var counters = transport.responseXML.getElementsByTagName("counters")[0];
91 var articles = transport.responseXML.getElementsByTagName("article");
92 var runtime_info = transport.responseXML.getElementsByTagName("runtime-info");
93
94 if (feed_cur_page == 0) {
95 if (headlines) {
96 f.innerHTML = headlines.firstChild.nodeValue;
97 } else {
98 debug("headlines_callback: returned no data");
99 f.innerHTML = "<div class='whiteBox'>" + __('Could not update headlines (missing XML data)') + "</div>";
100
101 }
102 } else {
103 if (headlines) {
104 if (headlines_count > 0) {
105 debug("adding some more headlines...");
106
107 var c = document.getElementById("headlinesList");
108
109 if (!c) {
110 c = document.getElementById("headlinesInnerContainer");
111 }
112
113 c.innerHTML = c.innerHTML + headlines.firstChild.nodeValue;
114 } else {
115 debug("no new headlines received");
116 }
117 } else {
118 debug("headlines_callback: returned no data");
119 notify_error("Error while trying to load more headlines");
120 }
121
122 }
123
124 if (articles) {
125 for (var i = 0; i < articles.length; i++) {
126 var a_id = articles[i].getAttribute("id");
127 debug("found id: " + a_id);
128 cache_inject(a_id, articles[i].firstChild.nodeValue);
129 }
130 } else {
131 debug("no cached articles received");
132 }
133
134 if (counters) {
135 debug("parsing piggybacked counters: " + counters);
136 parse_counters(counters, false);
137 } else {
138 debug("counters container not found in reply");
139 }
140
141 if (runtime_info) {
142 debug("parsing runtime info: " + runtime_info[0]);
143 parse_runtime_info(runtime_info[0]);
144 } else {
145 debug("counters container not found in reply");
146 }
147
148 } else {
149 debug("headlines_callback: returned no XML object");
150 f.innerHTML = "<div class='whiteBox'>" + __('Could not update headlines (missing XML object)') + "</div>";
151 }
152
153 if (typeof correctPNG != 'undefined') {
154 correctPNG();
155 }
156
157 if (_cdm_wd_timeout) window.clearTimeout(_cdm_wd_timeout);
158
159 if (!document.getElementById("headlinesList") &&
160 getInitParam("cdm_auto_catchup") == 1) {
161 debug("starting CDM watchdog");
162 _cdm_wd_timeout = window.setTimeout("cdmWatchdog()", 5000);
163 _cdm_wd_vishist = new Array();
164 } else {
165 debug("not in CDM mode or watchdog disabled");
166 }
167
168 if (_tag_cdm_scroll) {
169 try {
170 document.getElementById("headlinesInnerContainer").scrollTop = _tag_cdm_scroll;
171 _tag_cdm_scroll = false;
172 debug("resetting headlinesInner scrollTop");
173
174 } catch (e) { }
175 }
176
177 _feed_cur_page = feed_cur_page;
178 _infscroll_request_sent = 0;
179
180 notify("");
181 } catch (e) {
182 exception_error("headlines_callback2", e);
183 }
184 }
185
186 function render_article(article) {
187 try {
188 var f = document.getElementById("content-frame");
189 try {
190 f.scrollTop = 0;
191 } catch (e) { };
192
193 f.innerHTML = article;
194
195 } catch (e) {
196 exception_error("render_article", e);
197 }
198 }
199
200 function showArticleInHeadlines(id) {
201
202 try {
203
204 cleanSelected("headlinesList");
205
206 var crow = document.getElementById("RROW-" + id);
207 var article_is_unread = crow.className.match("Unread");
208
209 crow.className = crow.className.replace("Unread", "");
210
211 var upd_img_pic = document.getElementById("FUPDPIC-" + id);
212
213 if (upd_img_pic) {
214 upd_img_pic.src = "images/blank_icon.gif";
215 }
216
217 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
218 markHeadline(id);
219
220 } catch (e) {
221 exception_error("showArticleInHeadlines", e);
222 }
223 }
224
225 function article_callback2(transport, id, feed_id) {
226 try {
227 debug("article_callback2 " + id);
228
229 if (transport.responseXML) {
230
231 active_real_feed_id = feed_id;
232 active_post_id = id;
233
234 showArticleInHeadlines(id);
235
236 var reply = transport.responseXML.firstChild.firstChild;
237
238 var articles = transport.responseXML.getElementsByTagName("article");
239
240 for (var i = 0; i < articles.length; i++) {
241 var a_id = articles[i].getAttribute("id");
242
243 debug("found id: " + a_id);
244
245 if (a_id == active_post_id) {
246 debug("active article, rendering...");
247 render_article(articles[i].firstChild.nodeValue);
248 }
249
250 cache_inject(a_id, articles[i].firstChild.nodeValue);
251 }
252
253 } else {
254 debug("article_callback: returned no XML object");
255 var f = document.getElementById("content-frame");
256 f.innerHTML = "<div class='whiteBox'>" + __('Could not display article (missing XML object)') + "</div>";
257 }
258
259 var date = new Date();
260 last_article_view = date.getTime() / 1000;
261
262 if (typeof correctPNG != 'undefined') {
263 correctPNG();
264 }
265
266 if (_reload_feedlist_after_view) {
267 setTimeout('updateFeedList(false, false)', 50);
268 _reload_feedlist_after_view = false;
269 } else {
270 var counters = transport.responseXML.getElementsByTagName("counters")[0];
271
272 if (counters) {
273 debug("parsing piggybacked counters: " + counters);
274 parse_counters(counters, false);
275 } else {
276 debug("counters container not found in reply");
277 }
278 }
279
280 notify("");
281 } catch (e) {
282 exception_error("article_callback2", e);
283 }
284 }
285
286 function view(id, feed_id, skip_history) {
287
288 try {
289 debug("loading article: " + id + "/" + feed_id);
290
291 var cached_article = cache_find(id);
292
293 debug("cache check result: " + (cached_article != false));
294
295 enableHotkeys();
296
297 //setActiveFeedId(feed_id);
298
299 var query = "backend.php?op=view&id=" + param_escape(id) +
300 "&feed=" + param_escape(feed_id);
301
302 var date = new Date();
303
304 var neighbor_ids = getRelativePostIds(active_post_id);
305
306 /* only request uncached articles */
307
308 var cids_to_request = Array();
309
310 for (var i = 0; i < neighbor_ids.length; i++) {
311 if (!cache_check(neighbor_ids[i])) {
312 cids_to_request.push(neighbor_ids[i]);
313 }
314 }
315
316 debug("additional ids: " + cids_to_request.toString());
317
318 /* additional info for piggyback counters */
319
320 if (tagsAreDisplayed()) {
321 query = query + "&omode=lt";
322 } else {
323 query = query + "&omode=flc";
324 }
325
326 var date = new Date();
327 var timestamp = Math.round(date.getTime() / 1000);
328 query = query + "&ts=" + timestamp;
329
330 query = query + "&cids=" + cids_to_request.toString();
331
332 var crow = document.getElementById("RROW-" + id);
333 var article_is_unread = crow.className.match("Unread");
334
335 showArticleInHeadlines(id);
336
337 if (!cached_article) {
338
339 notify_progress("Loading, please wait...");
340
341 } else if (cached_article && article_is_unread) {
342
343 query = query + "&mode=prefetch";
344
345 render_article(cached_article);
346
347 } else if (cached_article) {
348
349 query = query + "&mode=prefetch_old";
350 render_article(cached_article);
351 }
352
353 cache_expire();
354
355 new Ajax.Request(query, {
356 onComplete: function(transport) {
357 article_callback2(transport, id, feed_id);
358 } });
359
360 } catch (e) {
361 exception_error("view", e);
362 }
363 }
364
365 function tMark(id) {
366 return toggleMark(id);
367 }
368
369 function tPub(id) {
370 return togglePub(id);
371 }
372
373 function tMark_afh_off(effect) {
374 try {
375 var elem = effect.effects[0].element;
376
377 debug("tMark_afh_off : " + elem.id);
378
379 if (elem) {
380 elem.src = elem.src.replace("mark_set", "mark_unset");
381 elem.alt = __("Star article");
382 Element.show(elem);
383 }
384
385 } catch (e) {
386 exception_error("tMark_afh_off", e);
387 }
388 }
389
390 function tPub_afh_off(effect) {
391 try {
392 var elem = effect.effects[0].element;
393
394 debug("tPub_afh_off : " + elem.id);
395
396 if (elem) {
397 elem.src = elem.src.replace("pub_set", "pub_unset");
398 elem.alt = __("Publish article");
399 Element.show(elem);
400 }
401
402 } catch (e) {
403 exception_error("tPub_afh_off", e);
404 }
405 }
406
407 function toggleMark(id, client_only, no_effects) {
408
409 try {
410
411 var query = "backend.php?op=rpc&id=" + id + "&subop=mark";
412
413 query = query + "&afid=" + getActiveFeedId();
414
415 if (tagsAreDisplayed()) {
416 query = query + "&omode=tl";
417 } else {
418 query = query + "&omode=flc";
419 }
420
421 var mark_img = document.getElementById("FMPIC-" + id);
422 var vfeedu = document.getElementById("FEEDU--1");
423 var crow = document.getElementById("RROW-" + id);
424
425 if (mark_img.src.match("mark_unset")) {
426 mark_img.src = mark_img.src.replace("mark_unset", "mark_set");
427 mark_img.alt = __("Unstar article");
428 query = query + "&mark=1";
429
430 /* if (vfeedu && crow.className.match("Unread")) {
431 vfeedu.innerHTML = (+vfeedu.innerHTML) + 1;
432 } */
433
434 } else {
435 //mark_img.src = "images/mark_unset.png";
436 mark_img.alt = __("Please wait...");
437 query = query + "&mark=0";
438
439 /* if (vfeedu && crow.className.match("Unread")) {
440 vfeedu.innerHTML = (+vfeedu.innerHTML) - 1;
441 } */
442
443 if (document.getElementById("headlinesList") && !no_effects) {
444 Effect.Puff(mark_img, {duration : 0.25, afterFinish: tMark_afh_off});
445 } else {
446 mark_img.src = mark_img.src.replace("mark_set", "mark_unset");
447 mark_img.alt = __("Star article");
448 }
449 }
450
451 /* var vfeedctr = document.getElementById("FEEDCTR--1");
452 var vfeedr = document.getElementById("FEEDR--1");
453
454 if (vfeedu && vfeedctr) {
455 if ((+vfeedu.innerHTML) > 0) {
456 if (crow.className.match("Unread") && !vfeedr.className.match("Unread")) {
457 vfeedr.className = vfeedr.className + "Unread";
458 vfeedctr.className = "odd";
459 }
460 } else {
461 vfeedctr.className = "invisible";
462 vfeedr.className = vfeedr.className.replace("Unread", "");
463 }
464 }
465
466 debug("toggle starred for aid " + id);
467
468 //new Ajax.Request(query); */
469
470 if (!client_only) {
471 debug(query);
472
473 new Ajax.Request(query, {
474 onComplete: function(transport) {
475 all_counters_callback2(transport);
476 } });
477
478 }
479
480 } catch (e) {
481 exception_error("toggleMark", e);
482 }
483 }
484
485 function togglePub(id, client_only, no_effects) {
486
487 try {
488
489 var query = "backend.php?op=rpc&id=" + id + "&subop=publ";
490
491 query = query + "&afid=" + getActiveFeedId();
492
493 if (tagsAreDisplayed()) {
494 query = query + "&omode=tl";
495 } else {
496 query = query + "&omode=flc";
497 }
498
499 var mark_img = document.getElementById("FPPIC-" + id);
500 var vfeedu = document.getElementById("FEEDU--2");
501 var crow = document.getElementById("RROW-" + id);
502
503 if (mark_img.src.match("pub_unset")) {
504 mark_img.src = mark_img.src.replace("pub_unset", "pub_set");
505 mark_img.alt = __("Unpublish article");
506 query = query + "&pub=1";
507
508 /* if (vfeedu && crow.className.match("Unread")) {
509 vfeedu.innerHTML = (+vfeedu.innerHTML) + 1;
510 } */
511
512 } else {
513 //mark_img.src = "images/pub_unset.png";
514 mark_img.alt = __("Please wait...");
515 query = query + "&pub=0";
516
517 /* if (vfeedu && crow.className.match("Unread")) {
518 vfeedu.innerHTML = (+vfeedu.innerHTML) - 1;
519 } */
520
521 if (document.getElementById("headlinesList") && !no_effects) {
522 Effect.Puff(mark_img, {duration : 0.25, afterFinish: tPub_afh_off});
523 } else {
524 mark_img.src = mark_img.src.replace("pub_set", "pub_unset");
525 mark_img.alt = __("Publish article");
526 }
527 }
528
529 /* var vfeedctr = document.getElementById("FEEDCTR--2");
530 var vfeedr = document.getElementById("FEEDR--2");
531
532 if (vfeedu && vfeedctr) {
533 if ((+vfeedu.innerHTML) > 0) {
534 if (crow.className.match("Unread") && !vfeedr.className.match("Unread")) {
535 vfeedr.className = vfeedr.className + "Unread";
536 vfeedctr.className = "odd";
537 }
538 } else {
539 vfeedctr.className = "invisible";
540 vfeedr.className = vfeedr.className.replace("Unread", "");
541 }
542 }
543
544 debug("toggle published for aid " + id);
545
546 new Ajax.Request(query); */
547
548 if (!client_only) {
549 new Ajax.Request(query, {
550 onComplete: function(transport) {
551 all_counters_callback2(transport);
552 } });
553 }
554
555 } catch (e) {
556
557 exception_error("togglePub", e);
558 }
559 }
560
561 function correctHeadlinesOffset(id) {
562
563 try {
564
565 var hlist = document.getElementById("headlinesList");
566 var container = document.getElementById("headlinesInnerContainer");
567 var row = document.getElementById("RROW-" + id);
568
569 var viewport = container.offsetHeight;
570
571 var rel_offset_top = row.offsetTop - container.scrollTop;
572 var rel_offset_bottom = row.offsetTop + row.offsetHeight - container.scrollTop;
573
574 debug("Rtop: " + rel_offset_top + " Rbtm: " + rel_offset_bottom);
575 debug("Vport: " + viewport);
576
577 if (rel_offset_top <= 0 || rel_offset_top > viewport) {
578 container.scrollTop = row.offsetTop;
579 } else if (rel_offset_bottom > viewport) {
580
581 /* doesn't properly work with Opera in some cases because
582 Opera fucks up element scrolling */
583
584 container.scrollTop = row.offsetTop + row.offsetHeight - viewport;
585 }
586
587 } catch (e) {
588 exception_error("correctHeadlinesOffset", e);
589 }
590
591 }
592
593 function moveToPost(mode) {
594
595 // check for combined mode
596 if (!document.getElementById("headlinesList"))
597 return;
598
599 var rows = getVisibleHeadlineIds();
600
601 var prev_id = false;
602 var next_id = false;
603
604 if (!document.getElementById('RROW-' + active_post_id)) {
605 active_post_id = false;
606 }
607
608 if (active_post_id == false) {
609 next_id = getFirstVisibleHeadlineId();
610 prev_id = getLastVisibleHeadlineId();
611 } else {
612 for (var i = 0; i < rows.length; i++) {
613 if (rows[i] == active_post_id) {
614 prev_id = rows[i-1];
615 next_id = rows[i+1];
616 }
617 }
618 }
619
620 if (mode == "next") {
621 if (next_id) {
622 correctHeadlinesOffset(next_id);
623 view(next_id, getActiveFeedId());
624 }
625 }
626
627 if (mode == "prev") {
628 if (prev_id) {
629 correctHeadlinesOffset(prev_id);
630 view(prev_id, getActiveFeedId());
631 }
632 }
633 }
634
635 function toggleUnread(id, cmode) {
636 try {
637
638 var row = document.getElementById("RROW-" + id);
639 if (row) {
640 var nc = row.className;
641 nc = nc.replace("Unread", "");
642 nc = nc.replace("Selected", "");
643
644 if (row.className.match("Unread")) {
645 row.className = nc;
646 } else {
647 row.className = nc + "Unread";
648 }
649
650 if (!cmode) cmode = 2;
651
652 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
653 param_escape(id) + "&cmode=" + param_escape(cmode);
654
655 // notify_progress("Loading, please wait...");
656
657 new Ajax.Request(query, {
658 onComplete: function(transport) {
659 all_counters_callback2(transport);
660 } });
661
662 }
663
664
665 } catch (e) {
666 exception_error("toggleUnread", e);
667 }
668 }
669
670 function selectionToggleUnread(cdm_mode, set_state, callback_func, no_error) {
671 try {
672 var rows;
673
674 if (cdm_mode) {
675 rows = cdmGetSelectedArticles();
676 } else {
677 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
678 }
679
680 if (rows.length == 0 && !no_error) {
681 alert(__("No articles are selected."));
682 return;
683 }
684
685 for (i = 0; i < rows.length; i++) {
686 var row = document.getElementById("RROW-" + rows[i]);
687 if (row) {
688 var nc = row.className;
689 nc = nc.replace("Unread", "");
690 nc = nc.replace("Selected", "");
691
692 if (set_state == undefined) {
693 if (row.className.match("Unread")) {
694 row.className = nc + "Selected";
695 } else {
696 row.className = nc + "UnreadSelected";
697 }
698 }
699
700 if (set_state == false) {
701 row.className = nc + "Selected";
702 }
703
704 if (set_state == true) {
705 row.className = nc + "UnreadSelected";
706 }
707 }
708 }
709
710 if (rows.length > 0) {
711
712 var cmode = "";
713
714 if (set_state == undefined) {
715 cmode = "2";
716 } else if (set_state == true) {
717 cmode = "1";
718 } else if (set_state == false) {
719 cmode = "0";
720 }
721
722 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
723 param_escape(rows.toString()) + "&cmode=" + cmode;
724
725 notify_progress("Loading, please wait...");
726
727 new Ajax.Request(query, {
728 onComplete: function(transport) {
729 catchup_callback2(transport, callback_func);
730 } });
731
732 }
733
734 } catch (e) {
735 exception_error("selectionToggleUnread", e);
736 }
737 }
738
739 function selectionToggleMarked(cdm_mode) {
740 try {
741
742 var rows;
743
744 if (cdm_mode) {
745 rows = cdmGetSelectedArticles();
746 } else {
747 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
748 }
749
750 if (rows.length == 0) {
751 alert(__("No articles are selected."));
752 return;
753 }
754
755 for (i = 0; i < rows.length; i++) {
756 toggleMark(rows[i], true, true);
757 }
758
759 if (rows.length > 0) {
760
761 var query = "backend.php?op=rpc&subop=markSelected&ids=" +
762 param_escape(rows.toString()) + "&cmode=2";
763
764 query = query + "&afid=" + getActiveFeedId();
765
766 /* if (tagsAreDisplayed()) {
767 query = query + "&omode=tl";
768 } else {
769 query = query + "&omode=flc";
770 } */
771
772 query = query + "&omode=lc";
773
774 new Ajax.Request(query, {
775 onComplete: function(transport) {
776 all_counters_callback2(transport);
777 } });
778
779 }
780
781 } catch (e) {
782 exception_error("selectionToggleMarked", e);
783 }
784 }
785
786 function selectionTogglePublished(cdm_mode) {
787 try {
788
789 var rows;
790
791 if (cdm_mode) {
792 rows = cdmGetSelectedArticles();
793 } else {
794 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
795 }
796
797 if (rows.length == 0) {
798 alert(__("No articles are selected."));
799 return;
800 }
801
802 for (i = 0; i < rows.length; i++) {
803 togglePub(rows[i], true, true);
804 }
805
806 if (rows.length > 0) {
807
808 var query = "backend.php?op=rpc&subop=publishSelected&ids=" +
809 param_escape(rows.toString()) + "&cmode=2";
810
811 query = query + "&afid=" + getActiveFeedId();
812
813 /* if (tagsAreDisplayed()) {
814 query = query + "&omode=tl";
815 } else {
816 query = query + "&omode=flc";
817 } */
818
819 query = query + "&omode=lc";
820
821 new Ajax.Request(query, {
822 onComplete: function(transport) {
823 all_counters_callback2(transport);
824 } });
825
826 }
827
828 } catch (e) {
829 exception_error("selectionToggleMarked", e);
830 }
831 }
832
833 function cdmGetSelectedArticles() {
834 var sel_articles = new Array();
835 var container = document.getElementById("headlinesInnerContainer");
836
837 for (i = 0; i < container.childNodes.length; i++) {
838 var child = container.childNodes[i];
839
840 if (child.id.match("RROW-") && child.className.match("Selected")) {
841 var c_id = child.id.replace("RROW-", "");
842 sel_articles.push(c_id);
843 }
844 }
845
846 return sel_articles;
847 }
848
849 function cdmGetVisibleArticles() {
850 var sel_articles = new Array();
851 var container = document.getElementById("headlinesInnerContainer");
852
853 for (i = 0; i < container.childNodes.length; i++) {
854 var child = container.childNodes[i];
855
856 if (child.id.match("RROW-")) {
857 var c_id = child.id.replace("RROW-", "");
858 sel_articles.push(c_id);
859 }
860 }
861
862 return sel_articles;
863 }
864
865 function cdmGetUnreadArticles() {
866 var sel_articles = new Array();
867 var container = document.getElementById("headlinesInnerContainer");
868
869 for (i = 0; i < container.childNodes.length; i++) {
870 var child = container.childNodes[i];
871
872 if (child.id.match("RROW-") && child.className.match("Unread")) {
873 var c_id = child.id.replace("RROW-", "");
874 sel_articles.push(c_id);
875 }
876 }
877
878 return sel_articles;
879 }
880
881
882 // mode = all,none,unread
883 function cdmSelectArticles(mode) {
884 var container = document.getElementById("headlinesInnerContainer");
885
886 for (i = 0; i < container.childNodes.length; i++) {
887 var child = container.childNodes[i];
888
889 if (child.id.match("RROW-")) {
890 var aid = child.id.replace("RROW-", "");
891
892 var cb = document.getElementById("RCHK-" + aid);
893
894 if (mode == "all") {
895 if (!child.className.match("Selected")) {
896 child.className = child.className + "Selected";
897 cb.checked = true;
898 }
899 } else if (mode == "unread") {
900 if (child.className.match("Unread") && !child.className.match("Selected")) {
901 child.className = child.className + "Selected";
902 cb.checked = true;
903 }
904 } else {
905 child.className = child.className.replace("Selected", "");
906 cb.checked = false;
907 }
908 }
909 }
910 }
911
912 function catchupPage() {
913
914 var fn = getFeedName(getActiveFeedId(), active_feed_is_cat);
915
916 var str = __("Mark all visible articles in %s as read?");
917
918 str = str.replace("%s", fn);
919
920 if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
921 return;
922 }
923
924 if (document.getElementById("headlinesList")) {
925 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, 'Unread', true);
926 selectionToggleUnread(false, false, 'viewCurrentFeed()', true);
927 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
928 } else {
929 cdmSelectArticles('all');
930 selectionToggleUnread(true, false, 'viewCurrentFeed()', true)
931 cdmSelectArticles('none');
932 }
933 }
934
935 function catchupSelection() {
936
937 try {
938
939 var rows;
940
941 if (document.getElementById("headlinesList")) {
942 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
943 } else {
944 rows = cdmGetSelectedArticles();
945 }
946
947 if (rows.length == 0) {
948 alert(__("No articles are selected."));
949 return;
950 }
951
952
953 var fn = getFeedName(getActiveFeedId(), active_feed_is_cat);
954
955 var str = __("Mark %d selected articles in %s as read?");
956
957 str = str.replace("%d", rows.length);
958 str = str.replace("%s", fn);
959
960 if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
961 return;
962 }
963
964 if (document.getElementById("headlinesList")) {
965 selectionToggleUnread(false, false, 'viewCurrentFeed()', true);
966 // selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
967 } else {
968 selectionToggleUnread(true, false, 'viewCurrentFeed()', true)
969 // cdmSelectArticles('none');
970 }
971
972 } catch (e) {
973 exception_error("catchupSelection", e);
974 }
975 }
976
977
978 function labelFromSearch(search, search_mode, match_on, feed_id, is_cat) {
979
980 if (!xmlhttp_ready(xmlhttp_rpc)) {
981 printLockingError();
982 }
983
984 var title = prompt(__("Please enter label title:"), "");
985
986 if (title) {
987
988 var query = "backend.php?op=labelFromSearch&search=" + param_escape(search) +
989 "&smode=" + param_escape(search_mode) + "&match=" + param_escape(match_on) +
990 "&feed=" + param_escape(feed_id) + "&is_cat=" + param_escape(is_cat) +
991 "&title=" + param_escape(title);
992
993 debug("LFS: " + query);
994
995 new Ajax.Request(query, {
996 onComplete: function(transport) {
997 dlg_frefresh_callback(transport);
998 } });
999 }
1000 }
1001
1002 function editArticleTags(id, feed_id, cdm_enabled) {
1003 _tag_active_post_id = id;
1004 _tag_active_feed_id = feed_id;
1005 _tag_active_cdm = cdm_enabled;
1006
1007 cache_invalidate(id);
1008
1009 try {
1010 _tag_cdm_scroll = document.getElementById("headlinesInnerContainer").scrollTop;
1011 } catch (e) { }
1012 displayDlg('editArticleTags', id);
1013 }
1014
1015
1016 function tag_saved_callback(transport) {
1017 try {
1018 debug("in tag_saved_callback");
1019
1020 closeInfoBox();
1021 notify("");
1022
1023 if (tagsAreDisplayed()) {
1024 _reload_feedlist_after_view = true;
1025 }
1026
1027 if (!_tag_active_cdm) {
1028 if (active_post_id == _tag_active_post_id) {
1029 debug("reloading current article");
1030 view(_tag_active_post_id, _tag_active_feed_id);
1031 }
1032 } else {
1033 debug("reloading current feed");
1034 viewCurrentFeed();
1035 }
1036
1037 } catch (e) {
1038 exception_error("catchup_callback", e);
1039 }
1040 }
1041
1042 function editTagsSave() {
1043
1044 notify_progress("Saving article tags...");
1045
1046 var form = document.forms["tag_edit_form"];
1047
1048 var query = Form.serialize("tag_edit_form");
1049
1050 query = "backend.php?op=rpc&subop=setArticleTags&" + query;
1051
1052 debug(query);
1053
1054 new Ajax.Request(query, {
1055 onComplete: function(transport) {
1056 tag_saved_callback(transport);
1057 } });
1058
1059 }
1060
1061 function editTagsInsert() {
1062 try {
1063
1064 var form = document.forms["tag_edit_form"];
1065
1066 var found_tags = form.found_tags;
1067 var tags_str = form.tags_str;
1068
1069 var tag = found_tags[found_tags.selectedIndex].value;
1070
1071 if (tags_str.value.length > 0 &&
1072 tags_str.value.lastIndexOf(", ") != tags_str.value.length - 2) {
1073
1074 tags_str.value = tags_str.value + ", ";
1075 }
1076
1077 tags_str.value = tags_str.value + tag + ", ";
1078
1079 found_tags.selectedIndex = 0;
1080
1081 } catch (e) {
1082 exception_error(e, "editTagsInsert");
1083 }
1084 }
1085
1086 function cdmWatchdog() {
1087
1088 try {
1089
1090 var ctr = document.getElementById("headlinesInnerContainer");
1091
1092 if (!ctr) return;
1093
1094 var ids = new Array();
1095
1096 var e = ctr.firstChild;
1097
1098 while (e) {
1099 if (e.className && e.className == "cdmArticleUnread" && e.id &&
1100 e.id.match("RROW-")) {
1101
1102 // article fits in viewport OR article is longer than viewport and
1103 // its bottom is visible
1104
1105 if (ctr.scrollTop <= e.offsetTop && e.offsetTop + e.offsetHeight <=
1106 ctr.scrollTop + ctr.offsetHeight) {
1107
1108 // debug(e.id + " is visible " + e.offsetTop + "." +
1109 // (e.offsetTop + e.offsetHeight) + " vs " + ctr.scrollTop + "." +
1110 // (ctr.scrollTop + ctr.offsetHeight));
1111
1112 ids.push(e.id.replace("RROW-", ""));
1113
1114 } else if (e.offsetHeight > ctr.offsetHeight &&
1115 e.offsetTop + e.offsetHeight >= ctr.scrollTop &&
1116 e.offsetTop + e.offsetHeight <= ctr.scrollTop + ctr.offsetHeight) {
1117
1118 ids.push(e.id.replace("RROW-", ""));
1119
1120 }
1121
1122 // method 2: article bottom is visible and is in upper 1/2 of the viewport
1123
1124 /* if (e.offsetTop + e.offsetHeight >= ctr.scrollTop &&
1125 e.offsetTop + e.offsetHeight <= ctr.scrollTop + ctr.offsetHeight/2) {
1126
1127 ids.push(e.id.replace("RROW-", ""));
1128
1129 } */
1130
1131 }
1132
1133 e = e.nextSibling;
1134 }
1135
1136 debug("cdmWatchdog, ids= " + ids.toString());
1137
1138 if (ids.length > 0) {
1139
1140 for (var i = 0; i < ids.length; i++) {
1141 var e = document.getElementById("RROW-" + ids[i]);
1142 if (e) {
1143 e.className = e.className.replace("Unread", "");
1144 }
1145 }
1146
1147 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
1148 param_escape(ids.toString()) + "&cmode=0";
1149
1150 new Ajax.Request(query, {
1151 onComplete: function(transport) {
1152 all_counters_callback2(transport);
1153 } });
1154
1155 }
1156
1157 _cdm_wd_timeout = window.setTimeout("cdmWatchdog()", 4000);
1158
1159 } catch (e) {
1160 exception_error(e, "cdmWatchdog");
1161 }
1162
1163 }
1164
1165
1166 function cache_inject(id, article) {
1167 if (!cache_check(id)) {
1168 debug("cache_article: miss: " + id);
1169
1170 var cache_obj = new Array();
1171
1172 cache_obj["id"] = id;
1173 cache_obj["data"] = article;
1174
1175 article_cache.push(cache_obj);
1176
1177 } else {
1178 debug("cache_article: hit: " + id);
1179 }
1180 }
1181
1182 function cache_find(id) {
1183 for (var i = 0; i < article_cache.length; i++) {
1184 if (article_cache[i]["id"] == id) {
1185 return article_cache[i]["data"];
1186 }
1187 }
1188 return false;
1189 }
1190
1191 function cache_check(id) {
1192 for (var i = 0; i < article_cache.length; i++) {
1193 if (article_cache[i]["id"] == id) {
1194 return true;
1195 }
1196 }
1197 return false;
1198 }
1199
1200 function cache_expire() {
1201 while (article_cache.length > 20) {
1202 article_cache.shift();
1203 }
1204 }
1205
1206 function cache_invalidate(id) {
1207 var i = 0
1208
1209 try {
1210
1211 while (i < article_cache.length) {
1212 if (article_cache[i]["id"] == id) {
1213 debug("cache_invalidate: removed id " + id);
1214 article_cache.splice(i, 1);
1215 return true;
1216 }
1217 i++;
1218 }
1219 debug("cache_invalidate: id not found: " + id);
1220 return false;
1221 } catch (e) {
1222 exception_error("cache_invalidate", e);
1223 }
1224 }
1225
1226 function getActiveArticleId() {
1227 return active_post_id;
1228 }
1229
1230 function cdmMouseIn(elem) {
1231 try {
1232 if (elem.id && elem.id.match("RROW-")) {
1233 var id = elem.id.replace("RROW-", "");
1234 active_post_id = id;
1235 }
1236 } catch (e) {
1237 exception_error("cdmMouseIn", e);
1238 }
1239
1240 }
1241
1242 function cdmMouseOut(elem) {
1243 active_post_id = false;
1244 }
1245
1246 function headlines_scroll_handler() {
1247 try {
1248
1249 var e = document.getElementById("headlinesInnerContainer");
1250
1251 // don't do infinite scrolling when Limit == All
1252
1253 var toolbar_form = document.forms["main_toolbar_form"];
1254
1255 var limit = toolbar_form.limit[toolbar_form.limit.selectedIndex];
1256 if (limit.value != 0) {
1257 if (e.scrollTop + e.offsetHeight > e.scrollHeight - 50) {
1258 if (!_infscroll_disable) {
1259 debug("more cowbell!");
1260 viewNextFeedPage();
1261 }
1262 }
1263 }
1264
1265 } catch (e) {
1266 exception_error("headlines_scroll_handler", e);
1267 }
1268 }
1269
1270 function catchupRelativeToArticle(below) {
1271
1272 try {
1273
1274 if (!xmlhttp_ready(xmlhttp_rpc)) {
1275 printLockingError();
1276 }
1277
1278 if (!getActiveArticleId()) {
1279 alert(__("No article is selected."));
1280 return;
1281 }
1282
1283 var visible_ids;
1284
1285 if (document.getElementById("headlinesList")) {
1286 visible_ids = getVisibleHeadlineIds();
1287 } else {
1288 visible_ids = cdmGetVisibleArticles();
1289 }
1290
1291 var ids_to_mark = new Array();
1292
1293 if (!below) {
1294 for (var i = 0; i < visible_ids.length; i++) {
1295 if (visible_ids[i] != getActiveArticleId()) {
1296 var e = document.getElementById("RROW-" + visible_ids[i]);
1297
1298 if (e && e.className.match("Unread")) {
1299 ids_to_mark.push(visible_ids[i]);
1300 }
1301 } else {
1302 break;
1303 }
1304 }
1305 } else {
1306 for (var i = visible_ids.length-1; i >= 0; i--) {
1307 if (visible_ids[i] != getActiveArticleId()) {
1308 var e = document.getElementById("RROW-" + visible_ids[i]);
1309
1310 if (e && e.className.match("Unread")) {
1311 ids_to_mark.push(visible_ids[i]);
1312 }
1313 } else {
1314 break;
1315 }
1316 }
1317 }
1318
1319 if (ids_to_mark.length == 0) {
1320 alert(__("No articles found to mark"));
1321 } else {
1322 var msg = __("Mark %d article(s) as read?").replace("%d", ids_to_mark.length);
1323
1324 if (confirm(msg)) {
1325
1326 for (var i = 0; i < ids_to_mark.length; i++) {
1327 var e = document.getElementById("RROW-" + ids_to_mark[i]);
1328 e.className = e.className.replace("Unread", "");
1329 }
1330
1331 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
1332 param_escape(ids_to_mark.toString()) + "&cmode=0";
1333
1334 xmlhttp_rpc.open("GET", query, true);
1335 xmlhttp_rpc.onreadystatechange=catchup_callback;
1336 xmlhttp_rpc.send(null);
1337
1338 }
1339 }
1340
1341 } catch (e) {
1342 exception_error("catchupRelativeToArticle", e);
1343 }
1344 }