]> git.wh0rd.org - tt-rss.git/blob - prefs.js
prefs: some async work (6)
[tt-rss.git] / prefs.js
1 var active_feed_cat = false;
2 var active_tab = false;
3
4 var init_params = new Array();
5
6 var caller_subop = false;
7 var sanity_check_done = false;
8 var hotkey_prefix = false;
9
10 function replace_pubkey_callback(transport) {
11 try {
12 var link = document.getElementById("pubGenAddress");
13
14 if (transport.responseXML) {
15
16 var new_link = transport.responseXML.getElementsByTagName("link")[0];
17
18 if (new_link) {
19 link.href = new_link.firstChild.nodeValue;
20 //link.innerHTML = new_link.firstChild.nodeValue;
21
22 new Effect.Highlight(link);
23
24 notify_info("Published feed URL changed.");
25 } else {
26 notify_error("Could not change feed URL.");
27 }
28
29 } else {
30 notify_error("Could not change feed URL.");
31 }
32 } catch (e) {
33 exception_error("replace_pubkey_callback", e);
34 }
35 }
36
37 function feedlist_callback2(transport) {
38
39 try {
40
41 var container = document.getElementById('prefContent');
42 container.innerHTML=transport.responseText;
43 selectTab("feedConfig", true);
44
45 if (caller_subop) {
46 var tuple = caller_subop.split(":");
47 if (tuple[0] == 'editFeed') {
48 window.setTimeout('editFeed('+tuple[1]+')', 100);
49 }
50
51 caller_subop = false;
52 }
53 if (typeof correctPNG != 'undefined') {
54 correctPNG();
55 }
56 notify("");
57 remove_splash();
58
59 } catch (e) {
60 exception_error("feedlist_callback2", e);
61 }
62 }
63
64 /* stub for subscription dialog */
65
66 function dlg_frefresh_callback(transport) {
67 return feedlist_callback2(transport);
68 }
69
70 function filterlist_callback2(transport) {
71 var container = document.getElementById('prefContent');
72 container.innerHTML=transport.responseText;
73 if (typeof correctPNG != 'undefined') {
74 correctPNG();
75 }
76 notify("");
77 remove_splash();
78 }
79
80 function labellist_callback2(transport) {
81
82 try {
83
84 var container = document.getElementById('prefContent');
85 closeInfoBox();
86 container.innerHTML=transport.responseText;
87
88 if (document.getElementById("prefLabelList")) {
89 var elems = document.getElementById("prefLabelList").getElementsByTagName("SPAN");
90
91 for (var i = 0; i < elems.length; i++) {
92 if (elems[i].id && elems[i].id.match("LILT-")) {
93
94 var id = elems[i].id.replace("LILT-", "");
95 new Ajax.InPlaceEditor(elems[i],
96 'backend.php?op=pref-labels&subop=save&id=' + id,
97 {cols: 20, rows: 1});
98 }
99 }
100 }
101
102 if (typeof correctPNG != 'undefined') {
103 correctPNG();
104 }
105 notify("");
106 remove_splash();
107
108 } catch (e) {
109 exception_error("labellist_callback2", e);
110 }
111 }
112
113 function userlist_callback2(transport) {
114 try {
115 var container = document.getElementById('prefContent');
116 if (transport.readyState == 4) {
117 container.innerHTML=transport.responseText;
118 notify("");
119 remove_splash();
120 }
121 } catch (e) {
122 exception_error("userlist_callback2", e);
123 }
124 }
125
126 function prefslist_callback2(transport) {
127 try {
128 var container = document.getElementById('prefContent');
129 container.innerHTML=transport.responseText;
130 notify("");
131 remove_splash();
132 } catch (e) {
133 exception_error("prefslist_callback2", e);
134 }
135 }
136
137 function notify_callback2(transport) {
138 notify_info(transport.responseText);
139 }
140
141 function prefs_reset_callback2(transport) {
142 try {
143 notify_info(transport.responseText);
144 selectTab();
145 } catch (e) {
146 exception_error("prefs_reset_callback2", e);
147 }
148 }
149
150
151 function changepass_callback2(transport) {
152 try {
153
154 if (transport.responseText.indexOf("ERROR: ") == 0) {
155 notify_error(transport.responseText.replace("ERROR: ", ""));
156 } else {
157 notify_info(transport.responseText);
158 var warn = document.getElementById("default_pass_warning");
159 if (warn) warn.style.display = "none";
160 }
161
162 document.forms['change_pass_form'].reset();
163
164 } catch (e) {
165 exception_error("changepass_callback2", e);
166 }
167 }
168
169 function init_cat_inline_editor() {
170 try {
171
172 if (document.getElementById("prefFeedCatList")) {
173 var elems = document.getElementById("prefFeedCatList").getElementsByTagName("SPAN");
174
175 for (var i = 0; i < elems.length; i++) {
176 if (elems[i].id && elems[i].id.match("FCATT-")) {
177 var cat_id = elems[i].id.replace("FCATT-", "");
178 new Ajax.InPlaceEditor(elems[i],
179 'backend.php?op=pref-feeds&subop=editCats&action=save&cid=' + cat_id);
180 }
181 }
182 }
183
184 } catch (e) {
185 exception_error("init_cat_inline_editor", e);
186 }
187 }
188
189 function infobox_feed_cat_callback2(transport) {
190 try {
191 infobox_callback2(transport);
192 init_cat_inline_editor();
193 } catch (e) {
194 exception_error("infobox_feed_cat_callback2", e);
195 }
196 }
197
198 function updateFeedList(sort_key) {
199
200 try {
201
202 var feed_search = document.getElementById("feed_search");
203 var search = "";
204 if (feed_search) { search = feed_search.value; }
205
206 var slat = document.getElementById("show_last_article_times");
207
208 var slat_checked = false;
209 if (slat) {
210 slat_checked = slat.checked;
211 }
212
213 var query = "backend.php?op=pref-feeds" +
214 "&sort=" + param_escape(sort_key) +
215 "&slat=" + param_escape(slat_checked) +
216 "&search=" + param_escape(search);
217
218 new Ajax.Request(query, {
219 onComplete: function(transport) {
220 feedlist_callback2(transport);
221 } });
222 } catch (e) {
223 exception_error("updateFeedList", e);
224 }
225 }
226
227 function updateUsersList(sort_key) {
228
229 try {
230
231 var user_search = document.getElementById("user_search");
232 var search = "";
233 if (user_search) { search = user_search.value; }
234
235 var query = "backend.php?op=pref-users&sort="
236 + param_escape(sort_key) +
237 "&search=" + param_escape(search);
238
239 new Ajax.Request(query, {
240 onComplete: function(transport) {
241 userlist_callback2(transport);
242 } });
243
244 } catch (e) {
245 exception_error("updateUsersList", e);
246 }
247 }
248
249 function addLabel() {
250
251 try {
252
253 var caption = prompt(__("Please enter label caption:"), "");
254
255 if (caption == null) {
256 return false;
257 }
258
259 if (caption == "") {
260 alert(__("Can't create label: missing caption."));
261 return false;
262 }
263
264 // we can be called from some other tab
265 active_tab = "labelConfig";
266
267 query = "backend.php?op=pref-labels&subop=add&caption=" +
268 param_escape(caption);
269
270 new Ajax.Request(query, {
271 onComplete: function(transport) {
272 infobox_submit_callback2(transport);
273 } });
274
275 } catch (e) {
276 exception_error("addLabel", e);
277 }
278 }
279
280 function addFeed() {
281
282 try {
283
284 var link = document.getElementById("fadd_link");
285
286 if (link.value.length == 0) {
287 alert(__("Error: No feed URL given."));
288 } else if (!isValidURL(link.value)) {
289 alert(__("Error: Invalid feed URL."));
290 } else {
291 notify_progress("Adding feed...");
292
293 var query = "backend.php?op=pref-feeds&subop=add&from=tt-rss&feed_url=" +
294 param_escape(link.value);
295
296 new Ajax.Request(query, {
297 onComplete: function(transport) {
298 feedlist_callback2(transport);
299 } });
300
301 link.value = "";
302
303 }
304
305 } catch (e) {
306 exception_error("addFeed", e);
307 }
308
309 }
310
311 function addFeedCat() {
312
313 var cat = document.getElementById("fadd_cat");
314
315 if (cat.value.length == 0) {
316 alert(__("Can't add category: no name specified."));
317 } else {
318 notify_progress("Adding feed category...");
319
320 var query = "backend.php?op=pref-feeds&subop=editCats&action=add&cat=" +
321 param_escape(cat.value);
322
323 new Ajax.Request(query, {
324 onComplete: function(transport) {
325 infobox_feed_cat_callback2(transport);
326 } });
327
328 link.value = "";
329
330 }
331
332 }
333 function addUser() {
334
335 try {
336
337 var sqlexp = document.getElementById("uadd_box");
338
339 if (sqlexp.value.length == 0) {
340 alert(__("Can't add user: no login specified."));
341 } else {
342 notify_progress("Adding user...");
343
344 var query = "backend.php?op=pref-users&subop=add&login=" +
345 param_escape(sqlexp.value);
346
347 new Ajax.Request(query, {
348 onComplete: function(transport) {
349 userlist_callback2(transport);
350 } });
351
352 sqlexp.value = "";
353 }
354
355 } catch (e) {
356 exception_error("addUser", e);
357 }
358 }
359
360 function editUser(id) {
361
362 try {
363
364 disableHotkeys();
365
366 notify_progress("Loading, please wait...");
367
368 selectTableRowsByIdPrefix('prefUserList', 'UMRR-', 'UMCHK-', false);
369 selectTableRowById('UMRR-'+id, 'UMCHK-'+id, true);
370
371 disableContainerChildren("userOpToolbar", false);
372
373 var query = "backend.php?op=pref-users&subop=edit&id=" +
374 param_escape(id);
375
376 new Ajax.Request(query, {
377 onComplete: function(transport) {
378 infobox_callback2(transport);
379 } });
380
381 } catch (e) {
382 exception_error("editUser", e);
383 }
384
385 }
386
387 function editFilter(id) {
388
389 try {
390
391 disableHotkeys();
392
393 notify_progress("Loading, please wait...");
394
395 disableContainerChildren("filterOpToolbar", false);
396
397 selectTableRowsByIdPrefix('prefFilterList', 'FILRR-', 'FICHK-', false);
398 selectTableRowById('FILRR-'+id, 'FICHK-'+id, true);
399
400 var query = "backend.php?op=pref-filters&subop=edit&id=" +
401 param_escape(id);
402
403 new Ajax.Request(query, {
404 onComplete: function(transport) {
405 infobox_callback2(transport);
406 } });
407 } catch (e) {
408 exception_error("editFilter", e);
409 }
410 }
411
412 function editFeed(feed) {
413
414 try {
415
416 disableHotkeys();
417
418 notify_progress("Loading, please wait...");
419
420 // clean selection from all rows & select row being edited
421 selectTableRowsByIdPrefix('prefFeedList', 'FEEDR-', 'FRCHK-', false);
422 selectTableRowById('FEEDR-'+feed, 'FRCHK-'+feed, true);
423
424 disableContainerChildren("feedOpToolbar", false);
425
426 var query = "backend.php?op=pref-feeds&subop=editfeed&id=" +
427 param_escape(feed);
428
429 new Ajax.Request(query, {
430 onComplete: function(transport) {
431 infobox_callback2(transport);
432 } });
433
434 } catch (e) {
435 exception_error("editFeed", e);
436 }
437 }
438
439 function getSelectedLabels() {
440 return getSelectedTableRowIds("prefLabelList", "LILRR");
441 }
442
443 function getSelectedUsers() {
444 return getSelectedTableRowIds("prefUserList", "UMRR");
445 }
446
447 function getSelectedFeeds() {
448 return getSelectedTableRowIds("prefFeedList", "FEEDR");
449 }
450
451 function getSelectedFilters() {
452 return getSelectedTableRowIds("prefFilterList", "FILRR");
453 }
454
455 function getSelectedFeedCats() {
456 return getSelectedTableRowIds("prefFeedCatList", "FCATR");
457 }
458
459
460 function removeSelectedLabels() {
461
462 var sel_rows = getSelectedLabels();
463
464 if (sel_rows.length > 0) {
465
466 var ok = confirm(__("Remove selected labels?"));
467
468 if (ok) {
469 notify_progress("Removing selected labels...");
470
471 var query = "backend.php?op=pref-labels&subop=remove&ids="+
472 param_escape(sel_rows.toString());
473
474 new Ajax.Request(query, {
475 onComplete: function(transport) {
476 labellist_callback2(transport);
477 } });
478
479 }
480 } else {
481 alert(__("No labels are selected."));
482 }
483
484 return false;
485 }
486
487 function removeSelectedUsers() {
488
489 try {
490
491 var sel_rows = getSelectedUsers();
492
493 if (sel_rows.length > 0) {
494
495 var ok = confirm(__("Remove selected users?"));
496
497 if (ok) {
498 notify_progress("Removing selected users...");
499
500 var query = "backend.php?op=pref-users&subop=remove&ids="+
501 param_escape(sel_rows.toString());
502
503 new Ajax.Request(query, {
504 onComplete: function(transport) {
505 userlist_callback2(transport);
506 } });
507
508 }
509
510 } else {
511 alert(__("No users are selected."));
512 }
513
514 } catch (e) {
515 exception_error("removeSelectedUsers", e);
516 }
517
518 return false;
519 }
520
521 function removeSelectedFilters() {
522
523 try {
524
525 var sel_rows = getSelectedFilters();
526
527 if (sel_rows.length > 0) {
528
529 var ok = confirm(__("Remove selected filters?"));
530
531 if (ok) {
532 notify_progress("Removing selected filters...");
533
534 var query = "backend.php?op=pref-filters&subop=remove&ids="+
535 param_escape(sel_rows.toString());
536
537 new Ajax.Request(query, {
538 onComplete: function(transport) {
539 filterlist_callback2(transport);
540 } });
541
542 }
543 } else {
544 alert(__("No filters are selected."));
545 }
546
547 } catch (e) {
548 exception_error("removeSelectedFilters", e);
549 }
550
551 return false;
552 }
553
554
555 function removeSelectedFeeds() {
556
557 try {
558
559 var sel_rows = getSelectedFeeds();
560
561 if (sel_rows.length > 0) {
562
563 var ok = confirm(__("Unsubscribe from selected feeds?"));
564
565 if (ok) {
566
567 notify_progress("Unsubscribing from selected feeds...");
568
569 var query = "backend.php?op=pref-feeds&subop=remove&ids="+
570 param_escape(sel_rows.toString());
571
572 new Ajax.Request(query, {
573 onComplete: function(transport) {
574 feedlist_callback2(transport);
575 } });
576 }
577
578 } else {
579 alert(__("No feeds are selected."));
580 }
581
582 } catch (e) {
583 exception_error("removeSelectedFeeds", e);
584 }
585
586 return false;
587 }
588
589 function clearSelectedFeeds() {
590
591 var sel_rows = getSelectedFeeds();
592
593 if (sel_rows.length > 1) {
594 alert(__("Please select only one feed."));
595 return;
596 }
597
598 if (sel_rows.length > 0) {
599
600 var ok = confirm(__("Erase all non-starred articles in selected feed?"));
601
602 if (ok) {
603 notify_progress("Clearing selected feed...");
604 clearFeedArticles(sel_rows[0]);
605 }
606
607 } else {
608
609 alert(__("No feeds are selected."));
610
611 }
612
613 return false;
614 }
615
616 function purgeSelectedFeeds() {
617
618 var sel_rows = getSelectedFeeds();
619
620 if (sel_rows.length > 0) {
621
622 var pr = prompt(__("How many days of articles to keep (0 - use default)?"), "0");
623
624 if (pr != undefined) {
625 notify_progress("Purging selected feed...");
626
627 var query = "backend.php?op=rpc&subop=purge&ids="+
628 param_escape(sel_rows.toString()) + "&days=" + pr;
629
630 debug(query);
631
632 new Ajax.Request(query, {
633 onComplete: function(transport) {
634 notify('');
635 } });
636 }
637
638 } else {
639
640 alert(__("No feeds are selected."));
641
642 }
643
644 return false;
645 }
646
647 function removeSelectedFeedCats() {
648
649 var sel_rows = getSelectedFeedCats();
650
651 if (sel_rows.length > 0) {
652
653 var ok = confirm(__("Remove selected categories?"));
654
655 if (ok) {
656 notify_progress("Removing selected categories...");
657
658 var query = "backend.php?op=pref-feeds&subop=editCats&action=remove&ids="+
659 param_escape(sel_rows.toString());
660
661 new Ajax.Request(query, {
662 onComplete: function(transport) {
663 infobox_feed_cat_callback2(transport);
664 } });
665
666 }
667
668 } else {
669
670 alert(__("No categories are selected."));
671
672 }
673
674 return false;
675 }
676
677 function feedEditCancel() {
678
679 try {
680 document.getElementById("subscribe_to_feed_btn").disabled = false;
681 document.getElementById("top25_feeds_btn").disabled = false;
682 } catch (e) {
683 // this button is not always available, no-op if not found
684 }
685
686 closeInfoBox();
687
688 selectPrefRows('feed', false); // cleanup feed selection
689
690 return false;
691 }
692
693 function feedEditSave() {
694
695 try {
696
697 // FIXME: add parameter validation
698
699 var query = Form.serialize("edit_feed_form");
700
701 notify_progress("Saving feed...");
702
703 new Ajax.Request("backend.php", {
704 parameters: query,
705 onComplete: function(transport) {
706 feedlist_callback2(transport);
707 } });
708
709 closeInfoBox();
710
711 return false;
712
713 } catch (e) {
714 exception_error("feedEditSave", e);
715 }
716 }
717
718 function userEditCancel() {
719
720 selectPrefRows('user', false); // cleanup feed selection
721 closeInfoBox();
722
723 return false;
724 }
725
726 function filterEditCancel() {
727
728 try {
729 document.getElementById("create_filter_btn").disabled = false;
730 selectPrefRows('filter', false); // cleanup feed selection
731 } catch (e) { }
732
733 closeInfoBox();
734
735 return false;
736 }
737
738 function userEditSave() {
739
740 try {
741
742 var login = document.forms["user_edit_form"].login.value;
743
744 if (login.length == 0) {
745 alert(__("Login field cannot be blank."));
746 return;
747 }
748
749 notify_progress("Saving user...");
750
751 closeInfoBox();
752
753 var query = Form.serialize("user_edit_form");
754
755 new Ajax.Request("backend.php", {
756 parameters: query,
757 onComplete: function(transport) {
758 userlist_callback2(transport);
759 } });
760
761 } catch (e) {
762 exception_error("userEditSave", e);
763 }
764
765 return false;
766
767 }
768
769
770 function filterEditSave() {
771
772 try {
773
774 notify_progress("Saving filter...");
775
776 var query = "backend.php?" + Form.serialize("filter_edit_form");
777
778 closeInfoBox();
779
780 document.getElementById("create_filter_btn").disabled = false;
781
782 new Ajax.Request(query, {
783 onComplete: function(transport) {
784 filterlist_callback2(transport);
785 } });
786
787 } catch (e) {
788 exception_error("filterEditSave", e);
789 }
790
791 return false;
792 }
793
794
795 function editSelectedUser() {
796 var rows = getSelectedUsers();
797
798 if (rows.length == 0) {
799 alert(__("No users are selected."));
800 return;
801 }
802
803 if (rows.length > 1) {
804 alert(__("Please select only one user."));
805 return;
806 }
807
808 notify("");
809
810 editUser(rows[0]);
811 }
812
813 function resetSelectedUserPass() {
814
815 try {
816
817 var rows = getSelectedUsers();
818
819 if (rows.length == 0) {
820 alert(__("No users are selected."));
821 return;
822 }
823
824 if (rows.length > 1) {
825 alert(__("Please select only one user."));
826 return;
827 }
828
829 var ok = confirm(__("Reset password of selected user?"));
830
831 if (ok) {
832 notify_progress("Resetting password for selected user...");
833
834 var id = rows[0];
835
836 var query = "backend.php?op=pref-users&subop=resetPass&id=" +
837 param_escape(id);
838
839 new Ajax.Request(query, {
840 onComplete: function(transport) {
841 userlist_callback2(transport);
842 } });
843
844 }
845
846 } catch (e) {
847 exception_error("resetSelectedUserPass", e);
848 }
849 }
850
851 function selectedUserDetails() {
852
853 try {
854
855 var rows = getSelectedUsers();
856
857 if (rows.length == 0) {
858 alert(__("No users are selected."));
859 return;
860 }
861
862 if (rows.length > 1) {
863 alert(__("Please select only one user."));
864 return;
865 }
866
867 notify_progress("Loading, please wait...");
868
869 var id = rows[0];
870
871 var query = "backend.php?op=pref-users&subop=user-details&id=" + id;
872
873 new Ajax.Request(query, {
874 onComplete: function(transport) {
875 infobox_callback2(transport);
876 } });
877 } catch (e) {
878 exception_error("selectedUserDetails", e);
879 }
880 }
881
882
883 function editSelectedFilter() {
884 var rows = getSelectedFilters();
885
886 if (rows.length == 0) {
887 alert(__("No filters are selected."));
888 return;
889 }
890
891 if (rows.length > 1) {
892 alert(__("Please select only one filter."));
893 return;
894 }
895
896 notify("");
897
898 editFilter(rows[0]);
899
900 }
901
902
903 function editSelectedFeed() {
904 var rows = getSelectedFeeds();
905
906 if (rows.length == 0) {
907 alert(__("No feeds are selected."));
908 return;
909 }
910
911 if (rows.length > 1) {
912 alert(__("Please select one feed."));
913 return;
914 }
915
916 notify("");
917
918 editFeed(rows[0]);
919
920 }
921
922 function editSelectedFeeds() {
923
924 try {
925 var rows = getSelectedFeeds();
926
927 if (rows.length == 0) {
928 alert(__("No feeds are selected."));
929 return;
930 }
931
932 notify("");
933
934 disableHotkeys();
935
936 notify_progress("Loading, please wait...");
937
938 var query = "backend.php?op=pref-feeds&subop=editfeeds&ids=" +
939 param_escape(rows.toString());
940
941 new Ajax.Request(query, {
942 onComplete: function(transport) {
943 infobox_callback2(transport);
944 } });
945
946 } catch (e) {
947 exception_error("editSelectedFeeds", e);
948 }
949 }
950
951 function piggie(enable) {
952 if (enable) {
953 debug("I LOVEDED IT!");
954 var piggie = document.getElementById("piggie");
955
956 Element.show(piggie);
957 Position.Center(piggie);
958 Effect.Puff(piggie);
959
960 }
961 }
962
963 function validateOpmlImport() {
964
965 var opml_file = document.getElementById("opml_file");
966
967 if (opml_file.value.length == 0) {
968 alert(__("No OPML file to upload."));
969 return false;
970 } else {
971 return true;
972 }
973 }
974
975 function updateFilterList(sort_key) {
976 try {
977
978 var filter_search = document.getElementById("filter_search");
979 var search = "";
980 if (filter_search) { search = filter_search.value; }
981
982 var query = "backend.php?op=pref-filters&sort=" +
983 param_escape(sort_key) +
984 "&search=" + param_escape(search);
985
986 new Ajax.Request(query, {
987 onComplete: function(transport) {
988 filterlist_callback2(transport);
989 } });
990
991 } catch (e) {
992 exception_error("updateFilterList", e);
993 }
994
995 }
996
997 function updateLabelList(sort_key) {
998
999 try {
1000
1001 var label_search = document.getElementById("label_search");
1002 var search = "";
1003 if (label_search) { search = label_search.value; }
1004
1005 var query = "backend.php?op=pref-labels&sort=" +
1006 param_escape(sort_key) +
1007 "&search=" + param_escape(search);
1008
1009 new Ajax.Request(query, {
1010 onComplete: function(transport) {
1011 labellist_callback2(transport);
1012 } });
1013
1014 } catch (e) {
1015 exception_error("updateLabelList", e);
1016 }
1017 }
1018
1019 function updatePrefsList() {
1020
1021 var query = "backend.php?op=pref-prefs";
1022
1023 new Ajax.Request(query, {
1024 onComplete: function(transport) {
1025 prefslist_callback2(transport);
1026 } });
1027
1028 }
1029
1030 function selectTab(id, noupdate, subop) {
1031
1032 // alert(id);
1033
1034 if (!id) id = active_tab;
1035
1036 try {
1037
1038 try {
1039 var c = document.getElementById('prefContent');
1040 c.scrollTop = 0;
1041 } catch (e) { };
1042
1043 if (!noupdate) {
1044
1045 debug("selectTab: " + id + "(NU: " + noupdate + ")");
1046
1047 notify_progress("Loading, please wait...");
1048
1049 // close active infobox if needed
1050 closeInfoBox();
1051
1052 // clean up all current selections, just in case
1053 active_feed_cat = false;
1054
1055 // Effect.Fade("prefContent", {duration: 1, to: 0.01,
1056 // queue: { position:'end', scope: 'FEED_TAB', limit: 1 } } );
1057
1058 if (id == "feedConfig") {
1059 updateFeedList();
1060 } else if (id == "filterConfig") {
1061 updateFilterList();
1062 } else if (id == "labelConfig") {
1063 updateLabelList();
1064 } else if (id == "genConfig") {
1065 updatePrefsList();
1066 } else if (id == "userConfig") {
1067 updateUsersList();
1068 }
1069 }
1070
1071 /* clean selection from all tabs */
1072
1073 var tabs_holder = document.getElementById("prefTabs");
1074 var tab = tabs_holder.firstChild;
1075
1076 while (tab) {
1077 if (tab.className && tab.className.match("prefsTabSelected")) {
1078 tab.className = "prefsTab";
1079 }
1080 tab = tab.nextSibling;
1081 }
1082
1083 /* mark new tab as selected */
1084
1085 tab = document.getElementById(id + "Tab");
1086
1087 if (tab) {
1088 if (!tab.className.match("Selected")) {
1089 tab.className = tab.className + "Selected";
1090 }
1091 }
1092
1093 active_tab = id;
1094
1095 } catch (e) {
1096 exception_error("selectTab", e);
1097 }
1098 }
1099
1100 function backend_sanity_check_callback2(transport) {
1101
1102 try {
1103
1104 if (sanity_check_done) {
1105 fatalError(11, "Sanity check request received twice. This can indicate "+
1106 "presence of Firebug or some other disrupting extension. "+
1107 "Please disable it and try again.");
1108 return;
1109 }
1110
1111 if (!transport.responseXML) {
1112 fatalError(3, "Sanity Check: Received reply is not XML",
1113 transport.responseText);
1114 return;
1115 }
1116
1117 var reply = transport.responseXML.firstChild.firstChild;
1118
1119 if (!reply) {
1120 fatalError(3, "Sanity Check: Invalid RPC reply", transport.responseText);
1121 return;
1122 }
1123
1124 var error_code = reply.getAttribute("error-code");
1125
1126 if (error_code && error_code != 0) {
1127 return fatalError(error_code, reply.getAttribute("error-msg"));
1128 }
1129
1130 debug("sanity check ok");
1131
1132 var params = reply.nextSibling;
1133
1134 if (params) {
1135 debug('reading init-params...');
1136 var param = params.firstChild;
1137
1138 while (param) {
1139 var k = param.getAttribute("key");
1140 var v = param.getAttribute("value");
1141 debug(k + " => " + v);
1142 init_params[k] = v;
1143 param = param.nextSibling;
1144 }
1145 }
1146
1147 sanity_check_done = true;
1148
1149 init_second_stage();
1150
1151 } catch (e) {
1152 exception_error("backend_sanity_check_callback", e);
1153 }
1154 }
1155
1156 function init_second_stage() {
1157
1158 try {
1159 active_tab = getInitParam("prefs_active_tab");
1160 if (!document.getElementById(active_tab+"Tab")) active_tab = "genConfig";
1161 if (!active_tab || active_tab == '0') active_tab = "genConfig";
1162
1163 document.onkeydown = pref_hotkey_handler;
1164
1165 var tab = getURLParam('tab');
1166
1167 caller_subop = getURLParam('subop');
1168
1169 if (getURLParam("subopparam")) {
1170 caller_subop = caller_subop + ":" + getURLParam("subopparam");
1171 }
1172
1173 if (tab) {
1174 active_tab = tab;
1175 }
1176
1177 if (navigator.userAgent.match("Opera")) {
1178 setTimeout("selectTab()", 500);
1179 } else {
1180 selectTab(active_tab);
1181 }
1182 notify("");
1183
1184 loading_set_progress(60);
1185
1186 } catch (e) {
1187 exception_error("init_second_stage", e);
1188 }
1189 }
1190
1191 function init() {
1192
1193 try {
1194
1195 if (arguments.callee.done) return;
1196 arguments.callee.done = true;
1197
1198 if (getURLParam('debug')) {
1199 Element.show("debug_output");
1200 debug('debug mode activated');
1201 }
1202
1203 loading_set_progress(30);
1204
1205 var query = "backend.php?op=rpc&subop=sanityCheck";
1206
1207 new Ajax.Request(query, {
1208 onComplete: function(transport) {
1209 backend_sanity_check_callback2(transport);
1210 } });
1211
1212 } catch (e) {
1213 exception_error("init", e);
1214 }
1215 }
1216
1217 function categorizeSelectedFeeds() {
1218
1219 var sel_rows = getSelectedFeeds();
1220
1221 var cat_sel = document.getElementById("sfeed_set_fcat");
1222 var cat_id = cat_sel[cat_sel.selectedIndex].value;
1223
1224 if (sel_rows.length > 0) {
1225
1226 notify_progress("Changing category of selected feeds...");
1227
1228 var query = "backend.php?op=pref-feeds&subop=categorize&ids="+
1229 param_escape(sel_rows.toString()) + "&cat_id=" + param_escape(cat_id);
1230
1231 new Ajax.Request(query, {
1232 onComplete: function(transport) {
1233 feedlist_callback2(transport);
1234 } });
1235
1236 } else {
1237
1238 alert(__("No feeds are selected."));
1239
1240 }
1241
1242 }
1243
1244 function validatePrefsReset() {
1245 try {
1246 var ok = confirm(__("Reset to defaults?"));
1247
1248 if (ok) {
1249
1250 var query = Form.serialize("pref_prefs_form");
1251 query = query + "&subop=reset-config";
1252 debug(query);
1253
1254 new Ajax.Request("backend.php", {
1255 parameters: query,
1256 onComplete: function(transport) {
1257 prefs_reset_callback2(transport);
1258 } });
1259
1260 }
1261
1262 } catch (e) {
1263 exception_error("validatePrefsSave", e);
1264 }
1265
1266 return false;
1267
1268 }
1269
1270 function feedBrowserSubscribe() {
1271 try {
1272
1273 var selected = getSelectedFeedsFromBrowser();
1274
1275 if (selected.length > 0) {
1276 closeInfoBox();
1277
1278 var query = "backend.php?op=pref-feeds&subop=massSubscribe&ids="+
1279 param_escape(selected.toString());
1280
1281 new Ajax.Request(query, {
1282 onComplete: function(transport) {
1283 feedlist_callback2(transport);
1284 } });
1285
1286 } else {
1287 alert(__("No feeds are selected."));
1288 }
1289
1290 } catch (e) {
1291 exception_error("feedBrowserSubscribe", e);
1292 }
1293 }
1294
1295 function updateBigFeedBrowserBtn() {
1296 notify_progress("Loading, please wait...");
1297 return updateBigFeedBrowser();
1298 }
1299
1300 function selectPrefRows(kind, select) {
1301
1302 if (kind) {
1303 var opbarid = false;
1304 var nchk = false;
1305 var nrow = false;
1306 var lname = false;
1307
1308 if (kind == "feed") {
1309 opbarid = "feedOpToolbar";
1310 nrow = "FEEDR-";
1311 nchk = "FRCHK-";
1312 lname = "prefFeedList";
1313 } else if (kind == "fcat") {
1314 opbarid = "catOpToolbar";
1315 nrow = "FCATR-";
1316 nchk = "FCCHK-";
1317 lname = "prefFeedCatList";
1318 } else if (kind == "filter") {
1319 opbarid = "filterOpToolbar";
1320 nrow = "FILRR-";
1321 nchk = "FICHK-";
1322 lname = "prefFilterList";
1323 } else if (kind == "label") {
1324 opbarid = "labelOpToolbar";
1325 nrow = "LILRR-";
1326 nchk = "LICHK-";
1327 lname = "prefLabelList";
1328 } else if (kind == "user") {
1329 opbarid = "userOpToolbar";
1330 nrow = "UMRR-";
1331 nchk = "UMCHK-";
1332 lname = "prefUserList";
1333 }
1334
1335 if (opbarid) {
1336 selectTableRowsByIdPrefix(lname, nrow, nchk, select);
1337 disableContainerChildren(opbarid, !select);
1338 }
1339
1340 }
1341 }
1342
1343
1344 function toggleSelectPrefRow(sender, kind) {
1345
1346 toggleSelectRow(sender);
1347
1348 if (kind) {
1349 var opbarid = false;
1350 var nsel = -1;
1351
1352 if (kind == "feed") {
1353 opbarid = "feedOpToolbar";
1354 nsel = getSelectedFeeds();
1355 } else if (kind == "fcat") {
1356 opbarid = "catOpToolbar";
1357 nsel = getSelectedFeedCats();
1358 } else if (kind == "filter") {
1359 opbarid = "filterOpToolbar";
1360 nsel = getSelectedFilters();
1361 } else if (kind == "label") {
1362 opbarid = "labelOpToolbar";
1363 nsel = getSelectedLabels();
1364 } else if (kind == "user") {
1365 opbarid = "userOpToolbar";
1366 nsel = getSelectedUsers();
1367 }
1368
1369 if (opbarid && nsel != -1) {
1370 disableContainerChildren(opbarid, nsel == false);
1371 }
1372
1373 }
1374 }
1375
1376 function toggleSelectFBListRow(sender) {
1377 toggleSelectListRow(sender);
1378 disableContainerChildren("fbrOpToolbar", getSelectedFeedsFromBrowser() == 0);
1379 }
1380
1381 var seq = "";
1382
1383 function pref_hotkey_handler(e) {
1384 try {
1385
1386 var keycode;
1387 var shift_key = false;
1388
1389 try {
1390 shift_key = e.shiftKey;
1391 } catch (e) {
1392
1393 }
1394
1395 if (window.event) {
1396 keycode = window.event.keyCode;
1397 } else if (e) {
1398 keycode = e.which;
1399 }
1400
1401 var keychar = String.fromCharCode(keycode);
1402
1403 if (keycode == 27) { // escape
1404 if (Element.visible("hotkey_help_overlay")) {
1405 Element.hide("hotkey_help_overlay");
1406 }
1407 hotkey_prefix = false;
1408 closeInfoBox();
1409 }
1410
1411 if (!hotkeys_enabled) {
1412 debug("hotkeys disabled");
1413 return;
1414 }
1415
1416 if (keycode == 16) return; // ignore lone shift
1417
1418 if ((keycode == 67 || keycode == 71) && !hotkey_prefix) {
1419 hotkey_prefix = keycode;
1420 debug("KP: PREFIX=" + keycode + " CHAR=" + keychar);
1421 return;
1422 }
1423
1424 if (Element.visible("hotkey_help_overlay")) {
1425 Element.hide("hotkey_help_overlay");
1426 }
1427
1428 if (keycode == 13 || keycode == 27) {
1429 seq = "";
1430 } else {
1431 seq = seq + "" + keycode;
1432 }
1433
1434 /* Global hotkeys */
1435
1436 if (!hotkey_prefix) {
1437
1438 if (keycode == 68 && shift_key) { // d
1439 if (!Element.visible("debug_output")) {
1440 Element.show("debug_output");
1441 debug('debug mode activated');
1442 } else {
1443 Element.hide("debug_output");
1444 }
1445 return;
1446 }
1447
1448 if ((keycode == 191 || keychar == '?') && shift_key) { // ?
1449 if (!Element.visible("hotkey_help_overlay")) {
1450 //Element.show("hotkey_help_overlay");
1451 Effect.Appear("hotkey_help_overlay", {duration : 0.3});
1452 } else {
1453 Element.hide("hotkey_help_overlay");
1454 }
1455 return false;
1456 }
1457
1458 if (keycode == 191 || keychar == '/') { // /
1459 var search_boxes = new Array("label_search",
1460 "feed_search", "filter_search", "user_search", "feed_browser_search");
1461
1462 for (var i = 0; i < search_boxes.length; i++) {
1463 var elem = document.getElementById(search_boxes[i]);
1464 if (elem) {
1465 focus_element(search_boxes[i]);
1466 return false;
1467 }
1468 }
1469 }
1470 }
1471
1472 /* Prefix c */
1473
1474 if (hotkey_prefix == 67) { // c
1475 hotkey_prefix = false;
1476
1477 if (keycode == 70) { // f
1478 displayDlg("quickAddFilter");
1479 return false;
1480 }
1481
1482 if (keycode == 83) { // s
1483 displayDlg("quickAddFeed");
1484 return false;
1485 }
1486
1487 /* if (keycode == 76) { // l
1488 displayDlg("quickAddLabel");
1489 return false;
1490 } */
1491
1492 if (keycode == 85) { // u
1493 // no-op
1494 }
1495
1496 if (keycode == 67) { // c
1497 editFeedCats();
1498 return false;
1499 }
1500
1501 if (keycode == 84 && shift_key) { // T
1502 browseFeeds();
1503 return false;
1504 }
1505
1506 }
1507
1508 /* Prefix g */
1509
1510 if (hotkey_prefix == 71) { // g
1511
1512 hotkey_prefix = false;
1513
1514 if (keycode == 49 && document.getElementById("genConfigTab")) { // 1
1515 selectTab("genConfig");
1516 return false;
1517 }
1518
1519 if (keycode == 50 && document.getElementById("feedConfigTab")) { // 2
1520 selectTab("feedConfig");
1521 return false;
1522 }
1523
1524 if (keycode == 51 && document.getElementById("filterConfigTab")) { // 4
1525 selectTab("filterConfig");
1526 return false;
1527 }
1528
1529 if (keycode == 52 && document.getElementById("labelConfigTab")) { // 5
1530 selectTab("labelConfig");
1531 return false;
1532 }
1533
1534 if (keycode == 53 && document.getElementById("userConfigTab")) { // 6
1535 selectTab("userConfig");
1536 return false;
1537 }
1538
1539 if (keycode == 88) { // x
1540 return gotoMain();
1541 }
1542
1543 }
1544
1545 if (document.getElementById("piggie")) {
1546
1547 if (seq.match("807371717369")) {
1548 seq = "";
1549 piggie(true);
1550 } else {
1551 piggie(false);
1552 }
1553 }
1554
1555 if (hotkey_prefix) {
1556 debug("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
1557 } else {
1558 debug("KP: CODE=" + keycode + " CHAR=" + keychar);
1559 }
1560
1561 } catch (e) {
1562 exception_error("pref_hotkey_handler", e);
1563 }
1564 }
1565
1566 function editFeedCats() {
1567 try {
1568 document.getElementById("subscribe_to_feed_btn").disabled = true;
1569
1570 try {
1571 document.getElementById("top25_feeds_btn").disabled = true;
1572 } catch (e) {
1573 // this button is not always available, no-op if not found
1574 }
1575
1576 var query = "backend.php?op=pref-feeds&subop=editCats";
1577
1578 new Ajax.Request(query, {
1579 onComplete: function(transport) {
1580 infobox_feed_cat_callback2(transport);
1581 } });
1582 } catch (e) {
1583 exception_error("editFeedCats", e);
1584 }
1585 }
1586
1587 function showFeedsWithErrors() {
1588 displayDlg('feedUpdateErrors');
1589 }
1590
1591 function changeUserPassword() {
1592
1593 try {
1594
1595 var f = document.forms["change_pass_form"];
1596
1597 if (f) {
1598 if (f.OLD_PASSWORD.value == "") {
1599 new Effect.Highlight(f.OLD_PASSWORD);
1600 notify_error("Old password cannot be blank.");
1601 return false;
1602 }
1603
1604 if (f.NEW_PASSWORD.value == "") {
1605 new Effect.Highlight(f.NEW_PASSWORD);
1606 notify_error("New password cannot be blank.");
1607 return false;
1608 }
1609
1610 if (f.CONFIRM_PASSWORD.value == "") {
1611 new Effect.Highlight(f.CONFIRM_PASSWORD);
1612 notify_error("Entered passwords do not match.");
1613 return false;
1614 }
1615
1616 if (f.CONFIRM_PASSWORD.value != f.NEW_PASSWORD.value) {
1617 new Effect.Highlight(f.CONFIRM_PASSWORD);
1618 new Effect.Highlight(f.NEW_PASSWORD);
1619 notify_error("Entered passwords do not match.");
1620 return false;
1621 }
1622
1623 }
1624
1625 var query = Form.serialize("change_pass_form");
1626
1627 notify_progress("Trying to change password...");
1628
1629 new Ajax.Request("backend.php", {
1630 parameters: query,
1631 onComplete: function(transport) {
1632 changepass_callback2(transport);
1633 } });
1634
1635
1636 } catch (e) {
1637 exception_error("changeUserPassword", e);
1638 }
1639
1640 return false;
1641 }
1642
1643 function changeUserEmail() {
1644
1645 try {
1646
1647 var query = Form.serialize("change_email_form");
1648
1649 notify_progress("Trying to change e-mail...");
1650
1651 new Ajax.Request("backend.php", {
1652 parameters: query,
1653 onComplete: function(transport) {
1654 notify_callback2(transport);
1655 } });
1656
1657 } catch (e) {
1658 exception_error("changeUserPassword", e);
1659 }
1660
1661 return false;
1662
1663 }
1664
1665 function feedlistToggleSLAT() {
1666 notify_progress("Loading, please wait...");
1667 updateFeedList()
1668 }
1669
1670 function pubRegenKey() {
1671
1672 var ok = confirm(__("Replace current publishing address with a new one?"));
1673
1674 if (ok) {
1675
1676 notify_progress("Trying to change address...");
1677
1678 var query = "backend.php?op=rpc&subop=regenPubKey";
1679
1680 new Ajax.Request(query, {
1681 onComplete: function(transport) {
1682 replace_pubkey_callback(transport);
1683 } });
1684
1685 }
1686
1687 return false;
1688 }
1689
1690 function validatePrefsSave() {
1691 try {
1692
1693 var ok = confirm(__("Save current configuration?"));
1694
1695 if (ok) {
1696
1697 var query = Form.serialize("pref_prefs_form");
1698 query = query + "&subop=save-config";
1699 debug(query);
1700
1701 new Ajax.Request("backend.php", {
1702 parameters: query,
1703 onComplete: function(transport) {
1704 notify_callback2(transport);
1705 } });
1706
1707 }
1708
1709 } catch (e) {
1710 exception_error("validatePrefsSave", e);
1711 }
1712
1713 return false;
1714 }
1715
1716 function feedActionChange() {
1717 try {
1718 var chooser = document.getElementById("feedActionChooser");
1719 var opid = chooser[chooser.selectedIndex].value;
1720
1721 chooser.selectedIndex = 0;
1722 feedActionGo(opid);
1723 } catch (e) {
1724 exception_error("feedActionChange", e);
1725 }
1726 }
1727
1728 function feedActionGo(op) {
1729 try {
1730 if (op == "facEdit") {
1731
1732 var rows = getSelectedFeeds();
1733
1734 if (rows.length > 1) {
1735 editSelectedFeeds();
1736 } else {
1737 editSelectedFeed();
1738 }
1739 }
1740
1741 if (op == "facClear") {
1742 clearSelectedFeeds();
1743 }
1744
1745 if (op == "facPurge") {
1746 purgeSelectedFeeds();
1747 }
1748
1749 if (op == "facEditCats") {
1750 editFeedCats();
1751 }
1752
1753 if (op == "facRescore") {
1754 rescoreSelectedFeeds();
1755 }
1756
1757 if (op == "facUnsubscribe") {
1758 removeSelectedFeeds();
1759 }
1760
1761 } catch (e) {
1762 exception_error("feedActionGo", e);
1763
1764 }
1765 }
1766
1767 function clearFeedArticles(feed_id) {
1768
1769 notify_progress("Clearing feed...");
1770
1771 var query = "backend.php?op=pref-feeds&quiet=1&subop=clear&id=" + feed_id;
1772
1773 new Ajax.Request(query, {
1774 onComplete: function(transport) {
1775 notify('');
1776 } });
1777
1778 return false;
1779 }
1780
1781 function rescoreSelectedFeeds() {
1782
1783 var sel_rows = getSelectedFeeds();
1784
1785 if (sel_rows.length > 0) {
1786
1787 //var ok = confirm(__("Rescore last 100 articles in selected feeds?"));
1788 var ok = confirm(__("Rescore articles in selected feeds?"));
1789
1790 if (ok) {
1791 notify_progress("Rescoring selected feeds...", true);
1792
1793 var query = "backend.php?op=pref-feeds&subop=rescore&quiet=1&ids="+
1794 param_escape(sel_rows.toString());
1795
1796 new Ajax.Request(query, {
1797 onComplete: function(transport) {
1798 notify_callback2(transport);
1799 } });
1800
1801 }
1802 } else {
1803 alert(__("No feeds are selected."));
1804 }
1805
1806 return false;
1807 }
1808
1809 function rescore_all_feeds() {
1810 var ok = confirm(__("Rescore all articles? This operation may take a lot of time."));
1811
1812 if (ok) {
1813 notify_progress("Rescoring feeds...", true);
1814
1815 var query = "backend.php?op=pref-feeds&subop=rescoreAll&quiet=1";
1816
1817 new Ajax.Request(query, {
1818 onComplete: function(transport) {
1819 notify_callback2(transport);
1820 } });
1821 }
1822 }
1823
1824 function removeFilter(id, title) {
1825
1826 try {
1827
1828 var msg = __("Remove filter %s?").replace("%s", title);
1829
1830 var ok = confirm(msg);
1831
1832 if (ok) {
1833 closeInfoBox();
1834
1835 notify_progress("Removing filter...");
1836
1837 var query = "backend.php?op=pref-filters&subop=remove&ids="+
1838 param_escape(id);
1839
1840 new Ajax.Request(query, {
1841 onComplete: function(transport) {
1842 filterlist_callback2(transport);
1843 } });
1844
1845 }
1846
1847 } catch (e) {
1848 exception_error("removeFilter", e);
1849 }
1850
1851 return false;
1852 }
1853
1854 function unsubscribeFeed(id, title) {
1855
1856 try {
1857
1858 var msg = __("Unsubscribe from %s?").replace("%s", title);
1859
1860 var ok = confirm(msg);
1861
1862 if (ok) {
1863 closeInfoBox();
1864
1865 notify_progress("Removing feed...");
1866
1867 var query = "backend.php?op=pref-feeds&subop=remove&ids="+
1868 param_escape(id);
1869
1870 new Ajax.Request(query, {
1871 onComplete: function(transport) {
1872 feedlist_callback2(transport);
1873 } });
1874 }
1875
1876 } catch (e) {
1877 exception_error("unsubscribeFeed", e);
1878 }
1879
1880 return false;
1881
1882 }
1883
1884 function feedsEditSave() {
1885 try {
1886
1887 var ok = confirm(__("Save changes to selected feeds?"));
1888
1889 if (ok) {
1890
1891 var f = document.forms["batch_edit_feed_form"];
1892
1893 var query = Form.serialize("batch_edit_feed_form");
1894
1895 /* Form.serialize ignores unchecked checkboxes */
1896
1897 if (!query.match("&hidden=") &&
1898 f.hidden.disabled == false) {
1899 query = query + "&hidden=false";
1900 }
1901
1902 if (!query.match("&rtl_content=") &&
1903 f.rtl_content.disabled == false) {
1904 query = query + "&rtl_content=false";
1905 }
1906
1907 if (!query.match("&private=") &&
1908 f.private.disabled == false) {
1909 query = query + "&private=false";
1910 }
1911
1912 if (!query.match("&cache_images=") &&
1913 f.cache_images.disabled == false) {
1914 query = query + "&cache_images=false";
1915 }
1916
1917 if (!query.match("&include_in_digest=") &&
1918 f.include_in_digest.disabled == false) {
1919 query = query + "&include_in_digest=false";
1920 }
1921
1922 closeInfoBox();
1923
1924 notify_progress("Saving feeds...");
1925
1926 new Ajax.Request("backend.php", {
1927 parameters: query,
1928 onComplete: function(transport) {
1929 feedlist_callback2(transport);
1930 } });
1931
1932 }
1933
1934 return false;
1935 } catch (e) {
1936 exception_error("feedsEditSave", e);
1937 }
1938 }
1939
1940 function batchFeedsToggleField(cb, elem, label) {
1941 try {
1942 var f = document.forms["batch_edit_feed_form"];
1943 var l = document.getElementById(label);
1944
1945 if (cb.checked) {
1946 f[elem].disabled = false;
1947
1948 if (l) {
1949 l.className = "";
1950 };
1951
1952 // new Effect.Highlight(f[elem], {duration: 1, startcolor: "#fff7d5",
1953 // queue: { position:'end', scope: 'BPEFQ', limit: 1 } } );
1954
1955 } else {
1956 f[elem].disabled = true;
1957
1958 if (l) {
1959 l.className = "insensitive";
1960 };
1961
1962 }
1963 } catch (e) {
1964 exception_error("batchFeedsToggleField", e);
1965 }
1966 }
1967
1968