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