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