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