]> git.wh0rd.org - tt-rss.git/blob - viewfeed.js
switch view() to async
[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
179 notify("");
180 } catch (e) {
181 exception_error("headlines_callback2", e);
182 }
183 }
184
185 function render_article(article) {
186 try {
187 var f = document.getElementById("content-frame");
188 try {
189 f.scrollTop = 0;
190 } catch (e) { };
191
192 f.innerHTML = article;
193
194 } catch (e) {
195 exception_error("render_article", e);
196 }
197 }
198
199 function showArticleInHeadlines(id) {
200
201 cleanSelected("headlinesList");
202
203 var crow = document.getElementById("RROW-" + id);
204 var article_is_unread = crow.className.match("Unread");
205
206 crow.className = crow.className.replace("Unread", "");
207
208 var upd_img_pic = document.getElementById("FUPDPIC-" + id);
209
210 if (upd_img_pic) {
211 upd_img_pic.src = "images/blank_icon.gif";
212 }
213
214 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
215 markHeadline(id);
216
217 }
218
219 function article_callback2(transport, id, feed_id) {
220 try {
221 debug("article_callback2 " + id);
222
223 if (transport.responseXML) {
224
225 active_real_feed_id = feed_id;
226 active_post_id = id;
227
228 showArticleInHeadlines(id);
229
230 var reply = transport.responseXML.firstChild.firstChild;
231
232 var articles = transport.responseXML.getElementsByTagName("article");
233
234 for (var i = 0; i < articles.length; i++) {
235 var a_id = articles[i].getAttribute("id");
236
237 debug("found id: " + a_id);
238
239 if (a_id == active_post_id) {
240 debug("active article, rendering...");
241 render_article(articles[i].firstChild.nodeValue);
242 }
243
244 cache_inject(a_id, articles[i].firstChild.nodeValue);
245 }
246
247 } else {
248 debug("article_callback: returned no XML object");
249 var f = document.getElementById("content-frame");
250 f.innerHTML = "<div class='whiteBox'>" + __('Could not display article (missing XML object)') + "</div>";
251 }
252
253 var date = new Date();
254 last_article_view = date.getTime() / 1000;
255
256 if (typeof correctPNG != 'undefined') {
257 correctPNG();
258 }
259
260 if (_reload_feedlist_after_view) {
261 setTimeout('updateFeedList(false, false)', 50);
262 _reload_feedlist_after_view = false;
263 } else {
264 var counters = transport.responseXML.getElementsByTagName("counters")[0];
265
266 if (counters) {
267 debug("parsing piggybacked counters: " + counters);
268 parse_counters(counters, false);
269 } else {
270 debug("counters container not found in reply");
271 }
272 }
273
274 notify("");
275 } catch (e) {
276 exception_error("article_callback2", e);
277 }
278 }
279
280 function view(id, feed_id, skip_history) {
281
282 try {
283 debug("loading article: " + id + "/" + feed_id);
284
285 var cached_article = cache_find(id);
286
287 debug("cache check result: " + (cached_article != false));
288
289 enableHotkeys();
290
291 //setActiveFeedId(feed_id);
292
293 var query = "backend.php?op=view&id=" + param_escape(id) +
294 "&feed=" + param_escape(feed_id);
295
296 var date = new Date();
297
298 /* if (!xmlhttp_ready(xmlhttp) && last_article_view < date.getTime() / 1000 - 15) {
299 debug("<b>xmlhttp seems to be stuck at view, aborting</b>");
300 xmlhttp.abort();
301 if (is_safari()) {
302 debug("trying alternative reset method for Safari");
303 xmlhttp = Ajax.getTransport();
304 }
305 }
306
307 if (xmlhttp_ready(xmlhttp)) { */
308
309 var neighbor_ids = getRelativePostIds(active_post_id);
310
311 /* only request uncached articles */
312
313 var cids_to_request = Array();
314
315 for (var i = 0; i < neighbor_ids.length; i++) {
316 if (!cache_check(neighbor_ids[i])) {
317 cids_to_request.push(neighbor_ids[i]);
318 }
319 }
320
321 debug("additional ids: " + cids_to_request.toString());
322
323 /* additional info for piggyback counters */
324
325 if (tagsAreDisplayed()) {
326 query = query + "&omode=lt";
327 } else {
328 query = query + "&omode=flc";
329 }
330
331 var date = new Date();
332 var timestamp = Math.round(date.getTime() / 1000);
333 query = query + "&ts=" + timestamp;
334
335 query = query + "&cids=" + cids_to_request.toString();
336
337 var crow = document.getElementById("RROW-" + id);
338 var article_is_unread = crow.className.match("Unread");
339
340 showArticleInHeadlines(id);
341
342 if (!cached_article) {
343
344 notify_progress("Loading, please wait...");
345
346 } else if (cached_article && article_is_unread) {
347
348 query = query + "&mode=prefetch";
349
350 render_article(cached_article);
351
352 } else if (cached_article) {
353
354 query = query + "&mode=prefetch_old";
355 render_article(cached_article);
356 }
357
358 cache_expire();
359
360 new Ajax.Request(query, {
361 onComplete: function(transport) {
362 article_callback2(transport, id, feed_id);
363 } });
364
365 } catch (e) {
366 exception_error("view", e);
367 }
368 }
369
370 function tMark(id) {
371 return toggleMark(id);
372 }
373
374 function tPub(id) {
375 return togglePub(id);
376 }
377
378 function tMark_afh_off(effect) {
379 try {
380 var elem = effect.effects[0].element;
381
382 debug("tMark_afh_off : " + elem.id);
383
384 if (elem) {
385 elem.src = elem.src.replace("mark_set", "mark_unset");
386 elem.alt = __("Star article");
387 Element.show(elem);
388 }
389
390 } catch (e) {
391 exception_error("tMark_afh_off", e);
392 }
393 }
394
395 function tPub_afh_off(effect) {
396 try {
397 var elem = effect.effects[0].element;
398
399 debug("tPub_afh_off : " + elem.id);
400
401 if (elem) {
402 elem.src = elem.src.replace("pub_set", "pub_unset");
403 elem.alt = __("Publish article");
404 Element.show(elem);
405 }
406
407 } catch (e) {
408 exception_error("tPub_afh_off", e);
409 }
410 }
411
412 function toggleMark(id, client_only, no_effects) {
413
414 try {
415
416 var query = "backend.php?op=rpc&id=" + id + "&subop=mark";
417
418 query = query + "&afid=" + getActiveFeedId();
419
420 if (tagsAreDisplayed()) {
421 query = query + "&omode=tl";
422 } else {
423 query = query + "&omode=flc";
424 }
425
426 var mark_img = document.getElementById("FMPIC-" + id);
427 var vfeedu = document.getElementById("FEEDU--1");
428 var crow = document.getElementById("RROW-" + id);
429
430 if (mark_img.src.match("mark_unset")) {
431 mark_img.src = mark_img.src.replace("mark_unset", "mark_set");
432 mark_img.alt = __("Unstar article");
433 query = query + "&mark=1";
434
435 /* if (vfeedu && crow.className.match("Unread")) {
436 vfeedu.innerHTML = (+vfeedu.innerHTML) + 1;
437 } */
438
439 } else {
440 //mark_img.src = "images/mark_unset.png";
441 mark_img.alt = __("Please wait...");
442 query = query + "&mark=0";
443
444 /* if (vfeedu && crow.className.match("Unread")) {
445 vfeedu.innerHTML = (+vfeedu.innerHTML) - 1;
446 } */
447
448 if (document.getElementById("headlinesList") && !no_effects) {
449 Effect.Puff(mark_img, {duration : 0.25, afterFinish: tMark_afh_off});
450 } else {
451 mark_img.src = mark_img.src.replace("mark_set", "mark_unset");
452 mark_img.alt = __("Star article");
453 }
454 }
455
456 /* var vfeedctr = document.getElementById("FEEDCTR--1");
457 var vfeedr = document.getElementById("FEEDR--1");
458
459 if (vfeedu && vfeedctr) {
460 if ((+vfeedu.innerHTML) > 0) {
461 if (crow.className.match("Unread") && !vfeedr.className.match("Unread")) {
462 vfeedr.className = vfeedr.className + "Unread";
463 vfeedctr.className = "odd";
464 }
465 } else {
466 vfeedctr.className = "invisible";
467 vfeedr.className = vfeedr.className.replace("Unread", "");
468 }
469 }
470
471 debug("toggle starred for aid " + id);
472
473 //new Ajax.Request(query); */
474
475 if (!client_only) {
476 debug(query);
477
478 new Ajax.Request(query, {
479 onComplete: function(transport) {
480 all_counters_callback2(transport);
481 } });
482
483 }
484
485 } catch (e) {
486 exception_error("toggleMark", e);
487 }
488 }
489
490 function togglePub(id, client_only, no_effects) {
491
492 try {
493
494 var query = "backend.php?op=rpc&id=" + id + "&subop=publ";
495
496 query = query + "&afid=" + getActiveFeedId();
497
498 if (tagsAreDisplayed()) {
499 query = query + "&omode=tl";
500 } else {
501 query = query + "&omode=flc";
502 }
503
504 var mark_img = document.getElementById("FPPIC-" + id);
505 var vfeedu = document.getElementById("FEEDU--2");
506 var crow = document.getElementById("RROW-" + id);
507
508 if (mark_img.src.match("pub_unset")) {
509 mark_img.src = mark_img.src.replace("pub_unset", "pub_set");
510 mark_img.alt = __("Unpublish article");
511 query = query + "&pub=1";
512
513 /* if (vfeedu && crow.className.match("Unread")) {
514 vfeedu.innerHTML = (+vfeedu.innerHTML) + 1;
515 } */
516
517 } else {
518 //mark_img.src = "images/pub_unset.png";
519 mark_img.alt = __("Please wait...");
520 query = query + "&pub=0";
521
522 /* if (vfeedu && crow.className.match("Unread")) {
523 vfeedu.innerHTML = (+vfeedu.innerHTML) - 1;
524 } */
525
526 if (document.getElementById("headlinesList") && !no_effects) {
527 Effect.Puff(mark_img, {duration : 0.25, afterFinish: tPub_afh_off});
528 } else {
529 mark_img.src = mark_img.src.replace("pub_set", "pub_unset");
530 mark_img.alt = __("Publish article");
531 }
532 }
533
534 /* var vfeedctr = document.getElementById("FEEDCTR--2");
535 var vfeedr = document.getElementById("FEEDR--2");
536
537 if (vfeedu && vfeedctr) {
538 if ((+vfeedu.innerHTML) > 0) {
539 if (crow.className.match("Unread") && !vfeedr.className.match("Unread")) {
540 vfeedr.className = vfeedr.className + "Unread";
541 vfeedctr.className = "odd";
542 }
543 } else {
544 vfeedctr.className = "invisible";
545 vfeedr.className = vfeedr.className.replace("Unread", "");
546 }
547 }
548
549 debug("toggle published for aid " + id);
550
551 new Ajax.Request(query); */
552
553 if (!client_only) {
554 new Ajax.Request(query, {
555 onComplete: function(transport) {
556 all_counters_callback2(transport);
557 } });
558 }
559
560 } catch (e) {
561
562 exception_error("togglePub", e);
563 }
564 }
565
566 function correctHeadlinesOffset(id) {
567
568 try {
569
570 var hlist = document.getElementById("headlinesList");
571 var container = document.getElementById("headlinesInnerContainer");
572 var row = document.getElementById("RROW-" + id);
573
574 var viewport = container.offsetHeight;
575
576 var rel_offset_top = row.offsetTop - container.scrollTop;
577 var rel_offset_bottom = row.offsetTop + row.offsetHeight - container.scrollTop;
578
579 debug("Rtop: " + rel_offset_top + " Rbtm: " + rel_offset_bottom);
580 debug("Vport: " + viewport);
581
582 if (rel_offset_top <= 0 || rel_offset_top > viewport) {
583 container.scrollTop = row.offsetTop;
584 } else if (rel_offset_bottom > viewport) {
585
586 /* doesn't properly work with Opera in some cases because
587 Opera fucks up element scrolling */
588
589 container.scrollTop = row.offsetTop + row.offsetHeight - viewport;
590 }
591
592 } catch (e) {
593 exception_error("correctHeadlinesOffset", e);
594 }
595
596 }
597
598 function moveToPost(mode) {
599
600 // check for combined mode
601 if (!document.getElementById("headlinesList"))
602 return;
603
604 var rows = getVisibleHeadlineIds();
605
606 var prev_id = false;
607 var next_id = false;
608
609 if (!document.getElementById('RROW-' + active_post_id)) {
610 active_post_id = false;
611 }
612
613 if (active_post_id == false) {
614 next_id = getFirstVisibleHeadlineId();
615 prev_id = getLastVisibleHeadlineId();
616 } else {
617 for (var i = 0; i < rows.length; i++) {
618 if (rows[i] == active_post_id) {
619 prev_id = rows[i-1];
620 next_id = rows[i+1];
621 }
622 }
623 }
624
625 if (mode == "next") {
626 if (next_id) {
627 correctHeadlinesOffset(next_id);
628 view(next_id, getActiveFeedId());
629 }
630 }
631
632 if (mode == "prev") {
633 if (prev_id) {
634 correctHeadlinesOffset(prev_id);
635 view(prev_id, getActiveFeedId());
636 }
637 }
638 }
639
640 function toggleUnread(id, cmode) {
641 try {
642
643 var row = document.getElementById("RROW-" + id);
644 if (row) {
645 var nc = row.className;
646 nc = nc.replace("Unread", "");
647 nc = nc.replace("Selected", "");
648
649 if (row.className.match("Unread")) {
650 row.className = nc;
651 } else {
652 row.className = nc + "Unread";
653 }
654
655 if (!cmode) cmode = 2;
656
657 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
658 param_escape(id) + "&cmode=" + param_escape(cmode);
659
660 // notify_progress("Loading, please wait...");
661
662 new Ajax.Request(query, {
663 onComplete: function(transport) {
664 all_counters_callback2(transport);
665 } });
666
667 }
668
669
670 } catch (e) {
671 exception_error("toggleUnread", e);
672 }
673 }
674
675 function selectionToggleUnread(cdm_mode, set_state, callback_func, no_error) {
676 try {
677 /* if (!xmlhttp_ready(xmlhttp_rpc)) {
678 printLockingError();
679 return;
680 } */
681
682 var rows;
683
684 if (cdm_mode) {
685 rows = cdmGetSelectedArticles();
686 } else {
687 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
688 }
689
690 if (rows.length == 0 && !no_error) {
691 alert(__("No articles are selected."));
692 return;
693 }
694
695 for (i = 0; i < rows.length; i++) {
696 var row = document.getElementById("RROW-" + rows[i]);
697 if (row) {
698 var nc = row.className;
699 nc = nc.replace("Unread", "");
700 nc = nc.replace("Selected", "");
701
702 if (set_state == undefined) {
703 if (row.className.match("Unread")) {
704 row.className = nc + "Selected";
705 } else {
706 row.className = nc + "UnreadSelected";
707 }
708 }
709
710 if (set_state == false) {
711 row.className = nc + "Selected";
712 }
713
714 if (set_state == true) {
715 row.className = nc + "UnreadSelected";
716 }
717 }
718 }
719
720 if (rows.length > 0) {
721
722 var cmode = "";
723
724 if (set_state == undefined) {
725 cmode = "2";
726 } else if (set_state == true) {
727 cmode = "1";
728 } else if (set_state == false) {
729 cmode = "0";
730 }
731
732 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
733 param_escape(rows.toString()) + "&cmode=" + cmode;
734
735 // _catchup_callback_func = callback_func;
736
737 debug(callback_func);
738
739 notify_progress("Loading, please wait...");
740
741 /* xmlhttp_rpc.open("GET", query, true);
742 xmlhttp_rpc.onreadystatechange=catchup_callback;
743 xmlhttp_rpc.send(null); */
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 all selected articles in %s as read?");
974
975 str = str.replace("%s", fn);
976
977 if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
978 return;
979 }
980
981 if (document.getElementById("headlinesList")) {
982 selectionToggleUnread(false, false, 'viewCurrentFeed()', true);
983 // selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
984 } else {
985 selectionToggleUnread(true, false, 'viewCurrentFeed()', true)
986 // cdmSelectArticles('none');
987 }
988
989 } catch (e) {
990 exception_error("catchupSelection", e);
991 }
992 }
993
994
995 function labelFromSearch(search, search_mode, match_on, feed_id, is_cat) {
996
997 if (!xmlhttp_ready(xmlhttp_rpc)) {
998 printLockingError();
999 }
1000
1001 var title = prompt(__("Please enter label title:"), "");
1002
1003 if (title) {
1004
1005 var query = "backend.php?op=labelFromSearch&search=" + param_escape(search) +
1006 "&smode=" + param_escape(search_mode) + "&match=" + param_escape(match_on) +
1007 "&feed=" + param_escape(feed_id) + "&is_cat=" + param_escape(is_cat) +
1008 "&title=" + param_escape(title);
1009
1010 debug("LFS: " + query);
1011
1012 xmlhttp_rpc.open("GET", query, true);
1013 xmlhttp_rpc.onreadystatechange=dlg_frefresh_callback;
1014 xmlhttp_rpc.send(null);
1015 }
1016
1017 }
1018
1019 function editArticleTags(id, feed_id, cdm_enabled) {
1020 _tag_active_post_id = id;
1021 _tag_active_feed_id = feed_id;
1022 _tag_active_cdm = cdm_enabled;
1023
1024 cache_invalidate(id);
1025
1026 try {
1027 _tag_cdm_scroll = document.getElementById("headlinesInnerContainer").scrollTop;
1028 } catch (e) { }
1029 displayDlg('editArticleTags', id);
1030 }
1031
1032
1033 function tag_saved_callback() {
1034 if (xmlhttp_rpc.readyState == 4) {
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
1061 function editTagsSave() {
1062
1063 if (!xmlhttp_ready(xmlhttp_rpc)) {
1064 printLockingError();
1065 }
1066
1067 notify_progress("Saving article tags...");
1068
1069 var form = document.forms["tag_edit_form"];
1070
1071 var query = Form.serialize("tag_edit_form");
1072
1073 query = "backend.php?op=rpc&subop=setArticleTags&" + query;
1074
1075 debug(query);
1076
1077 xmlhttp_rpc.open("GET", query, true);
1078 xmlhttp_rpc.onreadystatechange=tag_saved_callback;
1079 xmlhttp_rpc.send(null);
1080
1081 }
1082
1083 function editTagsInsert() {
1084 try {
1085
1086 var form = document.forms["tag_edit_form"];
1087
1088 var found_tags = form.found_tags;
1089 var tags_str = form.tags_str;
1090
1091 var tag = found_tags[found_tags.selectedIndex].value;
1092
1093 if (tags_str.value.length > 0 &&
1094 tags_str.value.lastIndexOf(", ") != tags_str.value.length - 2) {
1095
1096 tags_str.value = tags_str.value + ", ";
1097 }
1098
1099 tags_str.value = tags_str.value + tag + ", ";
1100
1101 found_tags.selectedIndex = 0;
1102
1103 } catch (e) {
1104 exception_error(e, "editTagsInsert");
1105 }
1106 }
1107
1108 function cdmWatchdog() {
1109
1110 try {
1111
1112 var ctr = document.getElementById("headlinesInnerContainer");
1113
1114 if (!ctr) return;
1115
1116 var ids = new Array();
1117
1118 var e = ctr.firstChild;
1119
1120 while (e) {
1121 if (e.className && e.className == "cdmArticleUnread" && e.id &&
1122 e.id.match("RROW-")) {
1123
1124 // article fits in viewport OR article is longer than viewport and
1125 // its bottom is visible
1126
1127 if (ctr.scrollTop <= e.offsetTop && e.offsetTop + e.offsetHeight <=
1128 ctr.scrollTop + ctr.offsetHeight) {
1129
1130 // debug(e.id + " is visible " + e.offsetTop + "." +
1131 // (e.offsetTop + e.offsetHeight) + " vs " + ctr.scrollTop + "." +
1132 // (ctr.scrollTop + ctr.offsetHeight));
1133
1134 ids.push(e.id.replace("RROW-", ""));
1135
1136 } else if (e.offsetHeight > ctr.offsetHeight &&
1137 e.offsetTop + e.offsetHeight >= ctr.scrollTop &&
1138 e.offsetTop + e.offsetHeight <= ctr.scrollTop + ctr.offsetHeight) {
1139
1140 ids.push(e.id.replace("RROW-", ""));
1141
1142 }
1143
1144 // method 2: article bottom is visible and is in upper 1/2 of the viewport
1145
1146 /* if (e.offsetTop + e.offsetHeight >= ctr.scrollTop &&
1147 e.offsetTop + e.offsetHeight <= ctr.scrollTop + ctr.offsetHeight/2) {
1148
1149 ids.push(e.id.replace("RROW-", ""));
1150
1151 } */
1152
1153 }
1154
1155 e = e.nextSibling;
1156 }
1157
1158 debug("cdmWatchdog, ids= " + ids.toString());
1159
1160 if (ids.length > 0) {
1161
1162 for (var i = 0; i < ids.length; i++) {
1163 var e = document.getElementById("RROW-" + ids[i]);
1164 if (e) {
1165 e.className = e.className.replace("Unread", "");
1166 }
1167 }
1168
1169 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
1170 param_escape(ids.toString()) + "&cmode=0";
1171
1172 new Ajax.Request(query, {
1173 onComplete: function(transport) {
1174 all_counters_callback2(transport);
1175 } });
1176
1177 }
1178
1179 _cdm_wd_timeout = window.setTimeout("cdmWatchdog()", 4000);
1180
1181 } catch (e) {
1182 exception_error(e, "cdmWatchdog");
1183 }
1184
1185 }
1186
1187
1188 function cache_inject(id, article) {
1189 if (!cache_check(id)) {
1190 debug("cache_article: miss: " + id);
1191
1192 var cache_obj = new Array();
1193
1194 cache_obj["id"] = id;
1195 cache_obj["data"] = article;
1196
1197 article_cache.push(cache_obj);
1198
1199 } else {
1200 debug("cache_article: hit: " + id);
1201 }
1202 }
1203
1204 function cache_find(id) {
1205 for (var i = 0; i < article_cache.length; i++) {
1206 if (article_cache[i]["id"] == id) {
1207 return article_cache[i]["data"];
1208 }
1209 }
1210 return false;
1211 }
1212
1213 function cache_check(id) {
1214 for (var i = 0; i < article_cache.length; i++) {
1215 if (article_cache[i]["id"] == id) {
1216 return true;
1217 }
1218 }
1219 return false;
1220 }
1221
1222 function cache_expire() {
1223 while (article_cache.length > 20) {
1224 article_cache.shift();
1225 }
1226 }
1227
1228 function cache_invalidate(id) {
1229 var i = 0
1230
1231 try {
1232
1233 while (i < article_cache.length) {
1234 if (article_cache[i]["id"] == id) {
1235 debug("cache_invalidate: removed id " + id);
1236 article_cache.splice(i, 1);
1237 return true;
1238 }
1239 i++;
1240 }
1241 debug("cache_invalidate: id not found: " + id);
1242 return false;
1243 } catch (e) {
1244 exception_error("cache_invalidate", e);
1245 }
1246 }
1247
1248 function getActiveArticleId() {
1249 return active_post_id;
1250 }
1251
1252 function cdmMouseIn(elem) {
1253 try {
1254 if (elem.id && elem.id.match("RROW-")) {
1255 var id = elem.id.replace("RROW-", "");
1256 active_post_id = id;
1257 }
1258 } catch (e) {
1259 exception_error("cdmMouseIn", e);
1260 }
1261
1262 }
1263
1264 function cdmMouseOut(elem) {
1265 active_post_id = false;
1266 }
1267
1268 function headlines_scroll_handler() {
1269 try {
1270
1271 var e = document.getElementById("headlinesInnerContainer");
1272
1273 if (e.scrollTop + e.offsetHeight > e.scrollHeight - 300) {
1274 if (!_infscroll_disable) {
1275 debug("more cowbell!");
1276 viewNextFeedPage();
1277 }
1278 }
1279
1280 } catch (e) {
1281 exception_error("headlines_scroll_handler", e);
1282 }
1283 }
1284
1285 function catchupRelativeToArticle(below) {
1286
1287 try {
1288
1289 if (!xmlhttp_ready(xmlhttp_rpc)) {
1290 printLockingError();
1291 }
1292
1293 if (!getActiveArticleId()) {
1294 alert(__("No article is selected."));
1295 return;
1296 }
1297
1298 var visible_ids;
1299
1300 if (document.getElementById("headlinesList")) {
1301 visible_ids = getVisibleHeadlineIds();
1302 } else {
1303 visible_ids = cdmGetVisibleArticles();
1304 }
1305
1306 var ids_to_mark = new Array();
1307
1308 if (!below) {
1309 for (var i = 0; i < visible_ids.length; i++) {
1310 if (visible_ids[i] != getActiveArticleId()) {
1311 var e = document.getElementById("RROW-" + visible_ids[i]);
1312
1313 if (e && e.className.match("Unread")) {
1314 ids_to_mark.push(visible_ids[i]);
1315 }
1316 } else {
1317 break;
1318 }
1319 }
1320 } else {
1321 for (var i = visible_ids.length-1; i >= 0; i--) {
1322 if (visible_ids[i] != getActiveArticleId()) {
1323 var e = document.getElementById("RROW-" + visible_ids[i]);
1324
1325 if (e && e.className.match("Unread")) {
1326 ids_to_mark.push(visible_ids[i]);
1327 }
1328 } else {
1329 break;
1330 }
1331 }
1332 }
1333
1334 if (ids_to_mark.length == 0) {
1335 alert(__("No articles found to mark"));
1336 } else {
1337 var msg = __("Mark %d article(s) as read?").replace("%d", ids_to_mark.length);
1338
1339 if (confirm(msg)) {
1340
1341 for (var i = 0; i < ids_to_mark.length; i++) {
1342 var e = document.getElementById("RROW-" + ids_to_mark[i]);
1343 e.className = e.className.replace("Unread", "");
1344 }
1345
1346 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
1347 param_escape(ids_to_mark.toString()) + "&cmode=0";
1348
1349 xmlhttp_rpc.open("GET", query, true);
1350 xmlhttp_rpc.onreadystatechange=catchup_callback;
1351 xmlhttp_rpc.send(null);
1352
1353 }
1354 }
1355
1356 } catch (e) {
1357 exception_error("catchupRelativeToArticle", e);
1358 }
1359 }