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