]> git.wh0rd.org - tt-rss.git/blob - tt-rss.js
misc feed edit dialog fixes
[tt-rss.git] / tt-rss.js
1 var total_unread = 0;
2 var global_unread = -1;
3 var firsttime_update = true;
4 var _active_feed_id = 0;
5 var _active_feed_is_cat = false;
6 var number_of_feeds = 0;
7 var hotkey_prefix = false;
8 var hotkey_prefix_pressed = false;
9 var init_params = {};
10 var _force_scheduled_update = false;
11 var last_scheduled_update = false;
12
13 var _rpc_seq = 0;
14
15 function next_seq() {
16 _rpc_seq += 1;
17 return _rpc_seq;
18 }
19
20 function get_seq() {
21 return _rpc_seq;
22 }
23
24 function activeFeedIsCat() {
25 return _active_feed_is_cat;
26 }
27
28 function getActiveFeedId() {
29 try {
30 //console.log("gAFID: " + _active_feed_id);
31 return _active_feed_id;
32 } catch (e) {
33 exception_error("getActiveFeedId", e);
34 }
35 }
36
37 function setActiveFeedId(id, is_cat) {
38 try {
39 _active_feed_id = id;
40
41 if (is_cat != undefined) {
42 _active_feed_is_cat = is_cat;
43 }
44
45 selectFeed(id, is_cat);
46
47 } catch (e) {
48 exception_error("setActiveFeedId", e);
49 }
50 }
51
52
53 function dlg_frefresh_callback(transport, deleted_feed) {
54 if (getActiveFeedId() == deleted_feed) {
55 setTimeout("viewfeed(-5)", 100);
56 }
57
58 setTimeout('updateFeedList()', 50);
59 closeInfoBox();
60 }
61
62 function updateFeedList() {
63 try {
64
65 // $("feeds-holder").innerHTML = "<div id=\"feedlistLoading\">" +
66 // __("Loading, please wait...") + "</div>";
67
68 Element.show("feedlistLoading");
69
70 if (dijit.byId("feedTree")) {
71 dijit.byId("feedTree").destroyRecursive();
72 }
73
74 var store = new dojo.data.ItemFileWriteStore({
75 url: "backend.php?op=feeds"});
76
77 var treeModel = new fox.FeedStoreModel({
78 store: store,
79 query: {
80 "type": "feed"
81 },
82 rootId: "root",
83 rootLabel: "Feeds",
84 childrenAttrs: ["items"]
85 });
86
87 var tree = new fox.FeedTree({
88 model: treeModel,
89 onOpen: function (item, node) {
90 var id = String(item.id);
91 var cat_id = id.substr(id.indexOf(":")+1);
92
93 new Ajax.Request("backend.php",
94 { parameters: "backend.php?op=feeds&subop=collapse&cid=" +
95 param_escape(cat_id) + "&mode=0" } );
96 },
97 onClose: function (item, node) {
98 var id = String(item.id);
99 var cat_id = id.substr(id.indexOf(":")+1);
100
101 new Ajax.Request("backend.php",
102 { parameters: "backend.php?op=feeds&subop=collapse&cid=" +
103 param_escape(cat_id) + "&mode=1" } );
104
105 },
106 onClick: function (item, node) {
107 var id = String(item.id);
108 var is_cat = id.match("^CAT:");
109 var feed = id.substr(id.indexOf(":")+1);
110 viewfeed(feed, '', is_cat);
111 return false;
112 },
113 openOnClick: false,
114 showRoot: false,
115 id: "feedTree",
116 }, "feedTree");
117
118 /* var menu = new dijit.Menu({id: 'feedMenu'});
119
120 menu.addChild(new dijit.MenuItem({
121 label: "Simple menu item"
122 }));
123
124 // menu.bindDomNode(tree.domNode); */
125
126 var tmph = dojo.connect(dijit.byId('feedMenu'), '_openMyself', function (event) {
127 console.log(dijit.getEnclosingWidget(event.target));
128 dojo.disconnect(tmph);
129 });
130
131 $("feeds-holder").appendChild(tree.domNode);
132
133 var tmph = dojo.connect(tree, 'onLoad', function() {
134 dojo.disconnect(tmph);
135 Element.hide("feedlistLoading");
136
137 tree.collapseHiddenCats();
138
139 feedlist_init();
140
141 // var node = dijit.byId("feedTree")._itemNodesMap['FEED:-2'][0].domNode
142 // menu.bindDomNode(node);
143
144 loading_set_progress(25);
145 });
146
147 tree.startup();
148
149 } catch (e) {
150 exception_error("updateFeedList", e);
151 }
152 }
153
154 function catchupAllFeeds() {
155
156 var str = __("Mark all articles as read?");
157
158 if (getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
159
160 var query_str = "backend.php?op=feeds&subop=catchupAll";
161
162 notify_progress("Marking all feeds as read...");
163
164 //console.log("catchupAllFeeds Q=" + query_str);
165
166 new Ajax.Request("backend.php", {
167 parameters: query_str,
168 onComplete: function(transport) {
169 feedlist_callback2(transport);
170 } });
171
172 global_unread = 0;
173 updateTitle("");
174 }
175 }
176
177 function viewCurrentFeed(subop) {
178
179 if (getActiveFeedId() != undefined) {
180 viewfeed(getActiveFeedId(), subop, activeFeedIsCat());
181 }
182 return false; // block unneeded form submits
183 }
184
185 function timeout() {
186 if (getInitParam("bw_limit") == "1") return;
187
188 try {
189 var date = new Date();
190 var ts = Math.round(date.getTime() / 1000);
191
192 if (ts - last_scheduled_update > 10 || _force_scheduled_update) {
193
194 //console.log("timeout()");
195
196 window.clearTimeout(counter_timeout_id);
197
198 var query_str = "?op=rpc&subop=getAllCounters&seq=" + next_seq();
199
200 var omode;
201
202 if (firsttime_update && !navigator.userAgent.match("Opera")) {
203 firsttime_update = false;
204 omode = "T";
205 } else {
206 omode = "flc";
207 }
208
209 query_str = query_str + "&omode=" + omode;
210
211 if (!_force_scheduled_update)
212 query_str = query_str + "&last_article_id=" + getInitParam("last_article_id");
213
214 //console.log("[timeout]" + query_str);
215
216 new Ajax.Request("backend.php", {
217 parameters: query_str,
218 onComplete: function(transport) {
219 handle_rpc_reply(transport, !_force_scheduled_update);
220 _force_scheduled_update = false;
221 } });
222
223 last_scheduled_update = ts;
224 }
225
226 } catch (e) {
227 exception_error("timeout", e);
228 }
229
230 setTimeout("timeout()", 3000);
231 }
232
233 function search() {
234 closeInfoBox();
235 viewCurrentFeed();
236 }
237
238 function updateTitle() {
239 var tmp = "Tiny Tiny RSS";
240
241 if (global_unread > 0) {
242 tmp = tmp + " (" + global_unread + ")";
243 }
244
245 if (window.fluid) {
246 if (global_unread > 0) {
247 window.fluid.dockBadge = global_unread;
248 } else {
249 window.fluid.dockBadge = "";
250 }
251 }
252
253 document.title = tmp;
254 }
255
256 function genericSanityCheck() {
257 setCookie("ttrss_test", "TEST");
258
259 if (getCookie("ttrss_test") != "TEST") {
260 fatalError(2);
261 }
262
263 return true;
264 }
265
266 function init() {
267 try {
268 Form.disable("main_toolbar_form");
269
270 dojo.require("dijit.layout.BorderContainer");
271 dojo.require("dijit.layout.TabContainer");
272 dojo.require("dijit.layout.ContentPane");
273 dojo.require("dijit.Dialog");
274 dojo.require("dijit.form.Button");
275 dojo.require("dijit.Menu");
276 dojo.require("dojo.data.ItemFileWriteStore");
277 dojo.require("dijit.Tree");
278 dojo.require("dijit.form.Select");
279 dojo.require("dijit.form.TextBox");
280 dojo.require("dijit.form.ValidationTextBox");
281 dojo.require("dijit.form.FilteringSelect");
282 dojo.require("dijit.form.CheckBox");
283 dojo.require("dijit.Toolbar");
284 dojo.require("dijit.ProgressBar");
285 dojo.require("dijit.Menu");
286
287 dojo.registerModulePath("fox", "../..");
288
289 dojo.require("fox.FeedTree");
290
291 if (typeof themeBeforeLayout == 'function') {
292 themeBeforeLayout();
293 }
294
295 dojo.addOnLoad(function() {
296 updateFeedList();
297 closeArticlePanel();
298
299 if (typeof themeAfterLayout == 'function') {
300 themeAfterLayout();
301 }
302
303 });
304
305 if (!genericSanityCheck())
306 return;
307
308 loading_set_progress(20);
309
310 new Ajax.Request("backend.php", {
311 parameters: {op: "rpc", subop: "sanityCheck"},
312 onComplete: function(transport) {
313 backend_sanity_check_callback(transport);
314 } });
315
316 } catch (e) {
317 exception_error("init", e);
318 }
319 }
320
321 function init_second_stage() {
322
323 try {
324
325 delCookie("ttrss_test");
326
327 var toolbar = document.forms["main_toolbar_form"];
328
329 dropboxSelect(toolbar.view_mode, getInitParam("default_view_mode"));
330 dropboxSelect(toolbar.order_by, getInitParam("default_view_order_by"));
331
332 feeds_sort_by_unread = getInitParam("feeds_sort_by_unread") == 1;
333
334 loading_set_progress(30);
335
336 if (has_local_storage())
337 localStorage.clear();
338
339 console.log("second stage ok");
340
341 } catch (e) {
342 exception_error("init_second_stage", e);
343 }
344 }
345
346 function quickMenuChange() {
347 var chooser = $("quickMenuChooser");
348 var opid = chooser[chooser.selectedIndex].value;
349
350 chooser.selectedIndex = 0;
351 quickMenuGo(opid);
352 }
353
354 function quickMenuGo(opid) {
355 try {
356
357 if (opid == "qmcPrefs") {
358 gotoPreferences();
359 }
360
361 if (opid == "qmcTagCloud") {
362 displayDlg("printTagCloud");
363 }
364
365 if (opid == "qmcSearch") {
366 displayDlg("search", getActiveFeedId() + ":" + activeFeedIsCat(),
367 function() {
368 document.forms['search_form'].query.focus();
369 });
370 return;
371 }
372
373 if (opid == "qmcAddFeed") {
374 quickAddFeed();
375 return;
376 }
377
378 if (opid == "qmcEditFeed") {
379 if (activeFeedIsCat())
380 alert(__("You can't edit this kind of feed."));
381 else
382 editFeed(getActiveFeedId());
383 return;
384 }
385
386 if (opid == "qmcRemoveFeed") {
387 var actid = getActiveFeedId();
388
389 if (activeFeedIsCat()) {
390 alert(__("You can't unsubscribe from the category."));
391 return;
392 }
393
394 if (!actid) {
395 alert(__("Please select some feed first."));
396 return;
397 }
398
399 var fn = getFeedName(actid);
400
401 var pr = __("Unsubscribe from %s?").replace("%s", fn);
402
403 if (confirm(pr)) {
404 unsubscribeFeed(actid);
405 }
406
407 return;
408 }
409
410 if (opid == "qmcCatchupAll") {
411 catchupAllFeeds();
412 return;
413 }
414
415 if (opid == "qmcShowOnlyUnread") {
416 toggleDispRead();
417 return;
418 }
419
420 if (opid == "qmcAddFilter") {
421 displayDlg('quickAddFilter', '',
422 function () {document.forms['filter_add_form'].reg_exp.focus();});
423 }
424
425 if (opid == "qmcAddLabel") {
426 addLabel();
427 }
428
429 if (opid == "qmcRescoreFeed") {
430 rescoreCurrentFeed();
431 }
432
433 if (opid == "qmcHKhelp") {
434 //Element.show("hotkey_help_overlay");
435 Effect.Appear("hotkey_help_overlay", {duration : 0.3});
436 }
437
438 } catch (e) {
439 exception_error("quickMenuGo", e);
440 }
441 }
442
443 function toggleDispRead() {
444 try {
445
446 var hide = !(getInitParam("hide_read_feeds") == "1");
447
448 hideOrShowFeeds(hide);
449
450 var query = "?op=rpc&subop=setpref&key=HIDE_READ_FEEDS&value=" +
451 param_escape(hide);
452
453 setInitParam("hide_read_feeds", hide);
454
455 new Ajax.Request("backend.php", {
456 parameters: query,
457 onComplete: function(transport) {
458 } });
459
460 } catch (e) {
461 exception_error("toggleDispRead", e);
462 }
463 }
464
465 function parse_runtime_info(elem) {
466
467 if (!elem || !elem.firstChild) {
468 console.warn("parse_runtime_info: invalid node passed");
469 return;
470 }
471
472 var data = JSON.parse(elem.firstChild.nodeValue);
473
474 //console.log("parsing runtime info...");
475
476 for (k in data) {
477 var v = data[k];
478
479 // console.log("RI: " + k + " => " + v);
480
481 if (k == "new_version_available") {
482 var icon = $("newVersionIcon");
483 if (icon) {
484 if (v == "1") {
485 icon.style.display = "inline";
486 } else {
487 icon.style.display = "none";
488 }
489 }
490 return;
491 }
492
493 var error_flag;
494
495 if (k == "daemon_is_running" && v != 1) {
496 notify_error("<span onclick=\"javascript:explainError(1)\">Update daemon is not running.</span>", true);
497 return;
498 }
499
500 if (k == "daemon_stamp_ok" && v != 1) {
501 notify_error("<span onclick=\"javascript:explainError(3)\">Update daemon is not updating feeds.</span>", true);
502 return;
503 }
504
505 init_params[k] = v;
506 notify('');
507 }
508 }
509
510 function catchupCurrentFeed() {
511
512 var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
513
514 var str = __("Mark all articles in %s as read?").replace("%s", fn);
515
516 if (getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
517 return viewCurrentFeed('MarkAllRead')
518 }
519 }
520
521 function catchupFeedInGroup(id) {
522
523 try {
524
525 var title = getFeedName(id);
526
527 var str = __("Mark all articles in %s as read?").replace("%s", title);
528
529 if (getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
530 return viewCurrentFeed('MarkAllReadGR:' + id)
531 }
532
533 } catch (e) {
534 exception_error("catchupFeedInGroup", e);
535 }
536 }
537
538 function collapse_feedlist() {
539 try {
540
541 if (!Element.visible('feeds-holder')) {
542 Element.show('feeds-holder');
543 $("collapse_feeds_btn").innerHTML = "&lt;&lt;";
544 } else {
545 Element.hide('feeds-holder');
546 $("collapse_feeds_btn").innerHTML = "&gt;&gt;";
547 }
548
549 dijit.byId("main").resize();
550
551 query = "?op=rpc&subop=setpref&key=_COLLAPSED_FEEDLIST&value=true";
552 new Ajax.Request("backend.php", { parameters: query });
553
554 } catch (e) {
555 exception_error("collapse_feedlist", e);
556 }
557 }
558
559 function viewModeChanged() {
560 cache_flush();
561 return viewCurrentFeed('')
562 }
563
564 function viewLimitChanged() {
565 cache_flush();
566 return viewCurrentFeed('')
567 }
568
569 /* function adjustArticleScore(id, score) {
570 try {
571
572 var pr = prompt(__("Assign score to article:"), score);
573
574 if (pr != undefined) {
575 var query = "?op=rpc&subop=setScore&id=" + id + "&score=" + pr;
576
577 new Ajax.Request("backend.php", {
578 parameters: query,
579 onComplete: function(transport) {
580 viewCurrentFeed();
581 } });
582
583 }
584 } catch (e) {
585 exception_error("adjustArticleScore", e);
586 }
587 } */
588
589 function rescoreCurrentFeed() {
590
591 var actid = getActiveFeedId();
592
593 if (activeFeedIsCat() || actid < 0) {
594 alert(__("You can't rescore this kind of feed."));
595 return;
596 }
597
598 if (!actid) {
599 alert(__("Please select some feed first."));
600 return;
601 }
602
603 var fn = getFeedName(actid);
604 var pr = __("Rescore articles in %s?").replace("%s", fn);
605
606 if (confirm(pr)) {
607 notify_progress("Rescoring articles...");
608
609 var query = "?op=pref-feeds&subop=rescore&quiet=1&ids=" + actid;
610
611 new Ajax.Request("backend.php", {
612 parameters: query,
613 onComplete: function(transport) {
614 viewCurrentFeed();
615 } });
616 }
617 }
618
619 function hotkey_handler(e) {
620
621 try {
622
623 var keycode;
624 var shift_key = false;
625
626 var cmdline = $('cmdline');
627
628 try {
629 shift_key = e.shiftKey;
630 } catch (e) {
631
632 }
633
634 if (window.event) {
635 keycode = window.event.keyCode;
636 } else if (e) {
637 keycode = e.which;
638 }
639
640 var keychar = String.fromCharCode(keycode);
641
642 if (keycode == 27) { // escape
643 if (Element.visible("hotkey_help_overlay")) {
644 Element.hide("hotkey_help_overlay");
645 }
646 hotkey_prefix = false;
647 closeInfoBox();
648 }
649
650 var dialog = dijit.byId("infoBox");
651 var dialog_visible = false;
652
653 if (dialog)
654 dialog_visible = Element.visible(dialog.domNode);
655
656 if (dialog_visible || !hotkeys_enabled) {
657 console.log("hotkeys disabled");
658 return;
659 }
660
661 if (keycode == 16) return; // ignore lone shift
662 if (keycode == 17) return; // ignore lone ctrl
663
664 if ((keycode == 70 || keycode == 67 || keycode == 71)
665 && !hotkey_prefix) {
666
667 var date = new Date();
668 var ts = Math.round(date.getTime() / 1000);
669
670 hotkey_prefix = keycode;
671 hotkey_prefix_pressed = ts;
672
673 cmdline.innerHTML = keychar;
674 Element.show(cmdline);
675
676 console.log("KP: PREFIX=" + keycode + " CHAR=" + keychar + " TS=" + ts);
677 return true;
678 }
679
680 if (Element.visible("hotkey_help_overlay")) {
681 Element.hide("hotkey_help_overlay");
682 }
683
684 /* Global hotkeys */
685
686 Element.hide(cmdline);
687
688 if (!hotkey_prefix) {
689
690 if ((keycode == 191 || keychar == '?') && shift_key) { // ?
691 if (!Element.visible("hotkey_help_overlay")) {
692 Effect.Appear("hotkey_help_overlay", {duration : 0.3});
693 } else {
694 Element.hide("hotkey_help_overlay");
695 }
696 return false;
697 }
698
699 if (keycode == 191 || keychar == '/') { // /
700 displayDlg("search", getActiveFeedId() + ":" + activeFeedIsCat(),
701 function() {
702 document.forms['search_form'].query.focus();
703 });
704 return false;
705 }
706
707 if (keycode == 74) { // j
708 // TODO: move to previous feed
709 return;
710 }
711
712 if (keycode == 75) { // k
713 // TODO: move to next feed
714 return;
715 }
716
717 if (shift_key && keycode == 40) { // shift-down
718 catchupRelativeToArticle(1);
719 return;
720 }
721
722 if (shift_key && keycode == 38) { // shift-up
723 catchupRelativeToArticle(0);
724 return;
725 }
726
727 if (shift_key && keycode == 78) { // N
728 scrollArticle(50);
729 return;
730 }
731
732 if (shift_key && keycode == 80) { // P
733 scrollArticle(-50);
734 return;
735 }
736
737 if (keycode == 68 && shift_key) { // shift-D
738 dismissSelectedArticles();
739 }
740
741 if (keycode == 88 && shift_key) { // shift-X
742 dismissReadArticles();
743 }
744
745 if (keycode == 78 || keycode == 40) { // n, down
746 if (typeof moveToPost != 'undefined') {
747 moveToPost('next');
748 return false;
749 }
750 }
751
752 if (keycode == 80 || keycode == 38) { // p, up
753 if (typeof moveToPost != 'undefined') {
754 moveToPost('prev');
755 return false;
756 }
757 }
758
759 if (keycode == 83 && shift_key) { // S
760 selectionTogglePublished(undefined, false, true);
761 return;
762 }
763
764 if (keycode == 83) { // s
765 selectionToggleMarked(undefined, false, true);
766 return;
767 }
768
769
770 if (keycode == 85) { // u
771 selectionToggleUnread(undefined, false, true)
772 return;
773 }
774
775 if (keycode == 84 && shift_key) { // T
776 var id = getActiveArticleId();
777 if (id) {
778 editArticleTags(id, getActiveFeedId(), isCdmMode());
779 return;
780 }
781 }
782
783 if (keycode == 9) { // tab
784 var id = getArticleUnderPointer();
785 if (id) {
786 var cb = $("RCHK-" + id);
787
788 if (cb) {
789 cb.checked = !cb.checked;
790 toggleSelectRowById(cb, "RROW-" + id);
791 return false;
792 }
793 }
794 }
795
796 if (keycode == 79) { // o
797 if (getActiveArticleId()) {
798 openArticleInNewWindow(getActiveArticleId());
799 return;
800 }
801 }
802
803 if (keycode == 81 && shift_key) { // Q
804 if (typeof catchupAllFeeds != 'undefined') {
805 catchupAllFeeds();
806 return;
807 }
808 }
809
810 if (keycode == 88) { // x
811 if (activeFeedIsCat()) {
812 toggleCollapseCat(getActiveFeedId());
813 }
814 }
815 }
816
817 /* Prefix f */
818
819 if (hotkey_prefix == 70) { // f
820
821 hotkey_prefix = false;
822
823 if (keycode == 81) { // q
824 if (getActiveFeedId()) {
825 catchupCurrentFeed();
826 return;
827 }
828 }
829
830 if (keycode == 82) { // r
831 if (getActiveFeedId()) {
832 viewfeed(getActiveFeedId(), "ForceUpdate", activeFeedIsCat());
833 return;
834 }
835 }
836
837 if (keycode == 65) { // a
838 toggleDispRead();
839 return false;
840 }
841
842 if (keycode == 85) { // u
843 if (getActiveFeedId()) {
844 viewfeed(getActiveFeedId(), "ForceUpdate");
845 return false;
846 }
847 }
848
849 if (keycode == 69) { // e
850
851 if (activeFeedIsCat())
852 alert(__("You can't edit this kind of feed."));
853 else
854 editFeed(getActiveFeedId());
855 return;
856
857 return false;
858 }
859
860 if (keycode == 83) { // s
861 quickAddFeed();
862 return false;
863 }
864
865 if (keycode == 67 && shift_key) { // C
866 if (typeof catchupAllFeeds != 'undefined') {
867 catchupAllFeeds();
868 return false;
869 }
870 }
871
872 if (keycode == 67) { // c
873 if (getActiveFeedId()) {
874 catchupCurrentFeed();
875 return false;
876 }
877 }
878
879 if (keycode == 87) { // w
880 feeds_sort_by_unread = !feeds_sort_by_unread;
881 return resort_feedlist();
882 }
883
884 if (keycode == 88) { // x
885 reverseHeadlineOrder();
886 return;
887 }
888 }
889
890 /* Prefix c */
891
892 if (hotkey_prefix == 67) { // c
893 hotkey_prefix = false;
894
895 if (keycode == 70) { // f
896 displayDlg('quickAddFilter', '',
897 function () {document.forms['filter_add_form'].reg_exp.focus();});
898 return false;
899 }
900
901 if (keycode == 76) { // l
902 addLabel();
903 return false;
904 }
905
906 if (keycode == 83) { // s
907 if (typeof collapse_feedlist != 'undefined') {
908 collapse_feedlist();
909 return false;
910 }
911 }
912
913 if (keycode == 77) { // m
914 // TODO: sortable feedlist
915 return;
916 }
917
918 if (keycode == 78) { // n
919 catchupRelativeToArticle(1);
920 return;
921 }
922
923 if (keycode == 80) { // p
924 catchupRelativeToArticle(0);
925 return;
926 }
927
928
929 }
930
931 /* Prefix g */
932
933 if (hotkey_prefix == 71) { // g
934
935 hotkey_prefix = false;
936
937
938 if (keycode == 65) { // a
939 viewfeed(-4);
940 return false;
941 }
942
943 if (keycode == 83) { // s
944 viewfeed(-1);
945 return false;
946 }
947
948 if (keycode == 80 && shift_key) { // P
949 gotoPreferences();
950 return false;
951 }
952
953 if (keycode == 80) { // p
954 viewfeed(-2);
955 return false;
956 }
957
958 if (keycode == 70) { // f
959 viewfeed(-3);
960 return false;
961 }
962
963 if (keycode == 84 && shift_key) { // T
964 toggleTags();
965 return false;
966 }
967 }
968
969 /* Cmd */
970
971 if (hotkey_prefix == 224 || hotkey_prefix == 91) { // f
972 hotkey_prefix = false;
973 return;
974 }
975
976 if (hotkey_prefix) {
977 console.log("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
978 } else {
979 console.log("KP: CODE=" + keycode + " CHAR=" + keychar);
980 }
981
982
983 } catch (e) {
984 exception_error("hotkey_handler", e);
985 }
986 }
987
988 function inPreferences() {
989 return false;
990 }
991
992 function reverseHeadlineOrder() {
993 try {
994
995 var query_str = "?op=rpc&subop=togglepref&key=REVERSE_HEADLINES";
996
997 new Ajax.Request("backend.php", {
998 parameters: query_str,
999 onComplete: function(transport) {
1000 viewCurrentFeed();
1001 } });
1002
1003 } catch (e) {
1004 exception_error("reverseHeadlineOrder", e);
1005 }
1006 }
1007
1008 function showFeedsWithErrors() {
1009 displayDlg('feedUpdateErrors');
1010 }
1011
1012 function handle_rpc_reply(transport, scheduled_call) {
1013 try {
1014 if (transport.responseXML) {
1015
1016 if (!transport_error_check(transport)) return false;
1017
1018 var seq = transport.responseXML.getElementsByTagName("seq")[0];
1019
1020 if (seq) {
1021 seq = seq.firstChild.nodeValue;
1022
1023 if (get_seq() != seq) {
1024 //console.log("[handle_rpc_reply] sequence mismatch: " + seq);
1025 return true;
1026 }
1027 }
1028
1029 var message = transport.responseXML.getElementsByTagName("message")[0];
1030
1031 if (message) {
1032 message = message.firstChild.nodeValue;
1033
1034 if (message == "UPDATE_COUNTERS") {
1035 console.log("need to refresh counters...");
1036 setInitParam("last_article_id", -1);
1037 _force_scheduled_update = true;
1038 }
1039 }
1040
1041 var counters = transport.responseXML.getElementsByTagName("counters")[0];
1042
1043 if (counters)
1044 parse_counters(counters, scheduled_call);
1045
1046 var runtime_info = transport.responseXML.getElementsByTagName("runtime-info")[0];
1047
1048 if (runtime_info)
1049 parse_runtime_info(runtime_info);
1050
1051 hideOrShowFeeds(getInitParam("hide_read_feeds") == 1);
1052
1053 } else {
1054 notify_error("Error communicating with server.");
1055 }
1056
1057 } catch (e) {
1058 exception_error("handle_rpc_reply", e, transport);
1059 }
1060
1061 return true;
1062 }
1063
1064 function scheduleFeedUpdate(id, is_cat) {
1065 try {
1066 if (!id) {
1067 id = getActiveFeedId();
1068 is_cat = activeFeedIsCat();
1069 }
1070
1071 if (!id) {
1072 alert(__("Please select some feed first."));
1073 return;
1074 }
1075
1076 var query = "?op=rpc&subop=scheduleFeedUpdate&id=" +
1077 param_escape(id) +
1078 "&is_cat=" + param_escape(is_cat);
1079
1080 console.log(query);
1081
1082 new Ajax.Request("backend.php", {
1083 parameters: query,
1084 onComplete: function(transport) {
1085
1086 if (transport.responseXML) {
1087 var message = transport.responseXML.getElementsByTagName("message")[0];
1088
1089 if (message) {
1090 notify_info(message.firstChild.nodeValue);
1091 return;
1092 }
1093 }
1094
1095 notify_error("Error communicating with server.");
1096
1097 } });
1098
1099
1100 } catch (e) {
1101 exception_error("scheduleFeedUpdate", e);
1102 }
1103 }