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