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