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