]> git.wh0rd.org - tt-rss.git/blob - viewfeed.js
update translations
[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 // FIXME: kludges, needs proper implementation
6 var _reload_feedlist_after_view = false;
7
8 var _cdm_wd_timeout = false;
9 var _cdm_wd_vishist = new Array();
10
11 var article_cache = new Array();
12
13 var vgroup_last_feed = false;
14 var post_under_pointer = false;
15
16 var last_requested_article = false;
17
18 function catchup_callback2(transport, callback) {
19 try {
20 debug("catchup_callback2 " + transport + ", " + callback);
21 notify("");
22 all_counters_callback2(transport);
23 if (callback) {
24 setTimeout(callback, 10);
25 }
26 } catch (e) {
27 exception_error("catchup_callback2", e, transport);
28 }
29 }
30
31 function clean_feed_selections() {
32 try {
33 var feeds = $("feedList").getElementsByTagName("LI");
34
35 for (var i = 0; i < feeds.length; i++) {
36 if (feeds[i].id && feeds[i].id.match("FEEDR-")) {
37 feeds[i].className = feeds[i].className.replace("Selected", "");
38 }
39 if (feeds[i].id && feeds[i].id.match("FCAT-")) {
40 feeds[i].className = feeds[i].className.replace("Selected", "");
41 }
42 }
43 } catch (e) {
44 exception_error("clean_feed_selections", e);
45 }
46 }
47
48 function headlines_callback2(transport, feed_cur_page) {
49 try {
50
51 if (!transport.responseText && db) {
52 offlineConfirmModeChange();
53 return;
54 }
55
56 loading_set_progress(100);
57
58 debug("headlines_callback2 [page=" + feed_cur_page + "]");
59
60 if (!transport_error_check(transport)) return;
61
62 clean_feed_selections();
63
64 var is_cat = false;
65 var feed_id = false;
66
67 if (transport.responseXML) {
68 var headlines = transport.responseXML.getElementsByTagName("headlines")[0];
69 if (headlines) {
70 is_cat = headlines.getAttribute("is_cat");
71 feed_id = headlines.getAttribute("id");
72 setActiveFeedId(feed_id, is_cat);
73 }
74 }
75
76 if (!is_cat) {
77 var feedr = $("FEEDR-" + feed_id);
78 if (feedr && !feedr.className.match("Selected")) {
79 feedr.className = feedr.className + "Selected";
80 }
81 } else {
82 var feedr = $("FCAT-" + feed_id);
83 if (feedr && !feedr.className.match("Selected")) {
84 feedr.className = feedr.className + "Selected";
85 }
86 }
87
88 var f = $("headlines-frame");
89 try {
90 if (feed_cur_page == 0) {
91 debug("resetting headlines scrollTop");
92 f.scrollTop = 0;
93 }
94 } catch (e) { };
95
96 if (transport.responseXML) {
97 var headlines = transport.responseXML.getElementsByTagName("headlines")[0];
98 var headlines_count_obj = transport.responseXML.getElementsByTagName("headlines-count")[0];
99 var headlines_unread_obj = transport.responseXML.getElementsByTagName("headlines-unread")[0];
100 var disable_cache_obj = transport.responseXML.getElementsByTagName("disable-cache")[0];
101
102 var vgroup_last_feed_obj = transport.responseXML.getElementsByTagName("vgroup-last-feed")[0];
103
104 var headlines_count = headlines_count_obj.getAttribute("value");
105 var headlines_unread = headlines_unread_obj.getAttribute("value");
106 var disable_cache = disable_cache_obj.getAttribute("value") != "0";
107
108 vgroup_last_feed = vgroup_last_feed_obj.getAttribute("value");
109
110 if (headlines_count == 0) {
111 _infscroll_disable = 1;
112 } else {
113 _infscroll_disable = 0;
114 }
115
116 var counters = transport.responseXML.getElementsByTagName("counters")[0];
117 var articles = transport.responseXML.getElementsByTagName("article");
118 var runtime_info = transport.responseXML.getElementsByTagName("runtime-info");
119
120 if (feed_cur_page == 0) {
121 if (headlines) {
122 f.innerHTML = headlines.firstChild.nodeValue;
123
124 var cache_prefix = "";
125
126 if (is_cat) {
127 cache_prefix = "C:";
128 } else {
129 cache_prefix = "F:";
130 }
131
132 cache_invalidate(cache_prefix + feed_id);
133
134 if (!disable_cache) {
135 cache_inject(cache_prefix + feed_id,
136 headlines.firstChild.nodeValue, headlines_unread);
137 }
138
139 } else {
140 debug("headlines_callback: returned no data");
141 f.innerHTML = "<div class='whiteBox'>" + __('Could not update headlines (missing XML data)') + "</div>";
142
143 }
144 } else {
145 if (headlines) {
146 if (headlines_count > 0) {
147 debug("adding some more headlines...");
148
149 var c = $("headlinesList");
150
151 if (!c) {
152 c = $("headlinesInnerContainer");
153 }
154
155 var ids = getSelectedArticleIds2();
156
157 c.innerHTML = c.innerHTML + headlines.firstChild.nodeValue;
158
159 debug("restore selected ids: " + ids);
160
161 for (var i = 0; i < ids.length; i++) {
162 markHeadline(ids[i]);
163 }
164
165 } else {
166 debug("no new headlines received");
167 }
168 } else {
169 debug("headlines_callback: returned no data");
170 notify_error("Error while trying to load more headlines");
171 }
172
173 }
174
175 if (articles) {
176 for (var i = 0; i < articles.length; i++) {
177 var a_id = articles[i].getAttribute("id");
178 debug("found id: " + a_id);
179 cache_inject(a_id, articles[i].firstChild.nodeValue);
180 }
181 } else {
182 debug("no cached articles received");
183 }
184
185 if (counters) {
186 debug("parsing piggybacked counters: " + counters);
187 parse_counters(counters, false);
188 } else {
189 debug("counters container not found in reply, requesting...");
190 request_counters();
191 }
192
193 if (runtime_info) {
194 debug("parsing runtime info: " + runtime_info[0]);
195 parse_runtime_info(runtime_info[0]);
196 } else {
197 debug("counters container not found in reply");
198 }
199
200 } else {
201 debug("headlines_callback: returned no XML object");
202 f.innerHTML = "<div class='whiteBox'>" + __('Could not update headlines (missing XML object)') + "</div>";
203 }
204
205 if (typeof correctPNG != 'undefined') {
206 correctPNG();
207 }
208
209 if (_cdm_wd_timeout) window.clearTimeout(_cdm_wd_timeout);
210
211 if (!$("headlinesList") &&
212 getActiveFeedId() != -3 &&
213 getInitParam("cdm_auto_catchup") == 1) {
214 debug("starting CDM watchdog");
215 _cdm_wd_timeout = window.setTimeout("cdmWatchdog()", 5000);
216 _cdm_wd_vishist = new Array();
217 } else {
218 debug("not in CDM mode or watchdog disabled");
219 }
220
221 _feed_cur_page = feed_cur_page;
222 _infscroll_request_sent = 0;
223
224 notify("");
225
226 remove_splash();
227
228 } catch (e) {
229 exception_error("headlines_callback2", e, transport);
230 }
231 }
232
233 function render_article(article) {
234 try {
235 var f = $("content-frame");
236 try {
237 f.scrollTop = 0;
238 } catch (e) { };
239
240 var fi = $("content-insert");
241
242 try {
243 fi.scrollTop = 0;
244 } catch (e) { };
245
246 fi.innerHTML = article;
247
248 } catch (e) {
249 exception_error("render_article", e);
250 }
251 }
252
253 function showArticleInHeadlines(id) {
254
255 try {
256
257 cleanSelected("headlinesList");
258
259 var crow = $("RROW-" + id);
260
261 if (!crow) return;
262
263 var article_is_unread = crow.className.match("Unread");
264
265 crow.className = crow.className.replace("Unread", "");
266
267 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
268
269 var upd_img_pic = $("FUPDPIC-" + id);
270
271 var cache_prefix = "";
272
273 if (activeFeedIsCat()) {
274 cache_prefix = "C:";
275 } else {
276 cache_prefix = "F:";
277 }
278
279 var view_mode = false;
280
281 try {
282 view_mode = document.forms['main_toolbar_form'].view_mode;
283 view_mode = view_mode[view_mode.selectedIndex].value;
284 } catch (e) {
285 //
286 }
287
288 if (upd_img_pic && upd_img_pic.src.match("updated.png")) {
289 upd_img_pic.src = "images/blank_icon.gif";
290
291 cache_invalidate(cache_prefix + getActiveFeedId());
292
293 cache_inject(cache_prefix + getActiveFeedId(),
294 $("headlines-frame").innerHTML,
295 get_feed_unread(getActiveFeedId()));
296
297 } else if (article_is_unread && view_mode == "all_articles") {
298
299 cache_invalidate(cache_prefix + getActiveFeedId());
300
301 cache_inject(cache_prefix + getActiveFeedId(),
302 $("headlines-frame").innerHTML,
303 get_feed_unread(getActiveFeedId())-1);
304
305 } else if (article_is_unread) {
306 cache_invalidate(cache_prefix + getActiveFeedId());
307 }
308
309 markHeadline(id);
310
311 } catch (e) {
312 exception_error("showArticleInHeadlines", e);
313 }
314 }
315
316 function article_callback2(transport, id, feed_id) {
317 try {
318 debug("article_callback2 " + id);
319
320 if (!transport.responseText && db) {
321 offlineConfirmModeChange();
322 return;
323 }
324
325 if (transport.responseXML) {
326
327 if (!transport_error_check(transport)) return;
328
329 debug("looking for articles to cache...");
330
331 var articles = transport.responseXML.getElementsByTagName("article");
332
333 for (var i = 0; i < articles.length; i++) {
334 var a_id = articles[i].getAttribute("id");
335
336 debug("found id: " + a_id);
337
338 if (a_id == active_post_id) {
339 debug("active article, rendering...");
340 render_article(articles[i].firstChild.nodeValue);
341 }
342
343 cache_inject(a_id, articles[i].firstChild.nodeValue);
344 }
345
346 if (id != last_requested_article) {
347 debug("requested article id is out of sequence, aborting");
348 return;
349 }
350
351 active_real_feed_id = feed_id;
352 active_post_id = id;
353
354 showArticleInHeadlines(id);
355
356 if (db) {
357 db.execute("UPDATE articles SET unread = 0 WHERE id = ?", [id]);
358 }
359
360 var reply = transport.responseXML.firstChild.firstChild;
361
362 } else {
363 debug("article_callback: returned no XML object");
364 //var f = $("content-frame");
365 //f.innerHTML = "<div class='whiteBox'>" + __('Could not display article (missing XML object)') + "</div>";
366 }
367
368 var date = new Date();
369 last_article_view = date.getTime() / 1000;
370
371 if (typeof correctPNG != 'undefined') {
372 correctPNG();
373 }
374
375 if (_reload_feedlist_after_view) {
376 setTimeout('updateFeedList(false, false)', 50);
377 _reload_feedlist_after_view = false;
378 } else {
379 if (transport.responseXML) {
380 var counters = transport.responseXML.getElementsByTagName("counters")[0];
381
382 if (counters) {
383 debug("parsing piggybacked counters: " + counters);
384 parse_counters(counters, false);
385 } else {
386 debug("counters container not found in reply, requesting...");
387 request_counters();
388 }
389 }
390 }
391
392 notify("");
393 } catch (e) {
394 exception_error("article_callback2", e, transport);
395 }
396 }
397
398 function view(id, feed_id, skip_history) {
399
400 try {
401 debug("loading article: " + id + "/" + feed_id);
402
403 if (offline_mode) return view_offline(id, feed_id);
404
405 var cached_article = cache_find(id);
406
407 debug("cache check result: " + (cached_article != false));
408
409 enableHotkeys();
410
411 //setActiveFeedId(feed_id);
412
413 var query = "backend.php?op=view&id=" + param_escape(id) +
414 "&feed=" + param_escape(feed_id);
415
416 var date = new Date();
417
418 var neighbor_ids = getRelativePostIds(active_post_id);
419
420 /* only request uncached articles */
421
422 var cids_to_request = Array();
423
424 for (var i = 0; i < neighbor_ids.length; i++) {
425 if (!cache_check(neighbor_ids[i])) {
426 cids_to_request.push(neighbor_ids[i]);
427 }
428 }
429
430 debug("additional ids: " + cids_to_request.toString());
431
432 /* additional info for piggyback counters */
433
434 if (tagsAreDisplayed()) {
435 query = query + "&omode=lt";
436 } else {
437 query = query + "&omode=flc";
438 }
439
440 var date = new Date();
441 var timestamp = Math.round(date.getTime() / 1000);
442 query = query + "&ts=" + timestamp;
443
444 query = query + "&cids=" + cids_to_request.toString();
445
446 var crow = $("RROW-" + id);
447 var article_is_unread = crow.className.match("Unread");
448
449 if (!async_counters_work) {
450 query = query + "&csync=true";
451 }
452
453 showArticleInHeadlines(id);
454
455 if (!cached_article) {
456
457 notify_progress("Loading, please wait...", true);
458
459 } else if (cached_article && article_is_unread) {
460
461 query = query + "&mode=prefetch";
462
463 render_article(cached_article);
464
465 } else if (cached_article) {
466
467 query = query + "&mode=prefetch_old";
468 render_article(cached_article);
469
470 }
471
472 cache_expire();
473
474 last_requested_article = id;
475
476 new Ajax.Request(query, {
477 onComplete: function(transport) {
478 article_callback2(transport, id, feed_id);
479 } });
480
481 return false;
482
483 } catch (e) {
484 exception_error("view", e);
485 }
486 }
487
488 function tMark(id) {
489 return toggleMark(id);
490 }
491
492 function tPub(id) {
493 return togglePub(id);
494 }
495
496 function tMark_afh_off(effect) {
497 try {
498 var elem = effect.effects[0].element;
499
500 debug("tMark_afh_off : " + elem.id);
501
502 if (elem) {
503 elem.src = elem.src.replace("mark_set", "mark_unset");
504 elem.alt = __("Star article");
505 Element.show(elem);
506 }
507
508 } catch (e) {
509 exception_error("tMark_afh_off", e);
510 }
511 }
512
513 function tPub_afh_off(effect) {
514 try {
515 var elem = effect.effects[0].element;
516
517 debug("tPub_afh_off : " + elem.id);
518
519 if (elem) {
520 elem.src = elem.src.replace("pub_set", "pub_unset");
521 elem.alt = __("Publish article");
522 Element.show(elem);
523 }
524
525 } catch (e) {
526 exception_error("tPub_afh_off", e);
527 }
528 }
529
530 function toggleMark(id, client_only, no_effects) {
531
532 try {
533
534 var query = "backend.php?op=rpc&id=" + id + "&subop=mark";
535
536 query = query + "&afid=" + getActiveFeedId();
537
538 if (tagsAreDisplayed()) {
539 query = query + "&omode=tl";
540 } else {
541 query = query + "&omode=flc";
542 }
543
544 var mark_img = $("FMPIC-" + id);
545
546 if (!mark_img) return;
547
548 var vfeedu = $("FEEDU--1");
549 var crow = $("RROW-" + id);
550
551 if (mark_img.src.match("mark_unset")) {
552 mark_img.src = mark_img.src.replace("mark_unset", "mark_set");
553 mark_img.alt = __("Unstar article");
554 query = query + "&mark=1";
555
556 if (db) {
557 db.execute("UPDATE articles SET marked = 1 WHERE id = ?", [id]);
558 }
559
560 } else {
561 //mark_img.src = "images/mark_unset.png";
562 mark_img.alt = __("Please wait...");
563 query = query + "&mark=0";
564
565 if ($("headlinesList") && !no_effects) {
566 Effect.Puff(mark_img, {duration : 0.25, afterFinish: tMark_afh_off});
567 } else {
568 mark_img.src = mark_img.src.replace("mark_set", "mark_unset");
569 mark_img.alt = __("Star article");
570 }
571
572 if (db) {
573 db.execute("UPDATE articles SET marked = 0 WHERE id = ?", [id]);
574 }
575
576 }
577
578 if (!no_effects) update_local_feedlist_counters();
579
580 if (!client_only) {
581 debug(query);
582
583 new Ajax.Request(query, {
584 onComplete: function(transport) {
585 all_counters_callback2(transport);
586 } });
587
588 }
589
590 } catch (e) {
591 exception_error("toggleMark", e);
592 }
593 }
594
595 function togglePub(id, client_only, no_effects) {
596
597 try {
598
599 var query = "backend.php?op=rpc&id=" + id + "&subop=publ";
600
601 query = query + "&afid=" + getActiveFeedId();
602
603 if (tagsAreDisplayed()) {
604 query = query + "&omode=tl";
605 } else {
606 query = query + "&omode=flc";
607 }
608
609 var mark_img = $("FPPIC-" + id);
610
611 if (!mark_img) return;
612
613 var vfeedu = $("FEEDU--2");
614 var crow = $("RROW-" + id);
615
616 if (mark_img.src.match("pub_unset")) {
617 mark_img.src = mark_img.src.replace("pub_unset", "pub_set");
618 mark_img.alt = __("Unpublish article");
619 query = query + "&pub=1";
620
621
622 } else {
623 //mark_img.src = "images/pub_unset.png";
624 mark_img.alt = __("Please wait...");
625 query = query + "&pub=0";
626
627 if ($("headlinesList") && !no_effects) {
628 Effect.Puff(mark_img, {duration : 0.25, afterFinish: tPub_afh_off});
629 } else {
630 mark_img.src = mark_img.src.replace("pub_set", "pub_unset");
631 mark_img.alt = __("Publish article");
632 }
633 }
634
635 if (!client_only) {
636 new Ajax.Request(query, {
637 onComplete: function(transport) {
638 all_counters_callback2(transport);
639 } });
640 }
641
642 } catch (e) {
643
644 exception_error("togglePub", e);
645 }
646 }
647
648 function correctHeadlinesOffset(id) {
649
650 try {
651
652 var hlist = $("headlinesList");
653 var container = $("headlinesInnerContainer");
654 var row = $("RROW-" + id);
655
656 var viewport = container.offsetHeight;
657
658 var rel_offset_top = row.offsetTop - container.scrollTop;
659 var rel_offset_bottom = row.offsetTop + row.offsetHeight - container.scrollTop;
660
661 debug("Rtop: " + rel_offset_top + " Rbtm: " + rel_offset_bottom);
662 debug("Vport: " + viewport);
663
664 if (rel_offset_top <= 0 || rel_offset_top > viewport) {
665 container.scrollTop = row.offsetTop;
666 } else if (rel_offset_bottom > viewport) {
667
668 /* doesn't properly work with Opera in some cases because
669 Opera fucks up element scrolling */
670
671 container.scrollTop = row.offsetTop + row.offsetHeight - viewport;
672 }
673
674 } catch (e) {
675 exception_error("correctHeadlinesOffset", e);
676 }
677
678 }
679
680 function moveToPost(mode) {
681
682 try {
683
684 var rows;
685
686 if (isCdmMode()) {
687 rows = cdmGetVisibleArticles();
688 } else {
689 rows = getVisibleHeadlineIds();
690 }
691
692 var prev_id = false;
693 var next_id = false;
694
695 if (!$('RROW-' + active_post_id)) {
696 active_post_id = false;
697 }
698
699 if (active_post_id == false) {
700 next_id = getFirstVisibleHeadlineId();
701 prev_id = getLastVisibleHeadlineId();
702 } else {
703 for (var i = 0; i < rows.length; i++) {
704 if (rows[i] == active_post_id) {
705 prev_id = rows[i-1];
706 next_id = rows[i+1];
707 }
708 }
709 }
710
711 if (mode == "next") {
712 if (next_id) {
713 if (isCdmMode()) {
714
715 if (!cdmArticleIsActuallyVisible(next_id)) {
716 cdmScrollToArticleId(next_id);
717 }
718 cdmSelectArticles("none");
719 toggleUnread(next_id, 0, true);
720 toggleSelected(next_id);
721
722 } else {
723 correctHeadlinesOffset(next_id);
724 view(next_id, getActiveFeedId());
725 }
726 }
727 }
728
729 if (mode == "prev") {
730 if (prev_id) {
731 if (isCdmMode()) {
732 cdmScrollToArticleId(prev_id);
733 cdmSelectArticles("none");
734 toggleUnread(prev_id, 0, true);
735 toggleSelected(prev_id);
736 } else {
737 correctHeadlinesOffset(prev_id);
738 view(prev_id, getActiveFeedId());
739 }
740 }
741 }
742
743 } catch (e) {
744 exception_error("moveToPost", e);
745 }
746 }
747
748 function toggleSelected(id) {
749 try {
750
751 var cb = $("RCHK-" + id);
752
753 var row = $("RROW-" + id);
754 if (row) {
755 var nc = row.className;
756
757 if (!nc.match("Selected")) {
758 nc = nc + "Selected";
759 if (cb) {
760 cb.checked = true;
761 }
762
763 // In CDM basically last selected article == active article
764 if (isCdmMode()) active_post_id = id;
765 } else {
766 nc = nc.replace("Selected", "");
767 if (cb) {
768 cb.checked = false;
769 }
770
771 }
772
773 row.className = nc;
774 }
775 } catch (e) {
776 exception_error("toggleSelected", e);
777 }
778 }
779
780 function toggleUnread_afh(effect) {
781 try {
782
783 var elem = effect.element;
784 elem.style.backgroundColor = "";
785
786 } catch (e) {
787 exception_error("toggleUnread_afh", e);
788 }
789 }
790
791 function toggleUnread(id, cmode, effect) {
792 try {
793
794 var row = $("RROW-" + id);
795 if (row) {
796 var nc = row.className;
797 var is_selected = row.className.match("Selected");
798 nc = nc.replace("Unread", "");
799 nc = nc.replace("Selected", "");
800
801 // since we are removing selection from the object, uncheck
802 // corresponding checkbox
803
804 var cb = $("RCHK-" + id);
805 if (cb) {
806 cb.checked = false;
807 }
808
809 // NOTE: I'm not sure that resetting selection here is a feature -fox
810
811 if (cmode == undefined || cmode == 2) {
812 if (row.className.match("Unread")) {
813 row.className = nc;
814
815 if (effect) {
816 new Effect.Highlight(row, {duration: 1, startcolor: "#fff7d5",
817 afterFinish: toggleUnread_afh,
818 queue: { position:'end', scope: 'TMRQ-' + id, limit: 1 } } );
819 }
820
821 } else {
822 row.className = nc + "Unread";
823 }
824
825 if (db) {
826 db.execute("UPDATE articles SET unread = not unread "+
827 "WHERE id = ?", [id]);
828 }
829
830 } else if (cmode == 0) {
831 row.className = nc;
832
833 if (effect) {
834 new Effect.Highlight(row, {duration: 1, startcolor: "#fff7d5",
835 afterFinish: toggleUnread_afh,
836 queue: { position:'end', scope: 'TMRQ-' + id, limit: 1 } } );
837 }
838
839 if (db) {
840 db.execute("UPDATE articles SET unread = 0 "+
841 "WHERE id = ?", [id]);
842 }
843
844 } else if (cmode == 1) {
845 row.className = nc + "Unread";
846
847 if (db) {
848 db.execute("UPDATE articles SET unread = 1 "+
849 "WHERE id = ?", [id]);
850 }
851
852 }
853
854 update_local_feedlist_counters();
855
856 // Disable unmarking as selected for the time being (16.05.08) -fox
857 if (is_selected) row.className = row.className + "Selected";
858
859 if (cmode == undefined) cmode = 2;
860
861 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
862 param_escape(id) + "&cmode=" + param_escape(cmode);
863
864 // notify_progress("Loading, please wait...");
865
866 new Ajax.Request(query, {
867 onComplete: function(transport) {
868 all_counters_callback2(transport);
869 } });
870
871 }
872
873 } catch (e) {
874 exception_error("toggleUnread", e);
875 }
876 }
877
878 function selectionRemoveLabel(id) {
879 try {
880
881 var ids = getSelectedArticleIds2();
882
883 if (ids.length == 0) {
884 alert(__("No articles are selected."));
885 return;
886 }
887
888 // var ok = confirm(__("Remove selected articles from label?"));
889
890 // if (ok) {
891
892 var query = "backend.php?op=rpc&subop=removeFromLabel&ids=" +
893 param_escape(ids.toString()) + "&lid=" + param_escape(id);
894
895 // notify_progress("Loading, please wait...");
896
897 cache_invalidate("F:" + (-11 - id));
898
899 new Ajax.Request(query, {
900 onComplete: function(transport) {
901 show_labels_in_headlines(transport);
902 all_counters_callback2(transport);
903 } });
904
905 // }
906
907 } catch (e) {
908 exception_error("selectionAssignLabel", e);
909
910 }
911 }
912
913 function selectionAssignLabel(id) {
914 try {
915
916 var ids = getSelectedArticleIds2();
917
918 if (ids.length == 0) {
919 alert(__("No articles are selected."));
920 return;
921 }
922
923 // var ok = confirm(__("Assign selected articles to label?"));
924
925 // if (ok) {
926
927 cache_invalidate("F:" + (-11 - id));
928
929 var query = "backend.php?op=rpc&subop=assignToLabel&ids=" +
930 param_escape(ids.toString()) + "&lid=" + param_escape(id);
931
932 // notify_progress("Loading, please wait...");
933
934 new Ajax.Request(query, {
935 onComplete: function(transport) {
936 show_labels_in_headlines(transport);
937 all_counters_callback2(transport);
938 } });
939
940 // }
941
942 } catch (e) {
943 exception_error("selectionAssignLabel", e);
944
945 }
946 }
947
948 function selectionToggleUnread(cdm_mode, set_state, callback_func, no_error) {
949 try {
950 var rows;
951
952 if (cdm_mode) {
953 rows = cdmGetSelectedArticles();
954 } else {
955 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
956 }
957
958 if (rows.length == 0 && !no_error) {
959 alert(__("No articles are selected."));
960 return;
961 }
962
963 for (i = 0; i < rows.length; i++) {
964 var row = $("RROW-" + rows[i]);
965 if (row) {
966 var nc = row.className;
967 nc = nc.replace("Unread", "");
968 nc = nc.replace("Selected", "");
969
970 if (set_state == undefined) {
971 if (row.className.match("Unread")) {
972 row.className = nc + "Selected";
973 } else {
974 row.className = nc + "UnreadSelected";
975 }
976 if (db) {
977 db.execute("UPDATE articles SET unread = NOT unread WHERE id = ?",
978 [rows[i]]);
979 }
980 }
981
982 if (set_state == false) {
983 row.className = nc + "Selected";
984 if (db) {
985 db.execute("UPDATE articles SET unread = 0 WHERE id = ?",
986 [rows[i]]);
987 }
988 }
989
990 if (set_state == true) {
991 row.className = nc + "UnreadSelected";
992 if (db) {
993 db.execute("UPDATE articles SET unread = 1 WHERE id = ?",
994 [rows[i]]);
995 }
996 }
997 }
998 }
999
1000 if (rows.length > 0) {
1001
1002 update_local_feedlist_counters();
1003
1004 var cmode = "";
1005
1006 if (set_state == undefined) {
1007 cmode = "2";
1008 } else if (set_state == true) {
1009 cmode = "1";
1010 } else if (set_state == false) {
1011 cmode = "0";
1012 }
1013
1014 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
1015 param_escape(rows.toString()) + "&cmode=" + cmode;
1016
1017 notify_progress("Loading, please wait...");
1018
1019 new Ajax.Request(query, {
1020 onComplete: function(transport) {
1021 catchup_callback2(transport, callback_func);
1022 } });
1023
1024 }
1025
1026 } catch (e) {
1027 exception_error("selectionToggleUnread", e);
1028 }
1029 }
1030
1031 function selectionToggleMarked(cdm_mode) {
1032 try {
1033
1034 var rows;
1035
1036 if (cdm_mode) {
1037 rows = cdmGetSelectedArticles();
1038 } else {
1039 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
1040 }
1041
1042 if (rows.length == 0) {
1043 alert(__("No articles are selected."));
1044 return;
1045 }
1046
1047 for (i = 0; i < rows.length; i++) {
1048 toggleMark(rows[i], true, true);
1049 }
1050
1051 update_local_feedlist_counters();
1052
1053 if (rows.length > 0) {
1054
1055 var query = "backend.php?op=rpc&subop=markSelected&ids=" +
1056 param_escape(rows.toString()) + "&cmode=2";
1057
1058 query = query + "&afid=" + getActiveFeedId();
1059
1060 /* if (tagsAreDisplayed()) {
1061 query = query + "&omode=tl";
1062 } else {
1063 query = query + "&omode=flc";
1064 } */
1065
1066 query = query + "&omode=lc";
1067
1068 new Ajax.Request(query, {
1069 onComplete: function(transport) {
1070 all_counters_callback2(transport);
1071 } });
1072
1073 }
1074
1075 } catch (e) {
1076 exception_error("selectionToggleMarked", e);
1077 }
1078 }
1079
1080 function selectionTogglePublished(cdm_mode) {
1081 try {
1082
1083 var rows;
1084
1085 if (cdm_mode) {
1086 rows = cdmGetSelectedArticles();
1087 } else {
1088 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
1089 }
1090
1091 if (rows.length == 0) {
1092 alert(__("No articles are selected."));
1093 return;
1094 }
1095
1096 for (i = 0; i < rows.length; i++) {
1097 togglePub(rows[i], true, true);
1098 }
1099
1100 if (rows.length > 0) {
1101
1102 var query = "backend.php?op=rpc&subop=publishSelected&ids=" +
1103 param_escape(rows.toString()) + "&cmode=2";
1104
1105 query = query + "&afid=" + getActiveFeedId();
1106
1107 /* if (tagsAreDisplayed()) {
1108 query = query + "&omode=tl";
1109 } else {
1110 query = query + "&omode=flc";
1111 } */
1112
1113 query = query + "&omode=lc";
1114
1115 new Ajax.Request(query, {
1116 onComplete: function(transport) {
1117 all_counters_callback2(transport);
1118 } });
1119
1120 }
1121
1122 } catch (e) {
1123 exception_error("selectionToggleMarked", e);
1124 }
1125 }
1126
1127 function cdmGetSelectedArticles() {
1128 var sel_articles = new Array();
1129 var container = $("headlinesInnerContainer");
1130
1131 for (i = 0; i < container.childNodes.length; i++) {
1132 var child = container.childNodes[i];
1133
1134 if (child.id && child.id.match("RROW-") && child.className.match("Selected")) {
1135 var c_id = child.id.replace("RROW-", "");
1136 sel_articles.push(c_id);
1137 }
1138 }
1139
1140 return sel_articles;
1141 }
1142
1143 function cdmGetVisibleArticles() {
1144 var sel_articles = new Array();
1145 var container = $("headlinesInnerContainer");
1146
1147 if (!container) return sel_articles;
1148
1149 for (i = 0; i < container.childNodes.length; i++) {
1150 var child = container.childNodes[i];
1151
1152 if (child.id && child.id.match("RROW-")) {
1153 var c_id = child.id.replace("RROW-", "");
1154 sel_articles.push(c_id);
1155 }
1156 }
1157
1158 return sel_articles;
1159 }
1160
1161 function cdmGetUnreadArticles() {
1162 var sel_articles = new Array();
1163 var container = $("headlinesInnerContainer");
1164
1165 for (i = 0; i < container.childNodes.length; i++) {
1166 var child = container.childNodes[i];
1167
1168 if (child.id && child.id.match("RROW-") && child.className.match("Unread")) {
1169 var c_id = child.id.replace("RROW-", "");
1170 sel_articles.push(c_id);
1171 }
1172 }
1173
1174 return sel_articles;
1175 }
1176
1177
1178 // mode = all,none,unread
1179 function cdmSelectArticles(mode) {
1180 var container = $("headlinesInnerContainer");
1181
1182 for (i = 0; i < container.childNodes.length; i++) {
1183 var child = container.childNodes[i];
1184
1185 if (child.id && child.id.match("RROW-")) {
1186 var aid = child.id.replace("RROW-", "");
1187
1188 var cb = $("RCHK-" + aid);
1189
1190 if (mode == "all") {
1191 if (!child.className.match("Selected")) {
1192 child.className = child.className + "Selected";
1193 cb.checked = true;
1194 }
1195 } else if (mode == "unread") {
1196 if (child.className.match("Unread") && !child.className.match("Selected")) {
1197 child.className = child.className + "Selected";
1198 cb.checked = true;
1199 }
1200 } else {
1201 child.className = child.className.replace("Selected", "");
1202 cb.checked = false;
1203 }
1204 }
1205 }
1206 }
1207
1208 function catchupPage() {
1209
1210 var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
1211
1212 var str = __("Mark all visible articles in %s as read?");
1213
1214 str = str.replace("%s", fn);
1215
1216 if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
1217 return;
1218 }
1219
1220 if ($("headlinesList")) {
1221 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, 'Unread', true);
1222 selectionToggleUnread(false, false, 'viewCurrentFeed()', true);
1223 selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
1224 } else {
1225 cdmSelectArticles('all');
1226 selectionToggleUnread(true, false, 'viewCurrentFeed()', true)
1227 cdmSelectArticles('none');
1228 }
1229 }
1230
1231 function catchupSelection() {
1232
1233 try {
1234
1235 var rows;
1236
1237 if ($("headlinesList")) {
1238 rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
1239 } else {
1240 rows = cdmGetSelectedArticles();
1241 }
1242
1243 if (rows.length == 0) {
1244 alert(__("No articles are selected."));
1245 return;
1246 }
1247
1248
1249 var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
1250
1251 var str = __("Mark %d selected articles in %s as read?");
1252
1253 str = str.replace("%d", rows.length);
1254 str = str.replace("%s", fn);
1255
1256 if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
1257 return;
1258 }
1259
1260 if ($("headlinesList")) {
1261 selectionToggleUnread(false, false, 'viewCurrentFeed()', true);
1262 // selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
1263 } else {
1264 selectionToggleUnread(true, false, 'viewCurrentFeed()', true)
1265 // cdmSelectArticles('none');
1266 }
1267
1268 } catch (e) {
1269 exception_error("catchupSelection", e);
1270 }
1271 }
1272
1273 function editArticleTags(id, feed_id, cdm_enabled) {
1274 displayDlg('editArticleTags', id);
1275 }
1276
1277
1278 function tag_saved_callback(transport) {
1279 try {
1280 debug("in tag_saved_callback");
1281
1282 closeInfoBox();
1283 notify("");
1284
1285 if (tagsAreDisplayed()) {
1286 _reload_feedlist_after_view = true;
1287 }
1288
1289
1290 if (transport.responseXML) {
1291 var tags_str = transport.responseXML.getElementsByTagName("tags-str")[0];
1292
1293 if (tags_str) {
1294 var id = tags_str.getAttribute("id");
1295
1296 if (id) {
1297 var tags = $("ATSTR-" + id);
1298 if (tags) {
1299 tags.innerHTML = tags_str.firstChild.nodeValue;
1300 }
1301 }
1302 }
1303 }
1304
1305 } catch (e) {
1306 exception_error("tag_saved_callback", e);
1307 }
1308 }
1309
1310 function editTagsSave() {
1311
1312 notify_progress("Saving article tags...");
1313
1314 var form = document.forms["tag_edit_form"];
1315
1316 var query = Form.serialize("tag_edit_form");
1317
1318 query = "backend.php?op=rpc&subop=setArticleTags&" + query;
1319
1320 debug(query);
1321
1322 new Ajax.Request(query, {
1323 onComplete: function(transport) {
1324 tag_saved_callback(transport);
1325 } });
1326
1327 }
1328
1329 function editTagsInsert() {
1330 try {
1331
1332 var form = document.forms["tag_edit_form"];
1333
1334 var found_tags = form.found_tags;
1335 var tags_str = form.tags_str;
1336
1337 var tag = found_tags[found_tags.selectedIndex].value;
1338
1339 if (tags_str.value.length > 0 &&
1340 tags_str.value.lastIndexOf(", ") != tags_str.value.length - 2) {
1341
1342 tags_str.value = tags_str.value + ", ";
1343 }
1344
1345 tags_str.value = tags_str.value + tag + ", ";
1346
1347 found_tags.selectedIndex = 0;
1348
1349 } catch (e) {
1350 exception_error("editTagsInsert", e);
1351 }
1352 }
1353
1354 function cdmScrollViewport(where) {
1355 debug("cdmScrollViewport: " + where);
1356
1357 var ctr = $("headlinesInnerContainer");
1358
1359 if (!ctr) return;
1360
1361 if (where == "bottom") {
1362 ctr.scrollTop = ctr.scrollHeight;
1363 } else {
1364 ctr.scrollTop = where;
1365 }
1366 }
1367
1368 function cdmArticleIsBelowViewport(id) {
1369 try {
1370 var ctr = $("headlinesInnerContainer");
1371 var e = $("RROW-" + id);
1372
1373 if (!e || !ctr) return;
1374
1375 // article starts below viewport
1376
1377 if (ctr.scrollTop < e.offsetTop) {
1378 return true;
1379 } else {
1380 return false;
1381 }
1382
1383 } catch (e) {
1384 exception_error("cdmArticleIsVisible", e);
1385 }
1386 }
1387
1388 function cdmArticleIsAboveViewport(id) {
1389 try {
1390 var ctr = $("headlinesInnerContainer");
1391 var e = $("RROW-" + id);
1392
1393 if (!e || !ctr) return;
1394
1395 // article starts above viewport
1396
1397 if (ctr.scrollTop > e.offsetTop + e.offsetHeight) {
1398 return true;
1399 } else {
1400 return false;
1401 }
1402
1403 } catch (e) {
1404 exception_error("cdmArticleIsVisible", e);
1405 }
1406 }
1407
1408 function cdmScrollToArticleId(id) {
1409 try {
1410 var ctr = $("headlinesInnerContainer");
1411 var e = $("RROW-" + id);
1412
1413 if (!e || !ctr) return;
1414
1415 ctr.scrollTop = e.offsetTop;
1416
1417 } catch (e) {
1418 exception_error("cdmScrollToArticleId", e);
1419 }
1420 }
1421
1422 function cdmArticleIsActuallyVisible(id) {
1423 try {
1424 var ctr = $("headlinesInnerContainer");
1425 var e = $("RROW-" + id);
1426
1427 if (!e || !ctr) return;
1428
1429 // article fits in viewport OR article is longer than viewport and
1430 // its bottom is visible
1431
1432 if (ctr.scrollTop <= e.offsetTop && e.offsetTop + e.offsetHeight <=
1433 ctr.scrollTop + ctr.offsetHeight) {
1434
1435 return true;
1436
1437 } else if (e.offsetHeight > ctr.offsetHeight &&
1438 e.offsetTop + e.offsetHeight >= ctr.scrollTop &&
1439 e.offsetTop + e.offsetHeight <= ctr.scrollTop + ctr.offsetHeight) {
1440
1441 return true;
1442
1443 }
1444
1445 return false;
1446
1447 } catch (e) {
1448 exception_error("cdmArticleIsVisible", e);
1449 }
1450 }
1451
1452 function cdmWatchdog() {
1453
1454 try {
1455
1456 var ctr = $("headlinesInnerContainer");
1457
1458 if (!ctr) return;
1459
1460 var ids = new Array();
1461
1462 var e = ctr.firstChild;
1463
1464 while (e) {
1465 if (e.className && e.className == "cdmArticleUnread" && e.id &&
1466 e.id.match("RROW-")) {
1467
1468 // article fits in viewport OR article is longer than viewport and
1469 // its bottom is visible
1470
1471 if (ctr.scrollTop <= e.offsetTop && e.offsetTop + e.offsetHeight <=
1472 ctr.scrollTop + ctr.offsetHeight) {
1473
1474 // debug(e.id + " is visible " + e.offsetTop + "." +
1475 // (e.offsetTop + e.offsetHeight) + " vs " + ctr.scrollTop + "." +
1476 // (ctr.scrollTop + ctr.offsetHeight));
1477
1478 ids.push(e.id.replace("RROW-", ""));
1479
1480 } else if (e.offsetHeight > ctr.offsetHeight &&
1481 e.offsetTop + e.offsetHeight >= ctr.scrollTop &&
1482 e.offsetTop + e.offsetHeight <= ctr.scrollTop + ctr.offsetHeight) {
1483
1484 ids.push(e.id.replace("RROW-", ""));
1485
1486 }
1487
1488 // method 2: article bottom is visible and is in upper 1/2 of the viewport
1489
1490 /* if (e.offsetTop + e.offsetHeight >= ctr.scrollTop &&
1491 e.offsetTop + e.offsetHeight <= ctr.scrollTop + ctr.offsetHeight/2) {
1492
1493 ids.push(e.id.replace("RROW-", ""));
1494
1495 } */
1496
1497 }
1498
1499 e = e.nextSibling;
1500 }
1501
1502 debug("cdmWatchdog, ids= " + ids.toString());
1503
1504 if (ids.length > 0) {
1505
1506 for (var i = 0; i < ids.length; i++) {
1507 var e = $("RROW-" + ids[i]);
1508 if (e) {
1509 e.className = e.className.replace("Unread", "");
1510 }
1511 }
1512
1513 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
1514 param_escape(ids.toString()) + "&cmode=0";
1515
1516 new Ajax.Request(query, {
1517 onComplete: function(transport) {
1518 all_counters_callback2(transport);
1519 } });
1520
1521 }
1522
1523 _cdm_wd_timeout = window.setTimeout("cdmWatchdog()", 4000);
1524
1525 } catch (e) {
1526 exception_error("cdmWatchdog", e);
1527 }
1528
1529 }
1530
1531
1532 function cache_inject(id, article, param) {
1533 try {
1534 if (!cache_check_param(id, param)) {
1535 debug("cache_article: miss: " + id + " [p=" + param + "]");
1536
1537
1538 if (db) {
1539
1540 var date = new Date();
1541 var ts = Math.round(date.getTime() / 1000);
1542
1543 db.execute("INSERT INTO cache (id, article, param, added) VALUES (?, ?, ?, ?)",
1544 [id, article, param, ts]);
1545 } else {
1546
1547 var cache_obj = new Array();
1548
1549 cache_obj["id"] = id;
1550 cache_obj["data"] = article;
1551 cache_obj["param"] = param;
1552
1553 article_cache.push(cache_obj);
1554 }
1555
1556 } else {
1557 debug("cache_article: hit: " + id + " [p=" + param + "]");
1558 }
1559 } catch (e) {
1560 exception_error("cache_inject", e);
1561 }
1562 }
1563
1564 function cache_find(id) {
1565
1566 if (db) {
1567 var rs = db.execute("SELECT article FROM cache WHERE id = ?", [id]);
1568 var a = false;
1569
1570 if (rs.isValidRow()) {
1571 var a = rs.field(0);
1572 }
1573
1574 rs.close();
1575
1576 return a;
1577
1578 } else {
1579 for (var i = 0; i < article_cache.length; i++) {
1580 if (article_cache[i]["id"] == id) {
1581 return article_cache[i]["data"];
1582 }
1583 }
1584 }
1585 return false;
1586 }
1587
1588 function cache_find_param(id, param) {
1589
1590 if (db) {
1591 var rs = db.execute("SELECT article FROM cache WHERE id = ? AND param = ?",
1592 [id, param]);
1593 var a = false;
1594
1595 if (rs.isValidRow()) {
1596 a = rs.field(0);
1597 }
1598
1599 rs.close();
1600
1601 return a;
1602
1603 } else {
1604 for (var i = 0; i < article_cache.length; i++) {
1605 if (article_cache[i]["id"] == id && article_cache[i]["param"] == param) {
1606 return article_cache[i]["data"];
1607 }
1608 }
1609 }
1610 return false;
1611 }
1612
1613 function cache_check(id) {
1614
1615 if (db) {
1616 var rs = db.execute("SELECT COUNT(*) AS c FROM cache WHERE id = ?",
1617 [id]);
1618 var a = false;
1619
1620 if (rs.isValidRow()) {
1621 a = rs.field(0) != "0";
1622 }
1623
1624 rs.close();
1625
1626 return a;
1627
1628 } else {
1629 for (var i = 0; i < article_cache.length; i++) {
1630 if (article_cache[i]["id"] == id) {
1631 return true;
1632 }
1633 }
1634 }
1635 return false;
1636 }
1637
1638 function cache_check_param(id, param) {
1639
1640 if (db) {
1641 var rs = db.execute("SELECT COUNT(*) AS c FROM cache WHERE id = ? AND param = ?",
1642 [id, param]);
1643 var a = false;
1644
1645 if (rs.isValidRow()) {
1646 a = rs.field(0) != "0";
1647 }
1648
1649 rs.close();
1650
1651 return a;
1652
1653 } else {
1654 for (var i = 0; i < article_cache.length; i++) {
1655 if (article_cache[i]["id"] == id && article_cache[i]["param"] == param) {
1656 return true;
1657 }
1658 }
1659 }
1660 return false;
1661 }
1662
1663 function cache_expire() {
1664 if (db) {
1665 var date = new Date();
1666 var ts = Math.round(date.getTime() / 1000);
1667
1668 db.execute("DELETE FROM cache WHERE added < ? - 1800 AND id LIKE 'FEEDLIST'", [ts]);
1669 db.execute("DELETE FROM cache WHERE added < ? - 600 AND (id LIKE 'F:%' OR id LIKE 'C:%')", [ts]);
1670 db.execute("DELETE FROM cache WHERE added < ? - 86400", [ts]);
1671
1672
1673 } else {
1674 while (article_cache.length > 25) {
1675 article_cache.shift();
1676 }
1677 }
1678 }
1679
1680 function cache_empty() {
1681 article_cache = new Array();
1682 }
1683
1684 function cache_invalidate(id) {
1685 try {
1686
1687 if (db) {
1688 rs = db.execute("DELETE FROM cache WHERE id = ?", [id]);
1689 return rs.rowsAffected != 0;
1690 } else {
1691
1692 var i = 0
1693
1694 while (i < article_cache.length) {
1695 if (article_cache[i]["id"] == id) {
1696 debug("cache_invalidate: removed id " + id);
1697 article_cache.splice(i, 1);
1698 return true;
1699 }
1700 i++;
1701 }
1702 }
1703
1704 debug("cache_invalidate: id not found: " + id);
1705 return false;
1706 } catch (e) {
1707 exception_error("cache_invalidate", e);
1708 }
1709 }
1710
1711 function getActiveArticleId() {
1712 return active_post_id;
1713 }
1714
1715 function cdmClicked(id) {
1716 try {
1717 var elem = $("RROW-" + id);
1718
1719 if (elem) {
1720 var id = elem.id.replace("RROW-", "");
1721 active_post_id = id;
1722
1723 // cdmSelectArticles("none");
1724 toggleUnread(id, 0, true);
1725 // toggleSelected(id);
1726
1727 }
1728 } catch (e) {
1729 exception_error("cdmClicked", e);
1730 }
1731 }
1732
1733 function preload_article_callback(transport) {
1734 try {
1735 if (transport.responseXML) {
1736 var articles = transport.responseXML.getElementsByTagName("article");
1737
1738 for (var i = 0; i < articles.length; i++) {
1739 var id = articles[i].getAttribute("id");
1740 if (!cache_check(id)) {
1741 cache_inject(id, articles[i].firstChild.nodeValue);
1742 debug("preloaded article: " + id);
1743 }
1744 }
1745 }
1746 } catch (e) {
1747 exception_error("preload_article_callback", e);
1748 }
1749 }
1750
1751 function preloadArticleUnderPointer(id) {
1752 try {
1753 if (getInitParam("bw_limit") == "1") return;
1754
1755 if (post_under_pointer == id && !cache_check(id)) {
1756
1757 debug("trying to preload article " + id);
1758
1759 var neighbor_ids = getRelativePostIds(id, 1);
1760
1761 /* only request uncached articles */
1762
1763 var cids_to_request = Array();
1764
1765 for (var i = 0; i < neighbor_ids.length; i++) {
1766 if (!cache_check(neighbor_ids[i])) {
1767 cids_to_request.push(neighbor_ids[i]);
1768 }
1769 }
1770 debug("additional ids: " + cids_to_request.toString());
1771
1772 cids_to_request.push(id);
1773
1774 var query = "backend.php?op=rpc&subop=getArticles&ids=" +
1775 cids_to_request.toString();
1776 new Ajax.Request(query, {
1777 onComplete: function(transport) {
1778 preload_article_callback(transport);
1779 } });
1780 }
1781 } catch (e) {
1782 exception_error("preloadArticleUnderPointer", e);
1783 }
1784 }
1785
1786 function postMouseIn(id) {
1787 try {
1788 if (post_under_pointer != id) {
1789 post_under_pointer = id;
1790 if (!isCdmMode()) {
1791 window.setTimeout("preloadArticleUnderPointer(" + id + ")", 250);
1792 }
1793 }
1794
1795 } catch (e) {
1796 exception_error("postMouseIn", e);
1797 }
1798 }
1799
1800 function postMouseOut(id) {
1801 try {
1802 post_under_pointer = false;
1803 } catch (e) {
1804 exception_error("postMouseOut", e);
1805 }
1806 }
1807
1808 function headlines_scroll_handler() {
1809 try {
1810
1811 var e = $("headlinesInnerContainer");
1812
1813 // don't do infinite scrolling when Limit == All
1814
1815 var toolbar_form = document.forms["main_toolbar_form"];
1816
1817 var limit = toolbar_form.limit[toolbar_form.limit.selectedIndex];
1818 if (limit.value != 0) {
1819
1820 debug((e.scrollTop + e.offsetHeight) + " vs " + e.scrollHeight + " dis? " +
1821 _infscroll_disable);
1822
1823 if (e.scrollTop + e.offsetHeight > e.scrollHeight - 100) {
1824 if (!_infscroll_disable) {
1825 debug("more cowbell!");
1826 viewNextFeedPage();
1827 }
1828 }
1829 }
1830
1831 } catch (e) {
1832 exception_error("headlines_scroll_handler", e);
1833 }
1834 }
1835
1836 function catchupRelativeToArticle(below) {
1837
1838 try {
1839
1840
1841 if (!getActiveArticleId()) {
1842 alert(__("No article is selected."));
1843 return;
1844 }
1845
1846 var visible_ids;
1847
1848 if ($("headlinesList")) {
1849 visible_ids = getVisibleHeadlineIds();
1850 } else {
1851 visible_ids = cdmGetVisibleArticles();
1852 }
1853
1854 var ids_to_mark = new Array();
1855
1856 if (!below) {
1857 for (var i = 0; i < visible_ids.length; i++) {
1858 if (visible_ids[i] != getActiveArticleId()) {
1859 var e = $("RROW-" + visible_ids[i]);
1860
1861 if (e && e.className.match("Unread")) {
1862 ids_to_mark.push(visible_ids[i]);
1863 }
1864 } else {
1865 break;
1866 }
1867 }
1868 } else {
1869 for (var i = visible_ids.length-1; i >= 0; i--) {
1870 if (visible_ids[i] != getActiveArticleId()) {
1871 var e = $("RROW-" + visible_ids[i]);
1872
1873 if (e && e.className.match("Unread")) {
1874 ids_to_mark.push(visible_ids[i]);
1875 }
1876 } else {
1877 break;
1878 }
1879 }
1880 }
1881
1882 if (ids_to_mark.length == 0) {
1883 alert(__("No articles found to mark"));
1884 } else {
1885 var msg = __("Mark %d article(s) as read?").replace("%d", ids_to_mark.length);
1886
1887 if (confirm(msg)) {
1888
1889 for (var i = 0; i < ids_to_mark.length; i++) {
1890 var e = $("RROW-" + ids_to_mark[i]);
1891 e.className = e.className.replace("Unread", "");
1892 }
1893
1894 var query = "backend.php?op=rpc&subop=catchupSelected&ids=" +
1895 param_escape(ids_to_mark.toString()) + "&cmode=0";
1896
1897 new Ajax.Request(query, {
1898 onComplete: function(transport) {
1899 catchup_callback2(transport);
1900 } });
1901
1902 }
1903 }
1904
1905 } catch (e) {
1906 exception_error("catchupRelativeToArticle", e);
1907 }
1908 }
1909
1910 function cdmExpandArticle(a_id) {
1911 try {
1912 var id = 'CICD-' + a_id;
1913
1914 try {
1915 Element.hide("CEXC-" + a_id);
1916 } catch (e) { }
1917
1918 Effect.Appear(id, {duration : 0.5,
1919 beforeStart: function(effect) {
1920 var h_id = 'CICH-' + a_id;
1921 var h_elem = $(h_id);
1922 if (h_elem) { h_elem.style.display = "none"; }
1923
1924 toggleUnread(a_id, 0);
1925 }});
1926
1927
1928 } catch (e) {
1929 exception_error("appearBlockElementF", e);
1930 }
1931
1932 }
1933
1934 function fixHeadlinesOrder(ids) {
1935 try {
1936 for (var i = 0; i < ids.length; i++) {
1937 var e = $("RROW-" + ids[i]);
1938
1939 if (e) {
1940 if (i % 2 == 0) {
1941 e.className = e.className.replace("even", "odd");
1942 } else {
1943 e.className = e.className.replace("odd", "even");
1944 }
1945 }
1946 }
1947 } catch (e) {
1948 exception_error("fixHeadlinesOrder", e);
1949 }
1950 }
1951
1952 function hideReadHeadlines() {
1953 try {
1954
1955 var ids = false;
1956 var vis_ids = new Array();
1957
1958 if ($("headlinesList")) {
1959 ids = getVisibleHeadlineIds();
1960 } else {
1961 ids = cdmGetVisibleArticles();
1962 }
1963
1964 var read_headlines_visible = true;
1965
1966 for (var i = 0; i < ids.length; i++) {
1967 var row = $("RROW-" + ids[i]);
1968
1969 if (row && row.className) {
1970 if (read_headlines_visible) {
1971 if (row.className.match("Unread") || row.className.match("Selected")) {
1972 Element.show(row);
1973 vis_ids.push(ids[i]);
1974 } else {
1975 //Effect.Fade(row, {duration : 0.3});
1976 Element.hide(row);
1977 }
1978 } else {
1979 Element.show(row);
1980 vis_ids.push(ids[i]);
1981 }
1982 }
1983 }
1984
1985 fixHeadlinesOrder(vis_ids);
1986
1987 read_headlines_visible = !read_headlines_visible;
1988
1989 } catch (e) {
1990 exception_error("hideReadHeadlines", e);
1991 }
1992 }
1993
1994 function invertHeadlineSelection() {
1995 try {
1996 var rows = new Array();
1997 var r = false;
1998
1999 if (!isCdmMode()) {
2000 r = document.getElementsByTagName("TR");
2001 } else {
2002 r = document.getElementsByTagName("DIV");
2003 }
2004
2005 for (var i = 0; i < r.length; i++) {
2006 if (r[i].id && r[i].id.match("RROW-")) {
2007 rows.push(r[i]);
2008 }
2009 }
2010
2011 for (var i = 0; i < rows.length; i++) {
2012 var nc = rows[i].className;
2013 var id = rows[i].id.replace("RROW-", "");
2014 var cb = $("RCHK-" + id);
2015
2016 if (!rows[i].className.match("Selected")) {
2017 nc = nc + "Selected";
2018 cb.checked = true;
2019 } else {
2020 nc = nc.replace("Selected", "");
2021 cb.checked = false;
2022 }
2023
2024 rows[i].className = nc;
2025
2026 }
2027
2028 } catch (e) {
2029 exception_error("invertHeadlineSelection", e);
2030 }
2031 }
2032
2033 function getArticleUnderPointer() {
2034 return post_under_pointer;
2035 }
2036
2037 function zoomToArticle(id) {
2038 try {
2039 var w = window.open("backend.php?op=view&mode=zoom&id=" + param_escape(id),
2040 "ttrss_zoom_" + id,
2041 "status=0,toolbar=0,location=0,width=450,height=300,scrollbars=1,menubar=0");
2042
2043 } catch (e) {
2044 exception_error("zoomToArticle", e);
2045 }
2046 }
2047
2048 function showOriginalArticleInline(id) {
2049 try {
2050
2051 var query = "backend.php?op=rpc&subop=getArticleLink&id=" + id;
2052
2053 notify_progress("Loading, please wait...", true);
2054
2055 new Ajax.Request(query, {
2056 onComplete: function(transport) {
2057
2058 if (transport.responseXML) {
2059
2060 var link = transport.responseXML.getElementsByTagName("link")[0];
2061 var id = transport.responseXML.getElementsByTagName("id")[0];
2062
2063 notify("");
2064
2065 if (link && id) {
2066 link = link.firstChild.nodeValue;
2067
2068 var ci = $("content-insert");
2069
2070 var tmp = "<iframe id=\"inline_orig_article\" width=\""+ci.offsetWidth+"\" height=\""+ci.offsetHeight+"\" style=\"border-width : 0px;\" src=\""+link+"\"></iframe>";
2071
2072 render_article(tmp);
2073
2074 }
2075 }
2076 } });
2077
2078 } catch (e) {
2079 exception_error("showOriginalArticleInline", e);
2080 }
2081 }
2082
2083
2084 function scrollArticle(offset) {
2085 try {
2086 if (!isCdmMode()) {
2087 var ci = $("content-insert");
2088 if (ci) {
2089 ci.scrollTop += offset;
2090 }
2091 } else {
2092 var hi = $("headlinesInnerContainer");
2093 if (hi) {
2094 hi.scrollTop += offset;
2095 }
2096
2097 }
2098 } catch (e) {
2099 exception_error("scrollArticle", e);
2100 }
2101 }
2102
2103 function show_labels_in_headlines(transport) {
2104 try {
2105 if (transport.responseXML) {
2106 var info = transport.responseXML.getElementsByTagName("info-for-headlines")[0];
2107
2108 var elems = info.getElementsByTagName("entry");
2109
2110 for (var l = 0; l < elems.length; l++) {
2111 var e_id = elems[l].getAttribute("id");
2112
2113 if (e_id) {
2114
2115 var ctr = $("HLLCTR-" + e_id);
2116
2117 if (ctr) {
2118 ctr.innerHTML = elems[l].firstChild.nodeValue;
2119 }
2120 }
2121
2122 }
2123
2124 }
2125 } catch (e) {
2126 exception_error("show_labels_in_headlines", e);
2127
2128 }
2129 }
2130
2131 function toggleHeadlineActions() {
2132 try {
2133 var e = $("headlineActionsBody");
2134 var p = $("headlineActionsDrop");
2135
2136 if (!Element.visible(e)) {
2137 Element.show(e);
2138 } else {
2139 Element.hide(e);
2140 }
2141
2142 e.scrollTop = 0;
2143 e.style.left = (p.offsetLeft + 1) + "px";
2144 e.style.top = (p.offsetTop + p.offsetHeight + 2) + "px";
2145
2146 } catch (e) {
2147 exception_error("toggleHeadlineActions", e);
2148 }
2149 }