]> git.wh0rd.org - tt-rss.git/blob - prefs.js
add some more dijit Buttons
[tt-rss.git] / prefs.js
1 var init_params = new Array();
2
3 var caller_subop = false;
4 var hotkey_prefix = false;
5 var hotkey_prefix_pressed = false;
6
7 var seq = "";
8
9 function feedlist_callback2(transport) {
10
11 try {
12
13 dijit.byId('feedConfigTab').attr('content', transport.responseText);
14
15 selectTab("feedConfig", true);
16
17 if (caller_subop) {
18 var tuple = caller_subop.split(":");
19 if (tuple[0] == 'editFeed') {
20 window.setTimeout('editFeed('+tuple[1]+')', 100);
21 }
22
23 caller_subop = false;
24 }
25 notify("");
26
27 } catch (e) {
28 exception_error("feedlist_callback2", e);
29 }
30 }
31
32 function filterlist_callback2(transport) {
33 dijit.byId('filterConfigTab').attr('content', transport.responseText);
34 notify("");
35 }
36
37 function labellist_callback2(transport) {
38
39 try {
40
41 dijit.byId('labelConfigTab').attr('content', transport.responseText);
42 closeInfoBox();
43
44 notify("");
45
46 } catch (e) {
47 exception_error("labellist_callback2", e);
48 }
49 }
50
51 function userlist_callback2(transport) {
52 try {
53 dijit.byId('userConfigTab').attr('content', transport.responseText);
54
55 notify("");
56 } catch (e) {
57 exception_error("userlist_callback2", e);
58 }
59 }
60
61 function prefslist_callback2(transport) {
62 try {
63 dijit.byId('genConfigTab').attr('content', transport.responseText);
64
65 notify("");
66 } catch (e) {
67 exception_error("prefslist_callback2", e);
68 }
69 }
70
71 function notify_callback2(transport) {
72 notify_info(transport.responseText);
73 }
74
75 function updateFeedList(sort_key) {
76
77 try {
78
79 var feed_search = $("feed_search");
80 var search = "";
81 if (feed_search) { search = feed_search.value; }
82
83 var slat = $("show_last_article_times");
84
85 var slat_checked = false;
86 if (slat) {
87 slat_checked = slat.checked;
88 }
89
90 var query = "?op=pref-feeds" +
91 "&sort=" + param_escape(sort_key) +
92 "&slat=" + param_escape(slat_checked) +
93 "&search=" + param_escape(search);
94
95 new Ajax.Request("backend.php", {
96 parameters: query,
97 onComplete: function(transport) {
98 feedlist_callback2(transport);
99 } });
100 } catch (e) {
101 exception_error("updateFeedList", e);
102 }
103 }
104
105 function updateUsersList(sort_key) {
106
107 try {
108
109 var user_search = $("user_search");
110 var search = "";
111 if (user_search) { search = user_search.value; }
112
113 var query = "?op=pref-users&sort="
114 + param_escape(sort_key) +
115 "&search=" + param_escape(search);
116
117 new Ajax.Request("backend.php", {
118 parameters: query,
119 onComplete: function(transport) {
120 userlist_callback2(transport);
121 } });
122
123 } catch (e) {
124 exception_error("updateUsersList", e);
125 }
126 }
127
128 function addUser() {
129
130 try {
131
132 var login = prompt(__("Please enter login:"), "");
133
134 if (login == null) {
135 return false;
136 }
137
138 if (login == "") {
139 alert(__("Can't create user: no login specified."));
140 return false;
141 }
142
143 notify_progress("Adding user...");
144
145 var query = "?op=pref-users&subop=add&login=" +
146 param_escape(login);
147
148 new Ajax.Request("backend.php", {
149 parameters: query,
150 onComplete: function(transport) {
151 userlist_callback2(transport);
152 } });
153
154 } catch (e) {
155 exception_error("addUser", e);
156 }
157 }
158
159 function editUser(id, event) {
160
161 try {
162 if (!event || !event.ctrlKey) {
163
164 notify_progress("Loading, please wait...");
165
166 selectTableRows('prefUserList', 'none');
167 selectTableRowById('UMRR-'+id, 'UMCHK-'+id, true);
168
169 var query = "?op=pref-users&subop=edit&id=" +
170 param_escape(id);
171
172 new Ajax.Request("backend.php", {
173 parameters: query,
174 onComplete: function(transport) {
175 infobox_callback2(transport);
176 document.forms['user_edit_form'].login.focus();
177 } });
178
179 } else if (event.ctrlKey) {
180 var cb = $('UMCHK-' + id);
181 cb.checked = !cb.checked;
182 toggleSelectRow(cb);
183 }
184
185 } catch (e) {
186 exception_error("editUser", e);
187 }
188
189 }
190
191 function editFilter(id, event) {
192 try {
193
194 var query = "backend.php?op=pref-filters&subop=edit&id=" + param_escape(id);
195
196 if (dijit.byId("filterEditDlg"))
197 dijit.byId("filterEditDlg").destroyRecursive();
198
199 dialog = new dijit.Dialog({
200 id: "filterEditDlg",
201 title: __("Edit Filter"),
202 style: "width: 600px",
203 removeFilter: function() {
204 var title = this.attr('value').reg_exp;
205 var msg = __("Remove filter %s?").replace("%s", title);
206
207 if (confirm(msg)) {
208 this.hide();
209
210 notify_progress("Removing filter...");
211
212 var id = this.attr('value').id;
213
214 var query = "?op=pref-filters&subop=remove&ids="+
215 param_escape(id);
216
217 new Ajax.Request("backend.php", {
218 parameters: query,
219 onComplete: function(transport) {
220 updateFilterList();
221 } });
222 }
223 },
224
225 execute: function() {
226 if (this.validate()) {
227
228 var query = "?op=rpc&subop=verifyRegexp&reg_exp=" +
229 param_escape(dialog.attr('value').reg_exp);
230
231 notify_progress("Verifying regular expression...");
232
233 new Ajax.Request("backend.php", {
234 parameters: query,
235 onComplete: function(transport) {
236 handle_rpc_reply(transport);
237 var response = transport.responseXML;
238
239 if (response) {
240 var s = response.getElementsByTagName("status")[0].firstChild.nodeValue;
241
242 notify('');
243
244 if (s == "INVALID") {
245 alert("Match regular expression seems to be invalid.");
246 return;
247 } else {
248 notify_progress("Saving data...", true);
249
250 console.log(dojo.objectToQuery(dialog.attr('value')));
251
252 new Ajax.Request("backend.php", {
253 parameters: dojo.objectToQuery(dialog.attr('value')),
254 onComplete: function(transport) {
255 dialog.hide();
256 updateFilterList();
257 }})
258 }
259 }
260 }});
261 }
262 },
263 href: query});
264
265 dialog.show();
266
267
268 } catch (e) {
269 exception_error("editFilter", e);
270 }
271 }
272
273 function getSelectedLabels() {
274 var tree = dijit.byId("labelTree");
275 var items = tree.model.getCheckedItems();
276 var rv = [];
277
278 items.each(function(item) {
279 rv.push(tree.model.store.getValue(item, 'bare_id'));
280 });
281
282 return rv;
283 }
284
285 function getSelectedUsers() {
286 return getSelectedTableRowIds("prefUserList");
287 }
288
289 function getSelectedFeeds() {
290 var tree = dijit.byId("feedTree");
291 var items = tree.model.getCheckedItems();
292 var rv = [];
293
294 items.each(function(item) {
295 rv.push(tree.model.store.getValue(item, 'bare_id'));
296 });
297
298 return rv;
299 }
300
301 function getSelectedFilters() {
302 var tree = dijit.byId("filterTree");
303 var items = tree.model.getCheckedItems();
304 var rv = [];
305
306 items.each(function(item) {
307 rv.push(tree.model.store.getValue(item, 'bare_id'));
308 });
309
310 return rv;
311
312 }
313
314 /* function getSelectedFeedCats() {
315 return getSelectedTableRowIds("prefFeedCatList");
316 } */
317
318 function removeSelectedLabels() {
319
320 var sel_rows = getSelectedLabels();
321
322 if (sel_rows.length > 0) {
323
324 var ok = confirm(__("Remove selected labels?"));
325
326 if (ok) {
327 notify_progress("Removing selected labels...");
328
329 var query = "?op=pref-labels&subop=remove&ids="+
330 param_escape(sel_rows.toString());
331
332 new Ajax.Request("backend.php", {
333 parameters: query,
334 onComplete: function(transport) {
335 labellist_callback2(transport);
336 } });
337
338 }
339 } else {
340 alert(__("No labels are selected."));
341 }
342
343 return false;
344 }
345
346 function removeSelectedUsers() {
347
348 try {
349
350 var sel_rows = getSelectedUsers();
351
352 if (sel_rows.length > 0) {
353
354 var ok = confirm(__("Remove selected users? Neither default admin nor your account will be removed."));
355
356 if (ok) {
357 notify_progress("Removing selected users...");
358
359 var query = "?op=pref-users&subop=remove&ids="+
360 param_escape(sel_rows.toString());
361
362 new Ajax.Request("backend.php", {
363 parameters: query,
364 onComplete: function(transport) {
365 userlist_callback2(transport);
366 } });
367
368 }
369
370 } else {
371 alert(__("No users are selected."));
372 }
373
374 } catch (e) {
375 exception_error("removeSelectedUsers", e);
376 }
377
378 return false;
379 }
380
381 function removeSelectedFilters() {
382
383 try {
384
385 var sel_rows = getSelectedFilters();
386
387 if (sel_rows.length > 0) {
388
389 var ok = confirm(__("Remove selected filters?"));
390
391 if (ok) {
392 notify_progress("Removing selected filters...");
393
394 var query = "?op=pref-filters&subop=remove&ids="+
395 param_escape(sel_rows.toString());
396
397 new Ajax.Request("backend.php", {
398 parameters: query,
399 onComplete: function(transport) {
400 filterlist_callback2(transport);
401 } });
402
403 }
404 } else {
405 alert(__("No filters are selected."));
406 }
407
408 } catch (e) {
409 exception_error("removeSelectedFilters", e);
410 }
411
412 return false;
413 }
414
415
416 function removeSelectedFeeds() {
417
418 try {
419
420 var sel_rows = getSelectedFeeds();
421
422 if (sel_rows.length > 0) {
423
424 var ok = confirm(__("Unsubscribe from selected feeds?"));
425
426 if (ok) {
427
428 notify_progress("Unsubscribing from selected feeds...", true);
429
430 var query = "?op=pref-feeds&subop=remove&ids="+
431 param_escape(sel_rows.toString());
432
433 console.log(query);
434
435 new Ajax.Request("backend.php", {
436 parameters: query,
437 onComplete: function(transport) {
438 updateFeedList();
439 } });
440 }
441
442 } else {
443 alert(__("No feeds are selected."));
444 }
445
446 } catch (e) {
447 exception_error("removeSelectedFeeds", e);
448 }
449
450 return false;
451 }
452
453 function clearSelectedFeeds() {
454
455 var sel_rows = getSelectedFeeds();
456
457 if (sel_rows.length > 1) {
458 alert(__("Please select only one feed."));
459 return;
460 }
461
462 if (sel_rows.length > 0) {
463
464 var ok = confirm(__("Erase all non-starred articles in selected feed?"));
465
466 if (ok) {
467 notify_progress("Clearing selected feed...");
468 clearFeedArticles(sel_rows[0]);
469 }
470
471 } else {
472
473 alert(__("No feeds are selected."));
474
475 }
476
477 return false;
478 }
479
480 function purgeSelectedFeeds() {
481
482 var sel_rows = getSelectedFeeds();
483
484 if (sel_rows.length > 0) {
485
486 var pr = prompt(__("How many days of articles to keep (0 - use default)?"), "0");
487
488 if (pr != undefined) {
489 notify_progress("Purging selected feed...");
490
491 var query = "?op=rpc&subop=purge&ids="+
492 param_escape(sel_rows.toString()) + "&days=" + pr;
493
494 console.log(query);
495
496 new Ajax.Request("prefs.php", {
497 parameters: query,
498 onComplete: function(transport) {
499 notify('');
500 } });
501 }
502
503 } else {
504
505 alert(__("No feeds are selected."));
506
507 }
508
509 return false;
510 }
511
512 function removeSelectedPrefProfiles() {
513
514 var sel_rows = getSelectedFeedCats();
515
516 if (sel_rows.length > 0) {
517
518 var ok = confirm(__("Remove selected profiles? Active and default profiles will not be removed."));
519
520 if (ok) {
521 notify_progress("Removing selected profiles...");
522
523 var query = "?op=rpc&subop=remprofiles&ids="+
524 param_escape(sel_rows.toString());
525
526 new Ajax.Request("backend.php", {
527 parameters: query,
528 onComplete: function(transport) {
529 editProfiles();
530 } });
531 }
532
533 } else {
534 alert(__("No profiles selected."));
535 }
536
537 return false;
538 }
539
540 function userEditCancel() {
541 closeInfoBox();
542 return false;
543 }
544
545 function userEditSave() {
546
547 try {
548
549 var login = document.forms["user_edit_form"].login.value;
550
551 if (login.length == 0) {
552 alert(__("Login field cannot be blank."));
553 return;
554 }
555
556 notify_progress("Saving user...");
557
558 closeInfoBox();
559
560 var query = Form.serialize("user_edit_form");
561
562 new Ajax.Request("backend.php", {
563 parameters: query,
564 onComplete: function(transport) {
565 userlist_callback2(transport);
566 } });
567
568 } catch (e) {
569 exception_error("userEditSave", e);
570 }
571
572 return false;
573
574 }
575
576
577 function editSelectedUser() {
578 var rows = getSelectedUsers();
579
580 if (rows.length == 0) {
581 alert(__("No users are selected."));
582 return;
583 }
584
585 if (rows.length > 1) {
586 alert(__("Please select only one user."));
587 return;
588 }
589
590 notify("");
591
592 editUser(rows[0]);
593 }
594
595 function resetSelectedUserPass() {
596
597 try {
598
599 var rows = getSelectedUsers();
600
601 if (rows.length == 0) {
602 alert(__("No users are selected."));
603 return;
604 }
605
606 if (rows.length > 1) {
607 alert(__("Please select only one user."));
608 return;
609 }
610
611 var ok = confirm(__("Reset password of selected user?"));
612
613 if (ok) {
614 notify_progress("Resetting password for selected user...");
615
616 var id = rows[0];
617
618 var query = "?op=pref-users&subop=resetPass&id=" +
619 param_escape(id);
620
621 new Ajax.Request("backend.php", {
622 parameters: query,
623 onComplete: function(transport) {
624 userlist_callback2(transport);
625 } });
626
627 }
628
629 } catch (e) {
630 exception_error("resetSelectedUserPass", e);
631 }
632 }
633
634 function selectedUserDetails() {
635
636 try {
637
638 var rows = getSelectedUsers();
639
640 if (rows.length == 0) {
641 alert(__("No users are selected."));
642 return;
643 }
644
645 if (rows.length > 1) {
646 alert(__("Please select only one user."));
647 return;
648 }
649
650 notify_progress("Loading, please wait...");
651
652 var id = rows[0];
653
654 var query = "?op=pref-users&subop=user-details&id=" + id;
655
656 new Ajax.Request("backend.php", {
657 parameters: query,
658 onComplete: function(transport) {
659 infobox_callback2(transport);
660 } });
661 } catch (e) {
662 exception_error("selectedUserDetails", e);
663 }
664 }
665
666
667 function editSelectedFilter() {
668 var rows = getSelectedFilters();
669
670 if (rows.length == 0) {
671 alert(__("No filters are selected."));
672 return;
673 }
674
675 if (rows.length > 1) {
676 alert(__("Please select only one filter."));
677 return;
678 }
679
680 notify("");
681
682 editFilter(rows[0]);
683
684 }
685
686
687 function editSelectedFeed() {
688 var rows = getSelectedFeeds();
689
690 if (rows.length == 0) {
691 alert(__("No feeds are selected."));
692 return;
693 }
694
695 if (rows.length > 1) {
696 return editSelectedFeeds();
697 }
698
699 notify("");
700
701 editFeed(rows[0], {});
702
703 }
704
705 function editSelectedFeeds() {
706
707 try {
708 var rows = getSelectedFeeds();
709
710 if (rows.length == 0) {
711 alert(__("No feeds are selected."));
712 return;
713 }
714
715 notify("");
716
717 var query = "backend.php?op=pref-feeds&subop=editfeeds&ids=" +
718 param_escape(rows.toString());
719
720 if (dijit.byId("feedEditDlg"))
721 dijit.byId("feedEditDlg").destroyRecursive();
722
723 dialog = new dijit.Dialog({
724 id: "feedEditDlg",
725 title: __("Edit Multiple Feeds"),
726 style: "width: 600px",
727 getChildByName: function (name) {
728 var rv = null
729 this.getChildren().each(
730 function(child) {
731 if (child.name == name) {
732 rv = child;
733 return;
734 }
735 });
736 return rv;
737 },
738 toggleField: function (checkbox, elem, label) {
739 this.getChildByName(elem).attr('disabled', !checkbox.checked);
740
741 if ($(label))
742 if (checkbox.checked)
743 $(label).removeClassName('insensitive');
744 else
745 $(label).addClassName('insensitive');
746
747 },
748 execute: function() {
749 if (this.validate() && confirm(__("Save changes to selected feeds?"))) {
750 var query = dojo.objectToQuery(this.attr('value'));
751
752 /* Form.serialize ignores unchecked checkboxes */
753
754 if (!query.match("&rtl_content=") &&
755 this.getChildByName('rtl_content').attr('disabled') == false) {
756 query = query + "&rtl_content=false";
757 }
758
759 if (!query.match("&private=") &&
760 this.getChildByName('private').attr('disabled') == false) {
761 query = query + "&private=false";
762 }
763
764 if (!query.match("&cache_images=") &&
765 this.getChildByName('cache_images').attr('disabled') == false) {
766 query = query + "&cache_images=false";
767 }
768
769 if (!query.match("&include_in_digest=") &&
770 this.getChildByName('include_in_digest').attr('disabled') == false) {
771 query = query + "&include_in_digest=false";
772 }
773
774 console.log(query);
775
776 notify_progress("Saving data...", true);
777
778 new Ajax.Request("backend.php", {
779 parameters: query,
780 onComplete: function(transport) {
781 dialog.hide();
782 updateFeedList();
783 }})
784 }
785 },
786 href: query});
787
788 dialog.show();
789
790 } catch (e) {
791 exception_error("editSelectedFeeds", e);
792 }
793 }
794
795 function piggie(enable) {
796 if (enable) {
797 console.log("I LOVEDED IT!");
798 var piggie = $("piggie");
799
800 Element.show(piggie);
801 Position.Center(piggie);
802 Effect.Puff(piggie);
803
804 }
805 }
806
807 function opmlImport() {
808
809 var opml_file = $("opml_file");
810
811 if (opml_file.value.length == 0) {
812 alert(__("Please choose an OPML file first."));
813 return false;
814 } else {
815 notify_progress("Importing, please wait...", true);
816 return true;
817 }
818 }
819
820 function updateFilterList() {
821 new Ajax.Request("backend.php", {
822 parameters: "?op=pref-filters",
823 onComplete: function(transport) {
824 filterlist_callback2(transport);
825 } });
826 }
827
828 function updateLabelList() {
829 new Ajax.Request("backend.php", {
830 parameters: "?op=pref-labels",
831 onComplete: function(transport) {
832 labellist_callback2(transport);
833 } });
834 }
835
836 function updatePrefsList() {
837 new Ajax.Request("backend.php", {
838 parameters: "?op=pref-prefs",
839 onComplete: function(transport) {
840 prefslist_callback2(transport);
841 } });
842 }
843
844 function selectTab(id, noupdate, subop) {
845 try {
846 if (!noupdate) {
847 notify_progress("Loading, please wait...");
848 closeInfoBox();
849
850 if (id == "feedConfig") {
851 updateFeedList();
852 } else if (id == "filterConfig") {
853 updateFilterList();
854 } else if (id == "labelConfig") {
855 updateLabelList();
856 } else if (id == "genConfig") {
857 updatePrefsList();
858 } else if (id == "userConfig") {
859 updateUsersList();
860 }
861
862 var tab = dijit.byId(id + "Tab");
863 dijit.byId("pref-tabs").selectChild(tab);
864
865 }
866
867 } catch (e) {
868 exception_error("selectTab", e);
869 }
870 }
871
872 function init_second_stage() {
873 try {
874
875 document.onkeydown = pref_hotkey_handler;
876
877 caller_subop = getURLParam('subop');
878
879 if (getURLParam("subopparam")) {
880 caller_subop = caller_subop + ":" + getURLParam("subopparam");
881 }
882
883 loading_set_progress(50);
884
885 notify("");
886
887 dojo.addOnLoad(function() {
888 var tab = getURLParam('tab');
889
890 if (tab) {
891 tab = dijit.byId(tab + "Tab");
892 if (tab) dijit.byId("pref-tabs").selectChild(tab);
893 }
894 });
895
896 setTimeout("hotkey_prefix_timeout()", 5*1000);
897
898 } catch (e) {
899 exception_error("init_second_stage", e);
900 }
901 }
902
903 function init() {
904
905 try {
906
907 dojo.require("dijit.layout.TabContainer");
908 dojo.require("dijit.layout.BorderContainer");
909 dojo.require("dijit.layout.AccordionContainer");
910 dojo.require("dijit.layout.ContentPane");
911 dojo.require("dijit.Dialog");
912 dojo.require("dijit.form.Button");
913 dojo.require("dijit.form.Select");
914 dojo.require("dijit.form.FilteringSelect");
915 dojo.require("dijit.form.TextBox");
916 dojo.require("dijit.form.CheckBox");
917 dojo.require("dijit.form.ValidationTextBox");
918 dojo.require("dijit.form.RadioButton");
919 dojo.require("dijit.form.Select");
920 dojo.require("dijit.Toolbar");
921 dojo.require("dojo.data.ItemFileWriteStore");
922 dojo.require("dijit.Tree");
923 dojo.require("dijit.form.DropDownButton");
924 dojo.require("dijit.form.Form");
925 dojo.require("dijit.Menu");
926 dojo.require("dijit.tree.dndSource");
927 dojo.require("dijit.InlineEditBox");
928 dojo.require("dijit.ColorPalette");
929 dojo.require("dijit.ProgressBar");
930
931 dojo.registerModulePath("lib", "..");
932 dojo.registerModulePath("fox", "../..");
933
934 dojo.require("lib.CheckBoxTree");
935 dojo.require("fox.PrefFeedTree");
936 dojo.require("fox.PrefFilterTree");
937 dojo.require("fox.PrefLabelTree");
938
939 dojo.addOnLoad(function() {
940 loading_set_progress(50);
941
942 new Ajax.Request("backend.php", {
943 parameters: {op: "rpc", subop: "sanityCheck"},
944 onComplete: function(transport) {
945 backend_sanity_check_callback(transport);
946 } });
947 });
948
949 } catch (e) {
950 exception_error("init", e);
951 }
952 }
953
954 function validatePrefsReset() {
955 try {
956 var ok = confirm(__("Reset to defaults?"));
957
958 if (ok) {
959
960 var query = Form.serialize("pref_prefs_form");
961 query = query + "&subop=reset-config";
962 console.log(query);
963
964 new Ajax.Request("backend.php", {
965 parameters: query,
966 onComplete: function(transport) {
967 var msg = transport.responseText;
968 if (msg.match("PREFS_THEME_CHANGED")) {
969 window.location.reload();
970 } else {
971 notify_info(msg);
972 selectTab();
973 }
974 } });
975
976 }
977
978 } catch (e) {
979 exception_error("validatePrefsReset", e);
980 }
981
982 return false;
983
984 }
985
986
987 function pref_hotkey_handler(e) {
988 try {
989
990 if (dijit.getEnclosingWidget(e.target)) return;
991
992 var keycode;
993 var shift_key = false;
994
995 var cmdline = $('cmdline');
996
997 try {
998 shift_key = e.shiftKey;
999 } catch (e) {
1000
1001 }
1002
1003 if (window.event) {
1004 keycode = window.event.keyCode;
1005 } else if (e) {
1006 keycode = e.which;
1007 }
1008
1009 var keychar = String.fromCharCode(keycode);
1010
1011 if (keycode == 27) { // escape
1012 if (Element.visible("hotkey_help_overlay")) {
1013 Element.hide("hotkey_help_overlay");
1014 }
1015 hotkey_prefix = false;
1016 closeInfoBox();
1017 }
1018
1019 var dialog = dijit.byId("infoBox");
1020 var dialog_visible = false;
1021
1022 if (dialog)
1023 dialog_visible = Element.visible(dialog.domNode);
1024
1025 if (dialog_visible || !hotkeys_enabled) {
1026 console.log("hotkeys disabled");
1027 return;
1028 }
1029
1030 if (keycode == 16) return; // ignore lone shift
1031 if (keycode == 17) return; // ignore lone ctrl
1032
1033 if ((keycode == 67 || keycode == 71) && !hotkey_prefix) {
1034 hotkey_prefix = keycode;
1035
1036 var date = new Date();
1037 var ts = Math.round(date.getTime() / 1000);
1038
1039 hotkey_prefix_pressed = ts;
1040
1041 cmdline.innerHTML = keychar;
1042 Element.show(cmdline);
1043
1044 console.log("KP: PREFIX=" + keycode + " CHAR=" + keychar);
1045 return;
1046 }
1047
1048 if (Element.visible("hotkey_help_overlay")) {
1049 Element.hide("hotkey_help_overlay");
1050 }
1051
1052 if (keycode == 13 || keycode == 27) {
1053 seq = "";
1054 } else {
1055 seq = seq + "" + keycode;
1056 }
1057
1058 /* Global hotkeys */
1059
1060 Element.hide(cmdline);
1061
1062 if (!hotkey_prefix) {
1063
1064 if ((keycode == 191 || keychar == '?') && shift_key) { // ?
1065 if (!Element.visible("hotkey_help_overlay")) {
1066 //Element.show("hotkey_help_overlay");
1067 Effect.Appear("hotkey_help_overlay", {duration : 0.3});
1068 } else {
1069 Element.hide("hotkey_help_overlay");
1070 }
1071 return false;
1072 }
1073
1074 if (keycode == 191 || keychar == '/') { // /
1075 var search_boxes = new Array("label_search",
1076 "feed_search", "filter_search", "user_search", "feed_browser_search");
1077
1078 for (var i = 0; i < search_boxes.length; i++) {
1079 var elem = $(search_boxes[i]);
1080 if (elem) {
1081 $(search_boxes[i]).focus();
1082 return false;
1083 }
1084 }
1085 }
1086 }
1087
1088 /* Prefix c */
1089
1090 if (hotkey_prefix == 67) { // c
1091 hotkey_prefix = false;
1092
1093 if (keycode == 70) { // f
1094 quickAddFilter();
1095 return false;
1096 }
1097
1098 if (keycode == 83) { // s
1099 quickAddFeed();
1100 return false;
1101 }
1102
1103 if (keycode == 85) { // u
1104 // no-op
1105 }
1106
1107 if (keycode == 67) { // c
1108 editFeedCats();
1109 return false;
1110 }
1111
1112 if (keycode == 84 && shift_key) { // T
1113 feedBrowser();
1114 return false;
1115 }
1116
1117 }
1118
1119 /* Prefix g */
1120
1121 if (hotkey_prefix == 71) { // g
1122
1123 hotkey_prefix = false;
1124
1125 if (keycode == 49 && $("genConfigTab")) { // 1
1126 selectTab("genConfig");
1127 return false;
1128 }
1129
1130 if (keycode == 50 && $("feedConfigTab")) { // 2
1131 selectTab("feedConfig");
1132 return false;
1133 }
1134
1135 if (keycode == 51 && $("filterConfigTab")) { // 4
1136 selectTab("filterConfig");
1137 return false;
1138 }
1139
1140 if (keycode == 52 && $("labelConfigTab")) { // 5
1141 selectTab("labelConfig");
1142 return false;
1143 }
1144
1145 if (keycode == 53 && $("userConfigTab")) { // 6
1146 selectTab("userConfig");
1147 return false;
1148 }
1149
1150 if (keycode == 88) { // x
1151 return gotoMain();
1152 }
1153
1154 }
1155
1156 if ($("piggie")) {
1157 if (seq.match("8073717369")) {
1158 seq = "";
1159 piggie(true);
1160 } else {
1161 piggie(false);
1162 }
1163 }
1164
1165 if (hotkey_prefix) {
1166 console.log("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
1167 } else {
1168 console.log("KP: CODE=" + keycode + " CHAR=" + keychar);
1169 }
1170
1171 } catch (e) {
1172 exception_error("pref_hotkey_handler", e);
1173 }
1174 }
1175
1176 function editFeedCats() {
1177 try {
1178 var query = "backend.php?op=pref-feeds&subop=editCats";
1179
1180 if (dijit.byId("feedCatEditDlg"))
1181 dijit.byId("feedCatEditDlg").destroyRecursive();
1182
1183 dialog = new dijit.Dialog({
1184 id: "feedCatEditDlg",
1185 title: __("Feed Categories"),
1186 style: "width: 600px",
1187 getSelectedCategories: function() {
1188 return getSelectedTableRowIds("prefFeedCatList");
1189 },
1190 removeSelected: function() {
1191 var sel_rows = this.getSelectedCategories();
1192
1193 if (sel_rows.length > 0) {
1194 var ok = confirm(__("Remove selected categories?"));
1195
1196 if (ok) {
1197 notify_progress("Removing selected categories...", true);
1198
1199 var query = "?op=pref-feeds&subop=editCats&action=remove&ids="+
1200 param_escape(sel_rows.toString());
1201
1202 new Ajax.Request("backend.php", {
1203 parameters: query,
1204 onComplete: function(transport) {
1205 notify('');
1206 dialog.attr('content', transport.responseText);
1207 updateFeedList();
1208 } });
1209
1210 }
1211
1212 } else {
1213 alert(__("No categories are selected."));
1214 }
1215 },
1216 addCategory: function() {
1217 if (this.validate()) {
1218 notify_progress("Creating category...");
1219
1220 var query = "?op=pref-feeds&subop=editCats&action=add&cat=" +
1221 param_escape(this.attr('value').newcat);
1222
1223 new Ajax.Request("backend.php", {
1224 parameters: query,
1225 onComplete: function(transport) {
1226 notify('');
1227 dialog.attr('content', transport.responseText);
1228 updateFeedList();
1229 } });
1230 }
1231 },
1232 execute: function() {
1233 if (this.validate()) {
1234 }
1235 },
1236 href: query});
1237
1238 dialog.show();
1239
1240 } catch (e) {
1241 exception_error("editFeedCats", e);
1242 }
1243 }
1244
1245 function showFeedsWithErrors() {
1246 displayDlg('feedUpdateErrors');
1247 }
1248
1249 function opmlRegenKey() {
1250
1251 try {
1252 var ok = confirm(__("Replace current OPML publishing address with a new one?"));
1253
1254 if (ok) {
1255
1256 notify_progress("Trying to change address...", true);
1257
1258 var query = "?op=rpc&subop=regenOPMLKey";
1259
1260 new Ajax.Request("backend.php", {
1261 parameters: query,
1262 onComplete: function(transport) {
1263 var new_link = transport.responseXML.getElementsByTagName("link")[0];
1264
1265 var e = $('pub_opml_url');
1266
1267 if (new_link) {
1268 e.href = new_link.firstChild.nodeValue;
1269 e.innerHTML = new_link.firstChild.nodeValue;
1270
1271 new Effect.Highlight(e);
1272
1273 notify('');
1274
1275 } else {
1276 notify_error("Could not change feed URL.");
1277 }
1278 } });
1279 }
1280 } catch (e) {
1281 exception_error("opmlRegenKey", e);
1282 }
1283 return false;
1284 }
1285
1286 function feedActionChange() {
1287 try {
1288 var chooser = $("feedActionChooser");
1289 var opid = chooser[chooser.selectedIndex].value;
1290
1291 chooser.selectedIndex = 0;
1292 feedActionGo(opid);
1293 } catch (e) {
1294 exception_error("feedActionChange", e);
1295 }
1296 }
1297
1298 function feedActionGo(op) {
1299 try {
1300 if (op == "facEdit") {
1301
1302 var rows = getSelectedFeeds();
1303
1304 if (rows.length > 1) {
1305 editSelectedFeeds();
1306 } else {
1307 editSelectedFeed();
1308 }
1309 }
1310
1311 if (op == "facClear") {
1312 clearSelectedFeeds();
1313 }
1314
1315 if (op == "facPurge") {
1316 purgeSelectedFeeds();
1317 }
1318
1319 if (op == "facEditCats") {
1320 editFeedCats();
1321 }
1322
1323 if (op == "facRescore") {
1324 rescoreSelectedFeeds();
1325 }
1326
1327 if (op == "facUnsubscribe") {
1328 removeSelectedFeeds();
1329 }
1330
1331 } catch (e) {
1332 exception_error("feedActionGo", e);
1333
1334 }
1335 }
1336
1337 function clearFeedArticles(feed_id) {
1338
1339 notify_progress("Clearing feed...");
1340
1341 var query = "?op=pref-feeds&quiet=1&subop=clear&id=" + feed_id;
1342
1343 new Ajax.Request("backend.php", {
1344 parameters: query,
1345 onComplete: function(transport) {
1346 notify('');
1347 } });
1348
1349 return false;
1350 }
1351
1352 function rescoreSelectedFeeds() {
1353
1354 var sel_rows = getSelectedFeeds();
1355
1356 if (sel_rows.length > 0) {
1357
1358 //var ok = confirm(__("Rescore last 100 articles in selected feeds?"));
1359 var ok = confirm(__("Rescore articles in selected feeds?"));
1360
1361 if (ok) {
1362 notify_progress("Rescoring selected feeds...", true);
1363
1364 var query = "?op=pref-feeds&subop=rescore&quiet=1&ids="+
1365 param_escape(sel_rows.toString());
1366
1367 new Ajax.Request("backend.php", {
1368 parameters: query,
1369 onComplete: function(transport) {
1370 notify_callback2(transport);
1371 } });
1372
1373 }
1374 } else {
1375 alert(__("No feeds are selected."));
1376 }
1377
1378 return false;
1379 }
1380
1381 function rescore_all_feeds() {
1382 var ok = confirm(__("Rescore all articles? This operation may take a lot of time."));
1383
1384 if (ok) {
1385 notify_progress("Rescoring feeds...", true);
1386
1387 var query = "?op=pref-feeds&subop=rescoreAll&quiet=1";
1388
1389 new Ajax.Request("backend.php", {
1390 parameters: query,
1391 onComplete: function(transport) {
1392 notify_callback2(transport);
1393 } });
1394 }
1395 }
1396
1397 function labelColorReset() {
1398 try {
1399 var labels = getSelectedLabels();
1400
1401 var ok = confirm(__("Reset label colors to default?"));
1402
1403 if (ok) {
1404
1405 var query = "?op=pref-labels&subop=color-reset&ids="+
1406 param_escape(labels.toString());
1407
1408 new Ajax.Request("backend.php", {
1409 parameters: query,
1410 onComplete: function(transport) {
1411 labellist_callback2(transport);
1412 } });
1413 }
1414
1415 } catch (e) {
1416 exception_error("labelColorReset", e);
1417 }
1418 }
1419
1420
1421 function inPreferences() {
1422 return true;
1423 }
1424
1425 function editProfiles() {
1426 try {
1427
1428 if (dijit.byId("profileEditDlg"))
1429 dijit.byId("profileEditDlg").destroyRecursive();
1430
1431 var query = "backend.php?op=dlg&id=editPrefProfiles";
1432
1433 dialog = new dijit.Dialog({
1434 id: "profileEditDlg",
1435 title: __("Settings Profiles"),
1436 style: "width: 600px",
1437 getSelectedProfiles: function() {
1438 return getSelectedTableRowIds("prefFeedProfileList");
1439 },
1440 removeSelected: function() {
1441 var sel_rows = this.getSelectedProfiles();
1442
1443 if (sel_rows.length > 0) {
1444 var ok = confirm(__("Remove selected profiles? Active and default profiles will not be removed."));
1445
1446 if (ok) {
1447 notify_progress("Removing selected profiles...", true);
1448
1449 var query = "?op=rpc&subop=remprofiles&ids="+
1450 param_escape(sel_rows.toString());
1451
1452 new Ajax.Request("backend.php", {
1453 parameters: query,
1454 onComplete: function(transport) {
1455 notify('');
1456 editProfiles();
1457 } });
1458
1459 }
1460
1461 } else {
1462 alert(__("No profiles are selected."));
1463 }
1464 },
1465 activateProfile: function() {
1466 var sel_rows = this.getSelectedProfiles();
1467
1468 if (sel_rows.length == 1) {
1469
1470 var ok = confirm(__("Activate selected profile?"));
1471
1472 if (ok) {
1473 notify_progress("Loading, please wait...");
1474
1475 var query = "?op=rpc&subop=setprofile&id="+
1476 param_escape(sel_rows.toString());
1477
1478 new Ajax.Request("backend.php", {
1479 parameters: query,
1480 onComplete: function(transport) {
1481 window.location.reload();
1482 } });
1483 }
1484
1485 } else {
1486 alert(__("Please choose a profile to activate."));
1487 }
1488 },
1489 addProfile: function() {
1490 if (this.validate()) {
1491 notify_progress("Creating profile...", true);
1492
1493 var query = "?op=rpc&subop=addprofile&title=" +
1494 param_escape(dialog.attr('value').newprofile);
1495
1496 new Ajax.Request("backend.php", {
1497 parameters: query,
1498 onComplete: function(transport) {
1499 notify('');
1500 editProfiles();
1501 } });
1502
1503 }
1504 },
1505 execute: function() {
1506 if (this.validate()) {
1507 }
1508 },
1509 href: query});
1510
1511 dialog.show();
1512 } catch (e) {
1513 exception_error("editProfiles", e);
1514 }
1515 }
1516
1517 function activatePrefProfile() {
1518
1519 var sel_rows = getSelectedFeedCats();
1520
1521 if (sel_rows.length == 1) {
1522
1523 var ok = confirm(__("Activate selected profile?"));
1524
1525 if (ok) {
1526 notify_progress("Loading, please wait...");
1527
1528 var query = "?op=rpc&subop=setprofile&id="+
1529 param_escape(sel_rows.toString());
1530
1531 new Ajax.Request("backend.php", {
1532 parameters: query,
1533 onComplete: function(transport) {
1534 window.location.reload();
1535 } });
1536 }
1537
1538 } else {
1539 alert(__("Please choose a profile to activate."));
1540 }
1541
1542 return false;
1543 }
1544
1545 function opmlImportDone() {
1546 closeInfoBox();
1547 updateFeedList();
1548 }
1549
1550 function opmlImportHandler(iframe) {
1551 try {
1552 var tmp = new Object();
1553 tmp.responseText = iframe.document.body.innerHTML;
1554 notify('');
1555 infobox_callback2(tmp);
1556 } catch (e) {
1557 exception_error("opml_import_handler", e);
1558 }
1559 }
1560
1561 function clearFeedAccessKeys() {
1562
1563 var ok = confirm(__("This will invalidate all previously generated feed URLs. Continue?"));
1564
1565 if (ok) {
1566 notify_progress("Clearing URLs...");
1567
1568 var query = "?op=rpc&subop=clearKeys";
1569
1570 new Ajax.Request("backend.php", {
1571 parameters: query,
1572 onComplete: function(transport) {
1573 notify_info("Generated URLs cleared.");
1574 } });
1575 }
1576
1577 return false;
1578 }
1579
1580 function handle_rpc_reply(transport, scheduled_call) {
1581 try {
1582 if (transport.responseXML) {
1583
1584 if (!transport_error_check(transport)) return false;
1585
1586 } else {
1587 notify_error("Error communicating with server.");
1588 }
1589
1590 } catch (e) {
1591 exception_error("handle_rpc_reply", e, transport);
1592 }
1593
1594 return true;
1595 }
1596
1597 function resetFeedOrder() {
1598 try {
1599 notify_progress("Loading, please wait...");
1600
1601 new Ajax.Request("backend.php", {
1602 parameters: "?op=pref-feeds&subop=feedsortreset",
1603 onComplete: function(transport) {
1604 updateFeedList();
1605 } });
1606
1607
1608 } catch (e) {
1609 exception_error("resetFeedOrder");
1610 }
1611 }
1612
1613 function resetCatOrder() {
1614 try {
1615 notify_progress("Loading, please wait...");
1616
1617 new Ajax.Request("backend.php", {
1618 parameters: "?op=pref-feeds&subop=catsortreset",
1619 onComplete: function(transport) {
1620 updateFeedList();
1621 } });
1622
1623
1624 } catch (e) {
1625 exception_error("resetCatOrder");
1626 }
1627 }
1628
1629 function editCat(id, item, event) {
1630 try {
1631 var new_name = prompt(__('Rename category to:'), item.name);
1632
1633 if (new_name && new_name != item.name) {
1634
1635 notify_progress("Loading, please wait...");
1636
1637 new Ajax.Request("backend.php", {
1638 parameters: {
1639 op: 'pref-feeds',
1640 subop: 'renamecat',
1641 id: id,
1642 title: new_name,
1643 },
1644 onComplete: function(transport) {
1645 updateFeedList();
1646 } });
1647 }
1648
1649 } catch (e) {
1650 exception_error("editCat", e);
1651 }
1652 }
1653
1654 function editLabel(id, event) {
1655 try {
1656 var query = "backend.php?op=pref-labels&subop=edit&id=" +
1657 param_escape(id);
1658
1659 if (dijit.byId("labelEditDlg"))
1660 dijit.byId("labelEditDlg").destroyRecursive();
1661
1662 dialog = new dijit.Dialog({
1663 id: "labelEditDlg",
1664 title: __("Label Editor"),
1665 style: "width: 600px",
1666 setLabelColor: function(id, fg, bg) {
1667
1668 var kind = '';
1669 var color = '';
1670
1671 if (fg && bg) {
1672 kind = 'both';
1673 } else if (fg) {
1674 kind = 'fg';
1675 color = fg;
1676 } else if (bg) {
1677 kind = 'bg';
1678 color = bg;
1679 }
1680
1681 var query = "?op=pref-labels&subop=color-set&kind="+kind+
1682 "&ids=" + param_escape(id) + "&fg=" + param_escape(fg) +
1683 "&bg=" + param_escape(bg) + "&color=" + param_escape(color);
1684
1685 // console.log(query);
1686
1687 var e = $("LICID-" + id);
1688
1689 if (e) {
1690 if (fg) e.style.color = fg;
1691 if (bg) e.style.backgroundColor = bg;
1692 }
1693
1694 new Ajax.Request("backend.php", { parameters: query });
1695
1696 updateFilterList();
1697 },
1698 execute: function() {
1699 if (this.validate()) {
1700 var caption = this.attr('value').id;
1701 var caption = this.attr('value').caption;
1702 var fg_color = this.attr('value').fg_color;
1703 var bg_color = this.attr('value').bg_color;
1704 var query = dojo.objectToQuery(this.attr('value'));
1705
1706 dijit.byId('labelTree').setNameById(id, caption);
1707 this.setLabelColor(id, fg_color, bg_color);
1708 this.hide();
1709
1710 new Ajax.Request("backend.php", {
1711 parameters: query,
1712 onComplete: function(transport) {
1713 updateFilterList();
1714 } });
1715 }
1716 },
1717 href: query});
1718
1719 dialog.show();
1720
1721 } catch (e) {
1722 exception_error("editLabel", e);
1723 }
1724 }
1725
1726