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