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