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