1 var article_cache = new Array();
3 var _active_article_id = 0;
5 var vgroup_last_feed = false;
6 var post_under_pointer = false;
8 var last_requested_article = false;
10 var catchup_id_batch = [];
11 var catchup_timeout_id = false;
13 var cids_requested = [];
14 var loaded_article_ids = [];
15 var _last_headlines_update = 0;
16 var _headlines_scroll_offset = 0;
17 var current_first_id = 0;
19 var _catchup_request_sent = false;
21 var has_storage = 'sessionStorage' in window && window['sessionStorage'] !== null;
23 function headlines_callback2(transport, offset, background, infscroll_req) {
25 handle_rpc_json(transport);
27 console.log("headlines_callback2 [offset=" + offset + "] B:" + background + " I:" + infscroll_req);
35 reply = JSON.parse(transport.responseText);
42 is_cat = reply['headlines']['is_cat'];
43 feed_id = reply['headlines']['id'];
46 var content = reply['headlines']['content'];
48 content = content + "<div id='headlines-spacer'></div>";
52 if (feed_id != -7 && (feed_id != getActiveFeedId() || is_cat != activeFeedIsCat()))
55 /* dijit.getEnclosingWidget(
56 document.forms["main_toolbar_form"].update).attr('disabled',
57 is_cat || feed_id <= 0); */
60 if (infscroll_req == false) {
61 $("headlines-frame").scrollTop = 0;
63 $("floatingTitle").style.visibility = "hidden";
64 $("floatingTitle").setAttribute("data-article-id", 0);
65 $("floatingTitle").innerHTML = "";
69 $("headlines-frame").removeClassName("cdm");
70 $("headlines-frame").removeClassName("normal");
72 $("headlines-frame").addClassName(isCdmMode() ? "cdm" : "normal");
74 var headlines_count = reply['headlines-info']['count'];
76 vgroup_last_feed = reply['headlines-info']['vgroup_last_feed'];
78 if (parseInt(headlines_count) < 30) {
79 _infscroll_disable = 1;
81 _infscroll_disable = 0;
84 current_first_id = reply['headlines']['first_id'];
85 var counters = reply['counters'];
86 var articles = reply['articles'];
87 //var runtime_info = reply['runtime-info'];
89 if (infscroll_req == false) {
90 loaded_article_ids = [];
92 dojo.html.set($("headlines-toolbar"),
93 reply['headlines']['toolbar'],
94 {parseContent: true});
96 /*dojo.html.set($("headlines-frame"),
97 reply['headlines']['content'],
98 {parseContent: true});
100 $$("#headlines-frame div[id*='RROW']").each(function(row) {
101 loaded_article_ids.push(row.id);
104 $("headlines-frame").innerHTML = '';
106 var tmp = new Element("div");
107 tmp.innerHTML = reply['headlines']['content'];
108 dojo.parser.parse(tmp);
110 while (tmp.hasChildNodes()) {
111 var row = tmp.removeChild(tmp.firstChild);
113 if (loaded_article_ids.indexOf(row.id) == -1 || row.hasClassName("cdmFeedTitle")) {
114 dijit.byId("headlines-frame").domNode.appendChild(row);
116 loaded_article_ids.push(row.id);
120 var hsp = $("headlines-spacer");
121 if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
122 dijit.byId('headlines-frame').domNode.appendChild(hsp);
126 if (_infscroll_disable)
127 hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
128 __("Click to open next unread feed.") + "</a>";
131 $("feed_title").innerHTML += "<span id='cancel_search'>" +
132 " (<a href='#' onclick='cancelSearch()'>" + __("Cancel search") + "</a>)" +
138 if (headlines_count > 0 && feed_id == getActiveFeedId() && is_cat == activeFeedIsCat()) {
139 console.log("adding some more headlines: " + headlines_count);
141 var c = dijit.byId("headlines-frame");
142 var ids = getSelectedArticleIds2();
144 var hsp = $("headlines-spacer");
147 c.domNode.removeChild(hsp);
149 var tmp = new Element("div");
150 tmp.innerHTML = reply['headlines']['content'];
151 dojo.parser.parse(tmp);
155 while (tmp.hasChildNodes()) {
156 var row = tmp.removeChild(tmp.firstChild);
158 if (loaded_article_ids.indexOf(row.id) == -1 || row.hasClassName("cdmFeedTitle")) {
159 dijit.byId("headlines-frame").domNode.appendChild(row);
161 loaded_article_ids.push(row.id);
163 if (!isCdmMode() || row.hasClassName("cdmFeedTitle")) {
165 } else if (isCdmMode()) {
166 var titleWrap = $$("#" + row.id + " .titleWrap")[0];
169 new_rows.push(titleWrap);
175 if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
176 c.domNode.appendChild(hsp);
178 if (headlines_count < 30) _infscroll_disable = true;
180 console.log("restore selected ids: " + ids);
182 for (var i = 0; i < ids.length; i++) {
183 markHeadline(ids[i]);
186 initHeadlinesMenu(new_rows);
188 if (_infscroll_disable) {
189 hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
190 __("Click to open next unread feed.") + "</a>";
194 console.log("no new headlines received");
196 var first_id_changed = reply['headlines']['first_id_changed'];
197 console.log("first id changed:" + first_id_changed);
199 var hsp = $("headlines-spacer");
202 if (first_id_changed) {
203 hsp.innerHTML = "<a href='#' onclick='viewCurrentFeed()'>" +
204 __("New articles found, reload feed to continue.") + "</a>";
206 hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
207 __("Click to open next unread feed.") + "</a>";
216 for (var i = 0; i < articles.length; i++) {
217 var a_id = articles[i]['id'];
218 cache_set("article:" + a_id, articles[i]['content']);
221 console.log("no cached articles received");
225 parse_counters(counters);
227 request_counters(true);
230 console.error("Invalid object received: " + transport.responseText);
231 dijit.byId("headlines-frame").attr('content', "<div class='whiteBox'>" +
232 __('Could not update headlines (invalid object received - see error console for details)') +
236 _infscroll_request_sent = 0;
237 _last_headlines_update = new Date().getTime();
239 unpackVisibleHeadlines();
241 // if we have some more space in the buffer, why not try to fill it
243 if (!_infscroll_disable && $("headlines-spacer") &&
244 $("headlines-spacer").offsetTop < $("headlines-frame").offsetHeight) {
246 window.setTimeout(function() {
254 exception_error("headlines_callback2", e, transport);
258 function render_article(article) {
260 cleanup_memory("content-insert");
262 dijit.byId("headlines-wrap-inner").addChild(
263 dijit.byId("content-insert"));
265 var c = dijit.byId("content-insert");
268 c.domNode.scrollTop = 0;
271 c.attr('content', article);
272 PluginHost.run(PluginHost.HOOK_ARTICLE_RENDERED, c.domNode);
274 correctHeadlinesOffset(getActiveArticleId());
281 exception_error("render_article", e);
285 function showArticleInHeadlines(id, noexpand) {
288 var row = $("RROW-" + id);
292 row.removeClassName("Unread");
294 row.addClassName("active");
296 selectArticles('none');
301 exception_error("showArticleInHeadlines", e);
305 function article_callback2(transport, id) {
307 console.log("article_callback2 " + id);
309 handle_rpc_json(transport);
314 reply = JSON.parse(transport.responseText);
321 reply.each(function(article) {
322 if (getActiveArticleId() == article['id']) {
323 render_article(article['content']);
325 cids_requested.remove(article['id']);
327 cache_set("article:" + article['id'], article['content']);
330 // if (id != last_requested_article) {
331 // console.log("requested article id is out of sequence, aborting");
336 console.error("Invalid object received: " + transport.responseText);
338 render_article("<div class='whiteBox'>" +
339 __('Could not display article (invalid object received - see error console for details)') + "</div>");
342 var unread_in_buffer = $$("#headlines-frame > div[id*=RROW][class*=Unread]").length
343 request_counters(unread_in_buffer == 0);
347 exception_error("article_callback2", e, transport);
351 function view(id, activefeed, noexpand) {
353 var oldrow = $("RROW-" + getActiveArticleId());
354 if (oldrow) oldrow.removeClassName("active");
356 var crow = $("RROW-" + id);
360 setActiveArticleId(id);
361 showArticleInHeadlines(id, noexpand);
365 console.log("loading article: " + id);
367 var cached_article = cache_get("article:" + id);
369 console.log("cache check result: " + (cached_article != false));
371 var query = "?op=article&method=view&id=" + param_escape(id);
373 var neighbor_ids = getRelativePostIds(id);
375 /* only request uncached articles */
377 var cids_to_request = [];
379 for (var i = 0; i < neighbor_ids.length; i++) {
380 if (cids_requested.indexOf(neighbor_ids[i]) == -1)
381 if (!cache_get("article:" + neighbor_ids[i])) {
382 cids_to_request.push(neighbor_ids[i]);
383 cids_requested.push(neighbor_ids[i]);
387 console.log("additional ids: " + cids_to_request.toString());
389 query = query + "&cids=" + cids_to_request.toString();
391 var article_is_unread = crow.hasClassName("Unread");
393 setActiveArticleId(id);
394 showArticleInHeadlines(id);
396 if (cached_article && article_is_unread) {
398 query = query + "&mode=prefetch";
400 render_article(cached_article);
402 } else if (cached_article) {
404 query = query + "&mode=prefetch_old";
405 render_article(cached_article);
407 // if we don't need to request any relative ids, we might as well skip
408 // the server roundtrip altogether
409 if (cids_to_request.length == 0) {
414 last_requested_article = id;
418 if (article_is_unread) {
419 decrementFeedCounter(getActiveFeedId(), activeFeedIsCat());
422 new Ajax.Request("backend.php", {
424 onComplete: function(transport) {
425 article_callback2(transport, id);
431 exception_error("view", e);
435 function toggleMark(id, client_only) {
437 var query = "?op=rpc&id=" + id + "&method=mark";
439 var row = $("RROW-" + id);
444 var row_imgs = row.getElementsByClassName("markedPic");
446 for (var i = 0; i < row_imgs.length; i++)
447 imgs.push(row_imgs[i]);
449 var ft = $("floatingTitle");
451 if (ft && ft.getAttribute("data-article-id") == id) {
452 var fte = ft.getElementsByClassName("markedPic");
454 for (var i = 0; i < fte.length; i++)
458 for (i = 0; i < imgs.length; i++) {
461 if (!row.hasClassName("marked")) {
462 img.src = img.src.replace("mark_unset", "mark_set");
463 img.alt = __("Unstar article");
464 query = query + "&mark=1";
466 img.src = img.src.replace("mark_set", "mark_unset");
467 img.alt = __("Star article");
468 query = query + "&mark=0";
472 row.toggleClassName("marked");
475 new Ajax.Request("backend.php", {
477 onComplete: function(transport) {
478 handle_rpc_json(transport);
483 exception_error("toggleMark", e);
487 function togglePub(id, client_only, no_effects, note) {
489 var query = "?op=rpc&id=" + id + "&method=publ";
491 if (note != undefined) {
492 query = query + "¬e=" + param_escape(note);
494 query = query + "¬e=undefined";
497 var row = $("RROW-" + id);
502 var row_imgs = row.getElementsByClassName("pubPic");
504 for (var i = 0; i < row_imgs.length; i++)
505 imgs.push(row_imgs[i]);
507 var ft = $("floatingTitle");
509 if (ft && ft.getAttribute("data-article-id") == id) {
510 var fte = ft.getElementsByClassName("pubPic");
512 for (var i = 0; i < fte.length; i++)
516 for (i = 0; i < imgs.length; i++) {
519 if (!row.hasClassName("published") || note != undefined) {
520 img.src = img.src.replace("pub_unset", "pub_set");
521 img.alt = __("Unpublish article");
522 query = query + "&pub=1";
524 img.src = img.src.replace("pub_set", "pub_unset");
525 img.alt = __("Publish article");
526 query = query + "&pub=0";
530 if (note != undefined)
531 row.addClassName("published");
533 row.toggleClassName("published");
536 new Ajax.Request("backend.php", {
538 onComplete: function(transport) {
539 handle_rpc_json(transport);
544 exception_error("togglePub", e);
548 function moveToPost(mode, noscroll, noexpand) {
552 var rows = getLoadedArticleIds();
557 if (!$('RROW-' + getActiveArticleId())) {
558 setActiveArticleId(0);
561 if (!getActiveArticleId()) {
563 prev_id = rows[rows.length-1]
565 for (var i = 0; i < rows.length; i++) {
566 if (rows[i] == getActiveArticleId()) {
568 // Account for adjacent identical article ids.
569 if (i > 0) prev_id = rows[i-1];
571 for (var j = i+1; j < rows.length; j++) {
572 if (rows[j] != getActiveArticleId()) {
582 console.log("cur: " + getActiveArticleId() + " next: " + next_id);
584 if (mode == "next") {
585 if (next_id || getActiveArticleId()) {
588 var article = $("RROW-" + getActiveArticleId());
589 var ctr = $("headlines-frame");
591 if (!noscroll && article && article.offsetTop + article.offsetHeight >
592 ctr.scrollTop + ctr.offsetHeight) {
594 scrollArticle(ctr.offsetHeight/4);
596 } else if (next_id) {
597 cdmExpandArticle(next_id, noexpand);
598 cdmScrollToArticleId(next_id, true);
601 } else if (next_id) {
602 correctHeadlinesOffset(next_id);
603 view(next_id, getActiveFeedId(), noexpand);
608 if (mode == "prev") {
609 if (prev_id || getActiveArticleId()) {
612 var article = $("RROW-" + getActiveArticleId());
613 var prev_article = $("RROW-" + prev_id);
614 var ctr = $("headlines-frame");
616 if (!getInitParam("cdm_expanded")) {
618 if (!noscroll && article && article.offsetTop < ctr.scrollTop) {
619 scrollArticle(-ctr.offsetHeight/4);
621 cdmExpandArticle(prev_id, noexpand);
622 cdmScrollToArticleId(prev_id, true);
626 if (!noscroll && article && article.offsetTop < ctr.scrollTop) {
627 scrollArticle(-ctr.offsetHeight/3);
628 } else if (!noscroll && prev_article &&
629 prev_article.offsetTop < ctr.scrollTop) {
630 cdmExpandArticle(prev_id, noexpand);
631 scrollArticle(-ctr.offsetHeight/4);
632 } else if (prev_id) {
633 cdmExpandArticle(prev_id, noexpand);
634 cdmScrollToArticleId(prev_id, noscroll);
638 } else if (prev_id) {
639 correctHeadlinesOffset(prev_id);
640 view(prev_id, getActiveFeedId(), noexpand);
646 exception_error("moveToPost", e);
650 function toggleSelected(id, force_on) {
652 var row = $("RROW-" + id);
655 var cb = dijit.getEnclosingWidget(
656 row.getElementsByClassName("rchk")[0]);
658 if (row.hasClassName('Selected') && !force_on) {
659 row.removeClassName('Selected');
660 if (cb) cb.attr("checked", false);
662 row.addClassName('Selected');
663 if (cb) cb.attr("checked", true);
667 updateSelectedPrompt();
669 exception_error("toggleSelected", e);
673 function updateSelectedPrompt() {
675 var count = getSelectedArticleIds2().size();
676 var elem = $("selected_prompt");
679 elem.innerHTML = ngettext("%d article selected",
680 "%d articles selected", count).replace("%d", count);
689 exception_error("updateSelectedPrompt", e);
693 function toggleUnread(id, cmode, effect) {
696 var row = $("RROW-" + id);
698 var tmpClassName = row.className;
700 if (cmode == undefined || cmode == 2) {
701 if (row.hasClassName("Unread")) {
702 row.removeClassName("Unread");
705 row.addClassName("Unread");
708 } else if (cmode == 0) {
710 row.removeClassName("Unread");
712 } else if (cmode == 1) {
713 row.addClassName("Unread");
716 if (cmode == undefined) cmode = 2;
718 var query = "?op=rpc&method=catchupSelected" +
719 "&cmode=" + param_escape(cmode) + "&ids=" + param_escape(id);
721 // notify_progress("Loading, please wait...");
723 if (tmpClassName != row.className) {
724 new Ajax.Request("backend.php", {
726 onComplete: function (transport) {
727 handle_rpc_json(transport);
735 exception_error("toggleUnread", e);
739 function selectionRemoveLabel(id, ids) {
742 if (!ids) ids = getSelectedArticleIds2();
744 if (ids.length == 0) {
745 alert(__("No articles are selected."));
749 var query = "?op=article&method=removeFromLabel&ids=" +
750 param_escape(ids.toString()) + "&lid=" + param_escape(id);
754 new Ajax.Request("backend.php", {
756 onComplete: function(transport) {
757 handle_rpc_json(transport);
758 show_labels_in_headlines(transport);
762 exception_error("selectionAssignLabel", e);
767 function selectionAssignLabel(id, ids) {
770 if (!ids) ids = getSelectedArticleIds2();
772 if (ids.length == 0) {
773 alert(__("No articles are selected."));
777 var query = "?op=article&method=assignToLabel&ids=" +
778 param_escape(ids.toString()) + "&lid=" + param_escape(id);
782 new Ajax.Request("backend.php", {
784 onComplete: function(transport) {
785 handle_rpc_json(transport);
786 show_labels_in_headlines(transport);
790 exception_error("selectionAssignLabel", e);
795 function selectionToggleUnread(set_state, callback, no_error, ids) {
797 var rows = ids ? ids : getSelectedArticleIds2();
799 if (rows.length == 0 && !no_error) {
800 alert(__("No articles are selected."));
804 for (var i = 0; i < rows.length; i++) {
805 var row = $("RROW-" + rows[i]);
807 if (set_state == undefined) {
808 if (row.hasClassName("Unread")) {
809 row.removeClassName("Unread");
811 row.addClassName("Unread");
815 if (set_state == false) {
816 row.removeClassName("Unread");
819 if (set_state == true) {
820 row.addClassName("Unread");
825 updateFloatingTitle(true);
827 if (rows.length > 0) {
831 if (set_state == undefined) {
833 } else if (set_state == true) {
835 } else if (set_state == false) {
839 var query = "?op=rpc&method=catchupSelected" +
840 "&cmode=" + cmode + "&ids=" + param_escape(rows.toString());
842 notify_progress("Loading, please wait...");
844 new Ajax.Request("backend.php", {
846 onComplete: function(transport) {
847 handle_rpc_json(transport);
848 if (callback) callback(transport);
854 exception_error("selectionToggleUnread", e);
859 function selectionToggleMarked(sel_state, callback, no_error, ids) {
862 var rows = ids ? ids : getSelectedArticleIds2();
864 if (rows.length == 0 && !no_error) {
865 alert(__("No articles are selected."));
869 for (var i = 0; i < rows.length; i++) {
870 toggleMark(rows[i], true, true);
873 if (rows.length > 0) {
875 var query = "?op=rpc&method=markSelected&ids=" +
876 param_escape(rows.toString()) + "&cmode=2";
878 new Ajax.Request("backend.php", {
880 onComplete: function(transport) {
881 handle_rpc_json(transport);
882 if (callback) callback(transport);
888 exception_error("selectionToggleMarked", e);
893 function selectionTogglePublished(sel_state, callback, no_error, ids) {
896 var rows = ids ? ids : getSelectedArticleIds2();
898 if (rows.length == 0 && !no_error) {
899 alert(__("No articles are selected."));
903 for (var i = 0; i < rows.length; i++) {
904 togglePub(rows[i], true, true);
907 if (rows.length > 0) {
909 var query = "?op=rpc&method=publishSelected&ids=" +
910 param_escape(rows.toString()) + "&cmode=2";
912 new Ajax.Request("backend.php", {
914 onComplete: function(transport) {
915 handle_rpc_json(transport);
921 exception_error("selectionToggleMarked", e);
925 function getSelectedArticleIds2() {
929 $$("#headlines-frame > div[id*=RROW][class*=Selected]").each(
931 rv.push(child.getAttribute("data-article-id"));
937 function getLoadedArticleIds() {
940 var children = $$("#headlines-frame > div[id*=RROW-]");
942 children.each(function(child) {
943 if (Element.visible(child)) {
944 rv.push(child.getAttribute("data-article-id"));
952 // mode = all,none,unread,invert,marked,published
953 function selectArticles(mode, query) {
956 if (!query) query = "#headlines-frame > div[id*=RROW]";
958 var children = $$(query);
960 children.each(function(child) {
961 var id = child.getAttribute("data-article-id");
963 var cb = dijit.getEnclosingWidget(
964 child.getElementsByClassName("rchk")[0]);
967 child.addClassName("Selected");
968 if (cb) cb.attr("checked", true);
969 } else if (mode == "unread") {
970 if (child.hasClassName("Unread")) {
971 child.addClassName("Selected");
972 if (cb) cb.attr("checked", true);
974 child.removeClassName("Selected");
975 if (cb) cb.attr("checked", false);
977 } else if (mode == "marked") {
978 if (child.hasClassName("marked")) {
979 child.addClassName("Selected");
980 if (cb) cb.attr("checked", true);
982 child.removeClassName("Selected");
983 if (cb) cb.attr("checked", false);
985 } else if (mode == "published") {
986 if (child.hasClassName("published")) {
987 child.addClassName("Selected");
988 if (cb) cb.attr("checked", true);
990 child.removeClassName("Selected");
991 if (cb) cb.attr("checked", false);
994 } else if (mode == "invert") {
995 if (child.hasClassName("Selected")) {
996 child.removeClassName("Selected");
997 if (cb) cb.attr("checked", false);
999 child.addClassName("Selected");
1000 if (cb) cb.attr("checked", true);
1004 child.removeClassName("Selected");
1005 if (cb) cb.attr("checked", false);
1009 updateSelectedPrompt();
1012 exception_error("selectArticles", e);
1016 function deleteSelection() {
1020 var rows = getSelectedArticleIds2();
1022 if (rows.length == 0) {
1023 alert(__("No articles are selected."));
1027 var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
1030 if (getActiveFeedId() != 0) {
1031 str = ngettext("Delete %d selected article in %s?", "Delete %d selected articles in %s?" , rows.length);
1033 str = ngettext("Delete %d selected article?", "Delete %d selected articles?", rows.length);
1036 str = str.replace("%d", rows.length);
1037 str = str.replace("%s", fn);
1039 if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
1043 query = "?op=rpc&method=delete&ids=" + param_escape(rows);
1047 new Ajax.Request("backend.php", {
1049 onComplete: function(transport) {
1050 handle_rpc_json(transport);
1055 exception_error("deleteSelection", e);
1059 function archiveSelection() {
1063 var rows = getSelectedArticleIds2();
1065 if (rows.length == 0) {
1066 alert(__("No articles are selected."));
1070 var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
1074 if (getActiveFeedId() != 0) {
1075 str = ngettext("Archive %d selected article in %s?", "Archive %d selected articles in %s?", rows.length);
1078 str = ngettext("Move %d archived article back?", "Move %d archived articles back?", rows.length);
1080 str += " " + __("Please note that unstarred articles might get purged on next feed update.");
1085 str = str.replace("%d", rows.length);
1086 str = str.replace("%s", fn);
1088 if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
1092 query = "?op=rpc&method="+op+"&ids=" + param_escape(rows);
1096 for (var i = 0; i < rows.length; i++) {
1097 cache_delete("article:" + rows[i]);
1100 new Ajax.Request("backend.php", {
1102 onComplete: function(transport) {
1103 handle_rpc_json(transport);
1108 exception_error("archiveSelection", e);
1112 function catchupSelection() {
1116 var rows = getSelectedArticleIds2();
1118 if (rows.length == 0) {
1119 alert(__("No articles are selected."));
1123 var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
1125 var str = ngettext("Mark %d selected article in %s as read?", "Mark %d selected articles in %s as read?", rows.length);
1127 str = str.replace("%d", rows.length);
1128 str = str.replace("%s", fn);
1130 if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
1134 selectionToggleUnread(false, 'viewCurrentFeed()', true);
1137 exception_error("catchupSelection", e);
1141 function editArticleTags(id) {
1142 var query = "backend.php?op=article&method=editArticleTags¶m=" + param_escape(id);
1144 if (dijit.byId("editTagsDlg"))
1145 dijit.byId("editTagsDlg").destroyRecursive();
1147 dialog = new dijit.Dialog({
1149 title: __("Edit article Tags"),
1150 style: "width: 600px",
1151 execute: function() {
1152 if (this.validate()) {
1153 var query = dojo.objectToQuery(this.attr('value'));
1155 notify_progress("Saving article tags...", true);
1157 new Ajax.Request("backend.php", {
1159 onComplete: function(transport) {
1164 var data = JSON.parse(transport.responseText);
1171 var tags = $("ATSTR-" + id);
1172 var tooltip = dijit.byId("ATSTRTIP-" + id);
1174 if (tags) tags.innerHTML = data.content;
1175 if (tooltip) tooltip.attr('label', data.content_full);
1178 exception_error("editArticleTags/inner", e);
1187 var tmph = dojo.connect(dialog, 'onLoad', function() {
1188 dojo.disconnect(tmph);
1190 new Ajax.Autocompleter('tags_str', 'tags_choices',
1191 "backend.php?op=article&method=completeTags",
1192 { tokens: ',', paramName: "search" });
1199 function cdmScrollToArticleId(id, force) {
1201 var ctr = $("headlines-frame");
1202 var e = $("RROW-" + id);
1204 if (!e || !ctr) return;
1206 if (force || e.offsetTop+e.offsetHeight > (ctr.scrollTop+ctr.offsetHeight) ||
1207 e.offsetTop < ctr.scrollTop) {
1209 // expanded cdm has a 4px margin now
1210 ctr.scrollTop = parseInt(e.offsetTop) - 4;
1214 exception_error("cdmScrollToArticleId", e);
1218 function setActiveArticleId(id) {
1219 console.log("setActiveArticleId:" + id);
1221 _active_article_id = id;
1222 PluginHost.run(PluginHost.HOOK_ARTICLE_SET_ACTIVE, _active_article_id);
1225 function getActiveArticleId() {
1226 return _active_article_id;
1229 function postMouseIn(e, id) {
1230 post_under_pointer = id;
1233 function postMouseOut(id) {
1234 post_under_pointer = false;
1237 function unpackVisibleHeadlines() {
1239 if (!isCdmMode() || !getInitParam("cdm_expanded")) return;
1241 $$("#headlines-frame span.cencw[id]").each(
1243 var row = $("RROW-" + child.id.replace("CENCW-", ""));
1245 if (row && row.offsetTop <= $("headlines-frame").scrollTop +
1246 $("headlines-frame").offsetHeight) {
1248 //console.log("unpacking: " + child.id);
1250 child.innerHTML = htmlspecialchars_decode(child.innerHTML);
1251 child.removeAttribute('id');
1253 PluginHost.run(PluginHost.HOOK_ARTICLE_RENDERED_CDM, row);
1255 Element.show(child);
1261 exception_error("unpackVisibleHeadlines", e);
1265 function headlines_scroll_handler(e) {
1268 // rate-limit in case of smooth scrolling and similar abominations
1269 if (Math.max(e.scrollTop, _headlines_scroll_offset) - Math.min(e.scrollTop, _headlines_scroll_offset) < 25) {
1273 _headlines_scroll_offset = e.scrollTop;
1275 var hsp = $("headlines-spacer");
1277 unpackVisibleHeadlines();
1279 // set topmost child in the buffer as active
1280 if (isCdmMode() && getInitParam("cdm_auto_catchup") == 1 &&
1281 getSelectedArticleIds2().length <= 1 &&
1282 getInitParam("cdm_expanded")) {
1284 var rows = $$("#headlines-frame > div[id*=RROW]");
1286 for (var i = 0; i < rows.length; i++) {
1287 var child = rows[i];
1289 if ($("headlines-frame").scrollTop <= child.offsetTop &&
1290 child.offsetTop - $("headlines-frame").scrollTop < 100 &&
1291 child.getAttribute("data-article-id") != _active_article_id) {
1293 if (_active_article_id) {
1294 var row = $("RROW-" + _active_article_id);
1295 if (row) row.removeClassName("active");
1298 _active_article_id = child.getAttribute("data-article-id");
1299 showArticleInHeadlines(_active_article_id, true);
1300 updateSelectedPrompt();
1306 if (!_infscroll_disable) {
1307 if (hsp && hsp.offsetTop - 250 <= e.scrollTop + e.offsetHeight) {
1309 hsp.innerHTML = "<span class='loading'><img src='images/indicator_tiny.gif'> " +
1310 __("Loading, please wait...") + "</span>";
1312 loadMoreHeadlines();
1319 updateFloatingTitle();
1322 catchupCurrentBatchIfNeeded();
1324 if (getInitParam("cdm_auto_catchup") == 1) {
1326 // let's get DOM some time to settle down
1327 var ts = new Date().getTime();
1328 if (ts - _last_headlines_update < 100) return;
1330 $$("#headlines-frame > div[id*=RROW][class*=Unread]").each(
1332 if (child.hasClassName("Unread") && $("headlines-frame").scrollTop >
1333 (child.offsetTop + child.offsetHeight/2)) {
1335 var id = child.getAttribute("data-article-id")
1337 if (catchup_id_batch.indexOf(id) == -1)
1338 catchup_id_batch.push(id);
1340 //console.log("auto_catchup_batch: " + catchup_id_batch.toString());
1345 if (_infscroll_disable) {
1346 var child = $$("#headlines-frame div[id*=RROW]").last();
1348 if (child && $("headlines-frame").scrollTop >
1349 (child.offsetTop + child.offsetHeight - 50)) {
1351 console.log("we seem to be at an end");
1353 if (getInitParam("on_catchup_show_next_feed") == "1") {
1354 openNextUnreadFeed();
1361 console.warn("headlines_scroll_handler: " + e);
1365 function openNextUnreadFeed() {
1367 var is_cat = activeFeedIsCat();
1368 var nuf = getNextUnreadFeed(getActiveFeedId(), is_cat);
1369 if (nuf) viewfeed({feed: nuf, is_cat: is_cat});
1371 exception_error("openNextUnreadFeed", e);
1375 function catchupBatchedArticles() {
1377 if (catchup_id_batch.length > 0 && !_infscroll_request_sent && !_catchup_request_sent) {
1379 console.log("catchupBatchedArticles: working");
1381 // make a copy of the array
1382 var batch = catchup_id_batch.slice();
1383 var query = "?op=rpc&method=catchupSelected" +
1384 "&cmode=0&ids=" + param_escape(batch.toString());
1388 _catchup_request_sent = true;
1390 new Ajax.Request("backend.php", {
1392 onComplete: function(transport) {
1393 handle_rpc_json(transport);
1395 _catchup_request_sent = false;
1397 reply = JSON.parse(transport.responseText);
1398 var batch = reply.ids;
1400 batch.each(function(id) {
1402 var elem = $("RROW-" + id);
1403 if (elem) elem.removeClassName("Unread");
1404 catchup_id_batch.remove(id);
1407 updateFloatingTitle(true);
1413 exception_error("catchupBatchedArticles", e);
1417 function catchupRelativeToArticle(below, id) {
1421 if (!id) id = getActiveArticleId();
1424 alert(__("No article is selected."));
1428 var visible_ids = getLoadedArticleIds();
1430 var ids_to_mark = new Array();
1433 for (var i = 0; i < visible_ids.length; i++) {
1434 if (visible_ids[i] != id) {
1435 var e = $("RROW-" + visible_ids[i]);
1437 if (e && e.hasClassName("Unread")) {
1438 ids_to_mark.push(visible_ids[i]);
1445 for (var i = visible_ids.length-1; i >= 0; i--) {
1446 if (visible_ids[i] != id) {
1447 var e = $("RROW-" + visible_ids[i]);
1449 if (e && e.hasClassName("Unread")) {
1450 ids_to_mark.push(visible_ids[i]);
1458 if (ids_to_mark.length == 0) {
1459 alert(__("No articles found to mark"));
1461 var msg = ngettext("Mark %d article as read?", "Mark %d articles as read?", ids_to_mark.length).replace("%d", ids_to_mark.length);
1463 if (getInitParam("confirm_feed_catchup") != 1 || confirm(msg)) {
1465 for (var i = 0; i < ids_to_mark.length; i++) {
1466 var e = $("RROW-" + ids_to_mark[i]);
1467 e.removeClassName("Unread");
1470 var query = "?op=rpc&method=catchupSelected" +
1471 "&cmode=0" + "&ids=" + param_escape(ids_to_mark.toString());
1473 new Ajax.Request("backend.php", {
1475 onComplete: function(transport) {
1476 handle_rpc_json(transport);
1483 exception_error("catchupRelativeToArticle", e);
1487 function cdmCollapseArticle(event, id, unmark) {
1489 if (unmark == undefined) unmark = true;
1491 var row = $("RROW-" + id);
1492 var elem = $("CICD-" + id);
1495 var collapse = $$("div#RROW-" + id +
1496 " span[class='collapseBtn']")[0];
1499 Element.show("CEXC-" + id);
1500 Element.hide(collapse);
1503 row.removeClassName("active");
1505 markHeadline(id, false);
1507 if (id == getActiveArticleId()) {
1508 setActiveArticleId(0);
1511 updateSelectedPrompt();
1514 if (event) Event.stop(event);
1516 PluginHost.run(PluginHost.HOOK_ARTICLE_COLLAPSED, id);
1518 if (row.offsetTop < $("headlines-frame").scrollTop)
1519 scrollToRowId(row.id);
1521 $("floatingTitle").style.visibility = "hidden";
1522 $("floatingTitle").setAttribute("data-article-id", 0);
1526 exception_error("cdmCollapseArticle", e);
1530 function cdmExpandArticle(id, noexpand) {
1532 console.log("cdmExpandArticle " + id);
1534 if (!$("RROW-" + id)) return false;
1536 var oldrow = $("RROW-" + getActiveArticleId());
1538 var elem = $("CICD-" + getActiveArticleId());
1540 if (id == getActiveArticleId() && Element.visible(elem))
1543 selectArticles("none");
1545 var old_offset = $("RROW-" + id).offsetTop;
1547 if (getActiveArticleId() && elem && !getInitParam("cdm_expanded")) {
1548 var collapse = $$("div#RROW-" + getActiveArticleId() +
1549 " span[class='collapseBtn']")[0];
1552 Element.show("CEXC-" + getActiveArticleId());
1553 Element.hide(collapse);
1556 if (oldrow) oldrow.removeClassName("active");
1558 setActiveArticleId(id);
1560 elem = $("CICD-" + id);
1562 var collapse = $$("div#RROW-" + id +
1563 " span[class='collapseBtn']")[0];
1565 var cencw = $("CENCW-" + id);
1567 if (!Element.visible(elem) && !noexpand) {
1569 cencw.innerHTML = htmlspecialchars_decode(cencw.innerHTML);
1570 cencw.setAttribute('id', '');
1571 Element.show(cencw);
1575 Element.hide("CEXC-" + id);
1576 Element.show(collapse);
1579 var new_offset = $("RROW-" + id).offsetTop;
1581 if (old_offset > new_offset)
1582 $("headlines-frame").scrollTop -= (old_offset-new_offset);
1585 if (catchup_id_batch.indexOf(id) == -1)
1586 catchup_id_batch.push(id);
1588 catchupCurrentBatchIfNeeded();
1592 $("RROW-" + id).addClassName("active");
1594 PluginHost.run(PluginHost.HOOK_ARTICLE_EXPANDED, id);
1597 exception_error("cdmExpandArticle", e);
1603 function getArticleUnderPointer() {
1604 return post_under_pointer;
1607 function scrollArticle(offset) {
1610 var ci = $("content-insert");
1612 ci.scrollTop += offset;
1615 var hi = $("headlines-frame");
1617 hi.scrollTop += offset;
1622 exception_error("scrollArticle", e);
1626 function show_labels_in_headlines(transport) {
1628 var data = JSON.parse(transport.responseText);
1631 data['info-for-headlines'].each(function(elem) {
1632 $$(".HLLCTR-" + elem.id).each(function(ctr) {
1633 ctr.innerHTML = elem.labels;
1638 exception_error("show_labels_in_headlines", e);
1642 function cdmClicked(event, id) {
1644 //var shift_key = event.shiftKey;
1646 if (!event.ctrlKey && !event.metaKey) {
1648 if (!getInitParam("cdm_expanded")) {
1649 return cdmExpandArticle(id);
1652 var elem = $("RROW-" + getActiveArticleId());
1654 if (elem) elem.removeClassName("active");
1656 selectArticles("none");
1659 var elem = $("RROW-" + id);
1660 var article_is_unread = elem.hasClassName("Unread");
1662 elem.removeClassName("Unread");
1663 elem.addClassName("active");
1665 setActiveArticleId(id);
1667 if (article_is_unread) {
1668 decrementFeedCounter(getActiveFeedId(), activeFeedIsCat());
1669 updateFloatingTitle(true);
1672 var query = "?op=rpc&method=catchupSelected" +
1673 "&cmode=0&ids=" + param_escape(id);
1675 new Ajax.Request("backend.php", {
1677 onComplete: function(transport) {
1678 handle_rpc_json(transport);
1681 return !event.shiftKey;
1684 } else if (event.target.parents(".cdmHeader").length > 0) {
1686 toggleSelected(id, true);
1688 var elem = $("RROW-" + id);
1689 var article_is_unread = elem.hasClassName("Unread");
1691 if (article_is_unread) {
1692 decrementFeedCounter(getActiveFeedId(), activeFeedIsCat());
1695 toggleUnread(id, 0, false);
1697 openArticleInNewWindow(id);
1700 var unread_in_buffer = $$("#headlines-frame > div[id*=RROW][class*=Unread]").length
1701 request_counters(unread_in_buffer == 0);
1704 exception_error("cdmClicked");
1710 function hlClicked(event, id) {
1712 if (event.which == 2) {
1715 } else if (event.ctrlKey || event.metaKey) {
1716 toggleSelected(id, true);
1717 toggleUnread(id, 0, false);
1718 openArticleInNewWindow(id);
1726 exception_error("hlClicked");
1730 function openArticleInNewWindow(id) {
1731 toggleUnread(id, 0, false);
1732 window.open("backend.php?op=article&method=redirect&id=" + id);
1735 function isCdmMode() {
1736 return getInitParam("combined_display_mode");
1739 function markHeadline(id, marked) {
1740 if (marked == undefined) marked = true;
1742 var row = $("RROW-" + id);
1744 var check = dijit.getEnclosingWidget(
1745 row.getElementsByClassName("rchk")[0]);
1748 check.attr("checked", marked);
1752 row.addClassName("Selected");
1754 row.removeClassName("Selected");
1758 function getRelativePostIds(id, limit) {
1764 if (!limit) limit = 6; //3
1766 var ids = getLoadedArticleIds();
1768 for (var i = 0; i < ids.length; i++) {
1770 for (var k = 1; k <= limit; k++) {
1771 //if (i > k-1) tmp.push(ids[i-k]);
1772 if (i < ids.length-k) tmp.push(ids[i+k]);
1779 exception_error("getRelativePostIds", e);
1785 function correctHeadlinesOffset(id) {
1789 var container = $("headlines-frame");
1790 var row = $("RROW-" + id);
1792 if (!container || !row) return;
1794 var viewport = container.offsetHeight;
1796 var rel_offset_top = row.offsetTop - container.scrollTop;
1797 var rel_offset_bottom = row.offsetTop + row.offsetHeight - container.scrollTop;
1799 //console.log("Rtop: " + rel_offset_top + " Rbtm: " + rel_offset_bottom);
1800 //console.log("Vport: " + viewport);
1802 if (rel_offset_top <= 0 || rel_offset_top > viewport) {
1803 container.scrollTop = row.offsetTop;
1804 } else if (rel_offset_bottom > viewport) {
1806 /* doesn't properly work with Opera in some cases because
1807 Opera fucks up element scrolling */
1809 container.scrollTop = row.offsetTop + row.offsetHeight - viewport;
1813 exception_error("correctHeadlinesOffset", e);
1818 function headlineActionsChange(elem) {
1821 elem.attr('value', 'false');
1823 exception_error("headlineActionsChange", e);
1827 function closeArticlePanel() {
1829 if (dijit.byId("content-insert"))
1830 dijit.byId("headlines-wrap-inner").removeChild(
1831 dijit.byId("content-insert"));
1834 function initFloatingMenu() {
1836 if (!dijit.byId("floatingMenu")) {
1838 var menu = new dijit.Menu({
1840 targetNodeIds: ["floatingTitle"]
1843 var tmph = dojo.connect(menu, '_openMyself', function (event) {
1844 var callerNode = event.target, match = null, tries = 0;
1846 while (match == null && callerNode && tries <= 3) {
1847 match = callerNode.getAttribute("data-article-id");
1848 callerNode = callerNode.parentNode;
1852 if (match) this.callerRowId = match;
1856 headlinesMenuCommon(menu);
1862 exception_error("initFloatingMenu", e);
1866 function headlinesMenuCommon(menu) {
1869 menu.addChild(new dijit.MenuItem({
1870 label: __("Open original article"),
1871 onClick: function(event) {
1872 openArticleInNewWindow(this.getParent().callerRowId);
1875 menu.addChild(new dijit.MenuItem({
1876 label: __("Display article URL"),
1877 onClick: function(event) {
1878 displayArticleUrl(this.getParent().callerRowId);
1881 menu.addChild(new dijit.MenuSeparator());
1883 menu.addChild(new dijit.MenuItem({
1884 label: __("Toggle unread"),
1885 onClick: function(event) {
1886 var ids = getSelectedArticleIds2();
1888 var id = (this.getParent().callerRowId) + "";
1889 ids = ids.size() != 0 && ids.indexOf(id) != -1 ? ids : [id];
1891 selectionToggleUnread(undefined, false, true, ids);
1894 menu.addChild(new dijit.MenuItem({
1895 label: __("Toggle starred"),
1896 onClick: function(event) {
1897 var ids = getSelectedArticleIds2();
1899 var id = (this.getParent().callerRowId) + "";
1900 ids = ids.size() != 0 && ids.indexOf(id) != -1 ? ids : [id];
1902 selectionToggleMarked(undefined, false, true, ids);
1905 menu.addChild(new dijit.MenuItem({
1906 label: __("Toggle published"),
1907 onClick: function(event) {
1908 var ids = getSelectedArticleIds2();
1910 var id = (this.getParent().callerRowId) + "";
1911 ids = ids.size() != 0 && ids.indexOf(id) != -1 ? ids : [id];
1913 selectionTogglePublished(undefined, false, true, ids);
1916 menu.addChild(new dijit.MenuSeparator());
1918 menu.addChild(new dijit.MenuItem({
1919 label: __("Mark above as read"),
1920 onClick: function(event) {
1921 catchupRelativeToArticle(0, this.getParent().callerRowId);
1924 menu.addChild(new dijit.MenuItem({
1925 label: __("Mark below as read"),
1926 onClick: function(event) {
1927 catchupRelativeToArticle(1, this.getParent().callerRowId);
1931 var labels = dijit.byId("feedTree").model.getItemsInCategory(-2);
1935 menu.addChild(new dijit.MenuSeparator());
1937 var labelAddMenu = new dijit.Menu({ownerMenu: menu});
1938 var labelDelMenu = new dijit.Menu({ownerMenu: menu});
1940 labels.each(function(label) {
1941 var id = label.id[0];
1942 var bare_id = id.substr(id.indexOf(":")+1);
1943 var name = label.name[0];
1945 bare_id = feed_to_label_id(bare_id);
1947 labelAddMenu.addChild(new dijit.MenuItem({
1950 onClick: function(event) {
1951 var ids = getSelectedArticleIds2();
1953 var id = (this.getParent().ownerMenu.callerRowId) + "";
1955 ids = ids.size() != 0 && ids.indexOf(id) != -1 ? ids : [id];
1957 selectionAssignLabel(this.labelId, ids);
1960 labelDelMenu.addChild(new dijit.MenuItem({
1963 onClick: function(event) {
1964 var ids = getSelectedArticleIds2();
1966 var id = (this.getParent().ownerMenu.callerRowId) + "";
1968 ids = ids.size() != 0 && ids.indexOf(id) != -1 ? ids : [id];
1970 selectionRemoveLabel(this.labelId, ids);
1975 menu.addChild(new dijit.PopupMenuItem({
1976 label: __("Assign label"),
1980 menu.addChild(new dijit.PopupMenuItem({
1981 label: __("Remove label"),
1989 exception_error("headlinesMenuCommon", e);
1993 function initHeadlinesMenu(append_rows) {
1997 if (dijit.byId("headlinesMenu"))
1998 dijit.byId("headlinesMenu").destroyRecursive();
2003 nodes = $$("#headlines-frame > div[id*=RROW]");
2005 nodes = $$("#headlines-frame span[id*=RTITLE]");
2008 nodes.each(function (node) {
2012 var menu = new dijit.Menu({
2013 id: "headlinesMenu",
2017 var tmph = dojo.connect(menu, '_openMyself', function (event) {
2018 var callerNode = event.target, match = null, tries = 0;
2020 while (match == null && callerNode && tries <= 3) {
2022 match = callerNode.getAttribute("data-article-id")
2023 callerNode = callerNode.parentNode;
2027 if (match) this.callerRowId = match;
2031 headlinesMenuCommon(menu);
2036 var menu = dijit.byId("headlinesMenu");
2038 append_rows.each(function (row) {
2039 if (!row.hasClassName("cdmFeedTitle")) {
2040 menu.bindDomNode(row);
2045 /* vgroup feed title menu */
2049 var nodes = $$("#headlines-frame > div[class='cdmFeedTitle']");
2052 nodes.each(function(node) {
2056 if (ids.length > 0) {
2057 if (dijit.byId("headlinesFeedTitleMenu"))
2058 dijit.byId("headlinesFeedTitleMenu").destroyRecursive();
2060 var menu = new dijit.Menu({
2061 id: "headlinesFeedTitleMenu",
2065 var tmph = dojo.connect(menu, '_openMyself', function (event) {
2066 var callerNode = event.target, match = null, tries = 0;
2068 while (match == null && callerNode && tries <= 3) {
2069 match = callerNode.getAttribute("data-feed-id")
2070 callerNode = callerNode.parentNode;
2074 if (match) this.callerRowId = match;
2078 menu.addChild(new dijit.MenuItem({
2079 label: __("Select articles in group"),
2080 onClick: function (event) {
2081 selectArticles("all",
2082 "#headlines-frame > div[id*=RROW]" +
2083 "[data-orig-feed-id='" + menu.callerRowId + "']");
2088 menu.addChild(new dijit.MenuItem({
2089 label: __("Mark group as read"),
2090 onClick: function (event) {
2091 selectArticles("none");
2092 selectArticles("all",
2093 "#headlines-frame > div[id*=RROW]" +
2094 "[data-orig-feed-id='" + menu.callerRowId + "']");
2100 menu.addChild(new dijit.MenuItem({
2101 label: __("Mark feed as read"),
2102 onClick: function (event) {
2103 catchupFeedInGroup(menu.callerRowId);
2107 menu.addChild(new dijit.MenuItem({
2108 label: __("Edit feed"),
2109 onClick: function (event) {
2110 editFeed(menu.callerRowId);
2117 var menu = dijit.byId("headlinesFeedTitleMenu");
2119 append_rows.each(function (row) {
2120 if (row.hasClassName("cdmFeedTitle")) {
2121 menu.bindDomNode(row);
2127 exception_error("initHeadlinesMenu", e);
2131 function cache_set(id, obj) {
2132 //console.log("cache_set: " + id);
2135 sessionStorage[id] = obj;
2137 sessionStorage.clear();
2141 function cache_get(id) {
2143 return sessionStorage[id];
2146 function cache_clear() {
2148 sessionStorage.clear();
2151 function cache_delete(id) {
2153 sessionStorage.removeItem(id);
2156 function cancelSearch() {
2161 exception_error("cancelSearch", e);
2165 function setSelectionScore() {
2167 var ids = getSelectedArticleIds2();
2169 if (ids.length > 0) {
2172 var score = prompt(__("Please enter new score for selected articles:"), score);
2174 if (score != undefined) {
2175 var query = "op=article&method=setScore&id=" + param_escape(ids.toString()) +
2176 "&score=" + param_escape(score);
2178 new Ajax.Request("backend.php", {
2180 onComplete: function(transport) {
2181 var reply = JSON.parse(transport.responseText);
2185 ids.each(function(id) {
2186 var row = $("RROW-" + id);
2189 var pic = row.getElementsByClassName("hlScorePic")[0];
2192 pic.src = pic.src.replace(/score_.*?\.png/,
2193 reply["score_pic"]);
2194 pic.setAttribute("score", score);
2203 alert(__("No articles are selected."));
2206 exception_error("setSelectionScore", e);
2210 function updateScore(id) {
2212 var pic = $$("#RROW-" + id + " .hlScorePic")[0];
2216 var query = "op=article&method=getScore&id=" + param_escape(id);
2218 new Ajax.Request("backend.php", {
2220 onComplete: function(transport) {
2221 console.log(transport.responseText);
2223 var reply = JSON.parse(transport.responseText);
2226 pic.src = pic.src.replace(/score_.*?\.png/, reply["score_pic"]);
2227 pic.setAttribute("score", reply["score"]);
2228 pic.setAttribute("title", reply["score"]);
2234 exception_error("updateScore", e);
2238 function changeScore(id, pic) {
2240 var score = pic.getAttribute("score");
2242 var new_score = prompt(__("Please enter new score for this article:"), score);
2244 if (new_score != undefined) {
2246 var query = "op=article&method=setScore&id=" + param_escape(id) +
2247 "&score=" + param_escape(new_score);
2249 new Ajax.Request("backend.php", {
2251 onComplete: function(transport) {
2252 var reply = JSON.parse(transport.responseText);
2255 pic.src = pic.src.replace(/score_.*?\.png/, reply["score_pic"]);
2256 pic.setAttribute("score", new_score);
2257 pic.setAttribute("title", new_score);
2262 exception_error("changeScore", e);
2266 function displayArticleUrl(id) {
2268 var query = "op=rpc&method=getlinktitlebyid&id=" + param_escape(id);
2270 new Ajax.Request("backend.php", {
2272 onComplete: function(transport) {
2273 var reply = JSON.parse(transport.responseText);
2275 if (reply && reply.link) {
2276 prompt(__("Article URL:"), reply.link);
2280 exception_error("changeScore", e);
2284 function scrollToRowId(id) {
2289 $("headlines-frame").scrollTop = row.offsetTop - 4;
2292 exception_error("scrollToRowId", e);
2296 function updateFloatingTitle(unread_only) {
2298 if (!isCdmMode()) return;
2300 var hf = $("headlines-frame");
2302 var elems = $$("#headlines-frame > div[id*=RROW]");
2304 for (var i = 0; i < elems.length; i++) {
2306 var child = elems[i];
2308 if (child && child.offsetTop + child.offsetHeight > hf.scrollTop) {
2310 var header = child.getElementsByClassName("cdmHeader")[0];
2312 if (unread_only || child.getAttribute("data-article-id") != $("floatingTitle").getAttribute("data-article-id")) {
2313 if (child.getAttribute("data-article-id") != $("floatingTitle").getAttribute("data-article-id")) {
2315 $("floatingTitle").setAttribute("data-article-id", child.getAttribute("data-article-id"));
2316 $("floatingTitle").innerHTML = header.innerHTML;
2317 $("floatingTitle").firstChild.innerHTML = "<img class='anchor markedPic' src='images/page_white_go.png' onclick=\"scrollToRowId('"+child.id+"')\">" + $("floatingTitle").firstChild.innerHTML;
2321 var cb = $$("#floatingTitle .dijitCheckBox")[0];
2324 cb.parentNode.removeChild(cb);
2327 if (child.hasClassName("Unread"))
2328 $("floatingTitle").addClassName("Unread");
2330 $("floatingTitle").removeClassName("Unread");
2332 PluginHost.run(PluginHost.HOOK_FLOATING_TITLE, child);
2335 $("floatingTitle").style.marginRight = hf.offsetWidth - child.offsetWidth + "px";
2336 if (header.offsetTop + header.offsetHeight < hf.scrollTop + $("floatingTitle").offsetHeight - 5 &&
2337 child.offsetTop + child.offsetHeight >= hf.scrollTop + $("floatingTitle").offsetHeight - 5)
2338 $("floatingTitle").style.visibility = "visible";
2340 $("floatingTitle").style.visibility = "hidden";
2348 exception_error("updateFloatingTitle", e);
2352 function catchupCurrentBatchIfNeeded() {
2353 if (catchup_id_batch.length > 0) {
2354 window.clearTimeout(catchup_timeout_id);
2355 catchup_timeout_id = window.setTimeout(catchupBatchedArticles, 1000);
2357 if (catchup_id_batch.length >= 10) {
2358 catchupBatchedArticles();
2363 function cdmFooterClick(event) {
2364 event.stopPropagation();