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