1 var init_params = new Array();
3 var hotkey_prefix = false;
4 var hotkey_prefix_pressed = false;
8 function notify_callback2(transport, sticky) {
9 notify_info(transport.responseText, sticky);
12 function updateFeedList(sort_key) {
14 var user_search = $("feed_search");
16 if (user_search) { search = user_search.value; }
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);
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);
37 function updateUsersList(sort_key) {
39 var user_search = $("user_search");
41 if (user_search) { search = user_search.value; }
43 var query = "?op=pref-users&sort="
44 + param_escape(sort_key) +
45 "&search=" + param_escape(search);
47 new Ajax.Request("backend.php", {
49 onComplete: function(transport) {
50 dijit.byId('userConfigTab').attr('content', transport.responseText);
51 selectTab("userConfig", true)
56 exception_error("updateUsersList", e);
64 var login = prompt(__("Please enter login:"), "");
71 alert(__("Can't create user: no login specified."));
75 notify_progress("Adding user...");
77 var query = "?op=pref-users&method=add&login=" +
80 new Ajax.Request("backend.php", {
82 onComplete: function(transport) {
83 notify_callback2(transport);
88 exception_error("addUser", e);
92 function editUser(id, event) {
95 if (!event || !event.ctrlKey) {
97 notify_progress("Loading, please wait...");
99 selectTableRows('prefUserList', 'none');
100 selectTableRowById('UMRR-'+id, 'UMCHK-'+id, true);
102 var query = "?op=pref-users&method=edit&id=" +
105 new Ajax.Request("backend.php", {
107 onComplete: function(transport) {
108 infobox_callback2(transport);
109 document.forms['user_edit_form'].login.focus();
112 } else if (event.ctrlKey) {
113 var cb = $('UMCHK-' + id);
114 cb.checked = !cb.checked;
119 exception_error("editUser", e);
124 function editFilter(id) {
127 var query = "backend.php?op=pref-filters&method=edit&id=" + param_escape(id);
129 if (dijit.byId("feedEditDlg"))
130 dijit.byId("feedEditDlg").destroyRecursive();
132 if (dijit.byId("filterEditDlg"))
133 dijit.byId("filterEditDlg").destroyRecursive();
135 dialog = new dijit.Dialog({
137 title: __("Edit Filter"),
138 style: "width: 600px",
139 editRule: function(e) {
140 var li = e.parentNode;
141 var rule = li.getElementsByTagName("INPUT")[1].value;
142 addFilterRule(li, rule);
144 editAction: function(e) {
145 var li = e.parentNode;
146 var action = li.getElementsByTagName("INPUT")[1].value;
147 addFilterAction(li, action);
149 removeFilter: function() {
150 var msg = __("Remove filter?");
155 notify_progress("Removing filter...");
157 var id = this.attr('value').id;
159 var query = "?op=pref-filters&method=remove&ids="+
162 new Ajax.Request("backend.php", {
164 onComplete: function(transport) {
169 addAction: function() { addFilterAction(); },
170 addRule: function() { addFilterRule(); },
171 deleteAction: function() {
172 $$("#filterDlg_Actions li.[class*=Selected]").each(function(e) { e.parentNode.removeChild(e) });
174 deleteRule: function() {
175 $$("#filterDlg_Matches li.[class*=Selected]").each(function(e) { e.parentNode.removeChild(e) });
177 execute: function() {
178 if (this.validate()) {
180 notify_progress("Saving data...", true);
182 var query = dojo.formToQuery("filter_edit_form");
186 new Ajax.Request("backend.php", {
188 onComplete: function(transport) {
200 exception_error("editFilter", e);
204 function getSelectedLabels() {
205 var tree = dijit.byId("labelTree");
206 var items = tree.model.getCheckedItems();
209 items.each(function(item) {
210 rv.push(tree.model.store.getValue(item, 'bare_id'));
216 function getSelectedUsers() {
217 return getSelectedTableRowIds("prefUserList");
220 function getSelectedFeeds() {
221 var tree = dijit.byId("feedTree");
222 var items = tree.model.getCheckedItems();
225 items.each(function(item) {
226 if (item.id[0].match("FEED:"))
227 rv.push(tree.model.store.getValue(item, 'bare_id'));
233 function getSelectedFilters() {
234 var tree = dijit.byId("filterTree");
235 var items = tree.model.getCheckedItems();
238 items.each(function(item) {
239 rv.push(tree.model.store.getValue(item, 'bare_id'));
246 /* function getSelectedFeedCats() {
247 return getSelectedTableRowIds("prefFeedCatList");
250 function removeSelectedLabels() {
252 var sel_rows = getSelectedLabels();
254 if (sel_rows.length > 0) {
256 var ok = confirm(__("Remove selected labels?"));
259 notify_progress("Removing selected labels...");
261 var query = "?op=pref-labels&method=remove&ids="+
262 param_escape(sel_rows.toString());
264 new Ajax.Request("backend.php", {
266 onComplete: function(transport) {
272 alert(__("No labels are selected."));
278 function removeSelectedUsers() {
282 var sel_rows = getSelectedUsers();
284 if (sel_rows.length > 0) {
286 var ok = confirm(__("Remove selected users? Neither default admin nor your account will be removed."));
289 notify_progress("Removing selected users...");
291 var query = "?op=pref-users&method=remove&ids="+
292 param_escape(sel_rows.toString());
294 new Ajax.Request("backend.php", {
296 onComplete: function(transport) {
303 alert(__("No users are selected."));
307 exception_error("removeSelectedUsers", e);
313 function removeSelectedFilters() {
317 var sel_rows = getSelectedFilters();
319 if (sel_rows.length > 0) {
321 var ok = confirm(__("Remove selected filters?"));
324 notify_progress("Removing selected filters...");
326 var query = "?op=pref-filters&method=remove&ids="+
327 param_escape(sel_rows.toString());
329 new Ajax.Request("backend.php", {
331 onComplete: function(transport) {
336 alert(__("No filters are selected."));
340 exception_error("removeSelectedFilters", e);
347 function removeSelectedFeeds() {
351 var sel_rows = getSelectedFeeds();
353 if (sel_rows.length > 0) {
355 var ok = confirm(__("Unsubscribe from selected feeds?"));
359 notify_progress("Unsubscribing from selected feeds...", true);
361 var query = "?op=pref-feeds&method=remove&ids="+
362 param_escape(sel_rows.toString());
366 new Ajax.Request("backend.php", {
368 onComplete: function(transport) {
374 alert(__("No feeds are selected."));
378 exception_error("removeSelectedFeeds", e);
384 function clearSelectedFeeds() {
386 var sel_rows = getSelectedFeeds();
388 if (sel_rows.length > 1) {
389 alert(__("Please select only one feed."));
393 if (sel_rows.length > 0) {
395 var ok = confirm(__("Erase all non-starred articles in selected feed?"));
398 notify_progress("Clearing selected feed...");
399 clearFeedArticles(sel_rows[0]);
404 alert(__("No feeds are selected."));
411 function purgeSelectedFeeds() {
413 var sel_rows = getSelectedFeeds();
415 if (sel_rows.length > 0) {
417 var pr = prompt(__("How many days of articles to keep (0 - use default)?"), "0");
419 if (pr != undefined) {
420 notify_progress("Purging selected feed...");
422 var query = "?op=rpc&method=purge&ids="+
423 param_escape(sel_rows.toString()) + "&days=" + pr;
427 new Ajax.Request("prefs.php", {
429 onComplete: function(transport) {
436 alert(__("No feeds are selected."));
443 function userEditCancel() {
448 function userEditSave() {
452 var login = document.forms["user_edit_form"].login.value;
454 if (login.length == 0) {
455 alert(__("Login field cannot be blank."));
459 notify_progress("Saving user...");
463 var query = Form.serialize("user_edit_form");
465 new Ajax.Request("backend.php", {
467 onComplete: function(transport) {
472 exception_error("userEditSave", e);
480 function editSelectedUser() {
481 var rows = getSelectedUsers();
483 if (rows.length == 0) {
484 alert(__("No users are selected."));
488 if (rows.length > 1) {
489 alert(__("Please select only one user."));
498 function resetSelectedUserPass() {
502 var rows = getSelectedUsers();
504 if (rows.length == 0) {
505 alert(__("No users are selected."));
509 if (rows.length > 1) {
510 alert(__("Please select only one user."));
514 var ok = confirm(__("Reset password of selected user?"));
517 notify_progress("Resetting password for selected user...");
521 var query = "?op=pref-users&method=resetPass&id=" +
524 new Ajax.Request("backend.php", {
526 onComplete: function(transport) {
527 notify_info(transport.responseText);
533 exception_error("resetSelectedUserPass", e);
537 function selectedUserDetails() {
541 var rows = getSelectedUsers();
543 if (rows.length == 0) {
544 alert(__("No users are selected."));
548 if (rows.length > 1) {
549 alert(__("Please select only one user."));
553 notify_progress("Loading, please wait...");
557 var query = "?op=pref-users&method=userdetails&id=" + id;
559 new Ajax.Request("backend.php", {
561 onComplete: function(transport) {
562 infobox_callback2(transport);
565 exception_error("selectedUserDetails", e);
570 function editSelectedFilter() {
571 var rows = getSelectedFilters();
573 if (rows.length == 0) {
574 alert(__("No filters are selected."));
578 if (rows.length > 1) {
579 alert(__("Please select only one filter."));
589 function joinSelectedFilters() {
590 var rows = getSelectedFilters();
592 if (rows.length == 0) {
593 alert(__("No filters are selected."));
597 var ok = confirm(__("Combine selected filters?"));
600 notify_progress("Joining filters...");
602 var query = "?op=pref-filters&method=join&ids="+
603 param_escape(rows.toString());
607 new Ajax.Request("backend.php", {
609 onComplete: function(transport) {
615 function editSelectedFeed() {
616 var rows = getSelectedFeeds();
618 if (rows.length == 0) {
619 alert(__("No feeds are selected."));
623 if (rows.length > 1) {
624 return editSelectedFeeds();
629 editFeed(rows[0], {});
633 function editSelectedFeeds() {
636 var rows = getSelectedFeeds();
638 if (rows.length == 0) {
639 alert(__("No feeds are selected."));
643 notify_progress("Loading, please wait...");
645 var query = "backend.php?op=pref-feeds&method=editfeeds&ids=" +
646 param_escape(rows.toString());
650 if (dijit.byId("feedEditDlg"))
651 dijit.byId("feedEditDlg").destroyRecursive();
653 new Ajax.Request("backend.php", {
655 onComplete: function(transport) {
659 var dialog = new dijit.Dialog({
661 title: __("Edit Multiple Feeds"),
662 style: "width: 600px",
663 getChildByName: function (name) {
665 this.getChildren().each(
667 if (child.name == name) {
674 toggleField: function (checkbox, elem, label) {
675 this.getChildByName(elem).attr('disabled', !checkbox.checked);
678 if (checkbox.checked)
679 $(label).removeClassName('insensitive');
681 $(label).addClassName('insensitive');
684 execute: function() {
685 if (this.validate() && confirm(__("Save changes to selected feeds?"))) {
686 var query = dojo.objectToQuery(this.attr('value'));
688 /* Form.serialize ignores unchecked checkboxes */
690 if (!query.match("&rtl_content=") &&
691 this.getChildByName('rtl_content').attr('disabled') == false) {
692 query = query + "&rtl_content=false";
695 if (!query.match("&private=") &&
696 this.getChildByName('private').attr('disabled') == false) {
697 query = query + "&private=false";
701 if (!query.match("&cache_images=") &&
702 this.getChildByName('cache_images').attr('disabled') == false) {
703 query = query + "&cache_images=false";
707 if (!query.match("&include_in_digest=") &&
708 this.getChildByName('include_in_digest').attr('disabled') == false) {
709 query = query + "&include_in_digest=false";
712 if (!query.match("&always_display_enclosures=") &&
713 this.getChildByName('always_display_enclosures').attr('disabled') == false) {
714 query = query + "&always_display_enclosures=false";
717 if (!query.match("&mark_unread_on_update=") &&
718 this.getChildByName('mark_unread_on_update').attr('disabled') == false) {
719 query = query + "&mark_unread_on_update=false";
722 if (!query.match("&update_on_checksum_change=") &&
723 this.getChildByName('update_on_checksum_change').attr('disabled') == false) {
724 query = query + "&update_on_checksum_change=false";
729 notify_progress("Saving data...", true);
731 new Ajax.Request("backend.php", {
733 onComplete: function(transport) {
739 content: transport.responseText});
746 exception_error("editSelectedFeeds", e);
750 function piggie(enable) {
752 console.log("I LOVEDED IT!");
753 var piggie = $("piggie");
755 Element.show(piggie);
756 Position.Center(piggie);
762 function opmlImportComplete(iframe) {
764 if (!iframe.contentDocument.body.innerHTML) return false;
766 Element.show(iframe);
770 if (dijit.byId('opmlImportDlg'))
771 dijit.byId('opmlImportDlg').destroyRecursive();
773 var content = iframe.contentDocument.body.innerHTML;
775 dialog = new dijit.Dialog({
777 title: __("OPML Import"),
778 style: "width: 600px",
779 onCancel: function() {
784 execute: function() {
795 exception_error("opmlImportComplete", e);
799 function opmlImport() {
801 var opml_file = $("opml_file");
803 if (opml_file.value.length == 0) {
804 alert(__("Please choose an OPML file first."));
807 notify_progress("Importing, please wait...", true);
809 Element.show("upload_iframe");
815 function importData() {
817 var file = $("export_file");
819 if (file.value.length == 0) {
820 alert(__("Please choose the file first."));
823 notify_progress("Importing, please wait...", true);
825 Element.show("data_upload_iframe");
832 function updateFilterList() {
833 var user_search = $("filter_search");
835 if (user_search) { search = user_search.value; }
837 new Ajax.Request("backend.php", {
838 parameters: "?op=pref-filters&search=" + param_escape(search),
839 onComplete: function(transport) {
840 dijit.byId('filterConfigTab').attr('content', transport.responseText);
845 function updateLabelList() {
846 new Ajax.Request("backend.php", {
847 parameters: "?op=pref-labels",
848 onComplete: function(transport) {
849 dijit.byId('labelConfigTab').attr('content', transport.responseText);
854 function updatePrefsList() {
855 new Ajax.Request("backend.php", {
856 parameters: "?op=pref-prefs",
857 onComplete: function(transport) {
858 dijit.byId('genConfigTab').attr('content', transport.responseText);
863 function selectTab(id, noupdate, method) {
866 notify_progress("Loading, please wait...");
868 if (id == "feedConfig") {
870 } else if (id == "filterConfig") {
872 } else if (id == "labelConfig") {
874 } else if (id == "genConfig") {
876 } else if (id == "userConfig") {
880 var tab = dijit.byId(id + "Tab");
881 dijit.byId("pref-tabs").selectChild(tab);
886 exception_error("selectTab", e);
890 function init_second_stage() {
893 document.onkeydown = pref_hotkey_handler;
894 loading_set_progress(50);
897 dojo.addOnLoad(function() {
898 var tab = getURLParam('tab');
901 tab = dijit.byId(tab + "Tab");
902 if (tab) dijit.byId("pref-tabs").selectChild(tab);
905 var method = getURLParam('method');
907 if (method == 'editFeed') {
908 var param = getURLParam('methodparam');
910 window.setTimeout('editFeed(' + param + ')', 100);
914 setTimeout("hotkey_prefix_timeout()", 5*1000);
917 exception_error("init_second_stage", e);
924 dojo.registerModulePath("lib", "..");
925 dojo.registerModulePath("fox", "../../js/");
927 dojo.require("dijit.ColorPalette");
928 dojo.require("dijit.Dialog");
929 dojo.require("dijit.form.Button");
930 dojo.require("dijit.form.CheckBox");
931 dojo.require("dijit.form.DropDownButton");
932 dojo.require("dijit.form.FilteringSelect");
933 dojo.require("dijit.form.Form");
934 dojo.require("dijit.form.RadioButton");
935 dojo.require("dijit.form.Select");
936 dojo.require("dijit.form.SimpleTextarea");
937 dojo.require("dijit.form.TextBox");
938 dojo.require("dijit.form.ValidationTextBox");
939 dojo.require("dijit.InlineEditBox");
940 dojo.require("dijit.layout.AccordionContainer");
941 dojo.require("dijit.layout.BorderContainer");
942 dojo.require("dijit.layout.ContentPane");
943 dojo.require("dijit.layout.TabContainer");
944 dojo.require("dijit.Menu");
945 dojo.require("dijit.ProgressBar");
946 dojo.require("dijit.ProgressBar");
947 dojo.require("dijit.Toolbar");
948 dojo.require("dijit.Tree");
949 dojo.require("dijit.tree.dndSource");
950 dojo.require("dojo.data.ItemFileWriteStore");
952 dojo.require("lib.CheckBoxTree");
953 dojo.require("fox.PrefFeedTree");
954 dojo.require("fox.PrefFilterTree");
955 dojo.require("fox.PrefLabelTree");
959 dojo.addOnLoad(function() {
960 loading_set_progress(50);
962 new Ajax.Request("backend.php", {
963 parameters: {op: "rpc", method: "sanityCheck"},
964 onComplete: function(transport) {
965 backend_sanity_check_callback(transport);
970 exception_error("init", e);
974 function validatePrefsReset() {
976 var ok = confirm(__("Reset to defaults?"));
980 query = "?op=pref-prefs&method=resetconfig";
983 new Ajax.Request("backend.php", {
985 onComplete: function(transport) {
986 var msg = transport.responseText;
987 if (msg.match("PREFS_THEME_CHANGED")) {
988 window.location.reload();
998 exception_error("validatePrefsReset", e);
1006 function pref_hotkey_handler(e) {
1008 if (e.target.nodeName == "INPUT" || e.target.nodeName == "TEXTAREA") return;
1010 var keycode = false;
1011 var shift_key = false;
1013 var cmdline = $('cmdline');
1016 shift_key = e.shiftKey;
1022 keycode = window.event.keyCode;
1027 var keychar = String.fromCharCode(keycode);
1029 if (keycode == 27) { // escape
1030 if (Element.visible("hotkey_help_overlay")) {
1031 Element.hide("hotkey_help_overlay");
1033 hotkey_prefix = false;
1037 if (keycode == 16) return; // ignore lone shift
1038 if (keycode == 17) return; // ignore lone ctrl
1040 if ((keycode == 67 || keycode == 71) && !hotkey_prefix) {
1041 hotkey_prefix = keycode;
1043 var date = new Date();
1044 var ts = Math.round(date.getTime() / 1000);
1046 hotkey_prefix_pressed = ts;
1048 cmdline.innerHTML = keychar;
1049 Element.show(cmdline);
1051 console.log("KP: PREFIX=" + keycode + " CHAR=" + keychar);
1055 if (Element.visible("hotkey_help_overlay")) {
1056 Element.hide("hotkey_help_overlay");
1059 if (keycode == 13 || keycode == 27) {
1062 seq = seq + "" + keycode;
1065 /* Global hotkeys */
1067 Element.hide(cmdline);
1069 if (!hotkey_prefix) {
1071 if ((keycode == 191 || keychar == '?') && shift_key) { // ?
1076 if (keycode == 191 || keychar == '/') { // /
1077 var search_boxes = new Array("label_search",
1078 "feed_search", "filter_search", "user_search", "feed_browser_search");
1080 for (var i = 0; i < search_boxes.length; i++) {
1081 var elem = $(search_boxes[i]);
1083 $(search_boxes[i]).focus();
1092 if (hotkey_prefix == 67) { // c
1093 hotkey_prefix = false;
1095 if (keycode == 70) { // f
1100 if (keycode == 83) { // s
1105 if (keycode == 85) { // u
1109 if (keycode == 67) { // c
1114 if (keycode == 84 && shift_key) { // T
1123 if (hotkey_prefix == 71) { // g
1125 hotkey_prefix = false;
1127 if (keycode == 49 && $("genConfigTab")) { // 1
1128 selectTab("genConfig");
1132 if (keycode == 50 && $("feedConfigTab")) { // 2
1133 selectTab("feedConfig");
1137 if (keycode == 51 && $("filterConfigTab")) { // 4
1138 selectTab("filterConfig");
1142 if (keycode == 52 && $("labelConfigTab")) { // 5
1143 selectTab("labelConfig");
1147 if (keycode == 53 && $("userConfigTab")) { // 6
1148 selectTab("userConfig");
1152 if (keycode == 88) { // x
1159 if (seq.match("8073717369")) {
1167 if (hotkey_prefix) {
1168 console.log("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
1170 console.log("KP: CODE=" + keycode + " CHAR=" + keychar);
1174 exception_error("pref_hotkey_handler", e);
1178 function removeCategory(id, item) {
1181 var ok = confirm(__("Remove category %s? Any nested feeds would be placed into Uncategorized.").replace("%s", item.name));
1184 var query = "?op=pref-feeds&method=removeCat&ids="+
1187 notify_progress("Removing category...");
1189 new Ajax.Request("backend.php", {
1191 onComplete: function(transport) {
1198 exception_error("removeCategory", e);
1202 function createCategory() {
1204 var title = prompt(__("Category title:"));
1208 notify_progress("Creating category...");
1210 var query = "?op=pref-feeds&method=addCat&cat=" +
1211 param_escape(title);
1213 new Ajax.Request("backend.php", {
1215 onComplete: function(transport) {
1222 exception_error("createCategory", e);
1226 function showInactiveFeeds() {
1228 var query = "backend.php?op=dlg&method=inactiveFeeds";
1230 if (dijit.byId("inactiveFeedsDlg"))
1231 dijit.byId("inactiveFeedsDlg").destroyRecursive();
1233 dialog = new dijit.Dialog({
1234 id: "inactiveFeedsDlg",
1235 title: __("Feeds without recent updates"),
1236 style: "width: 600px",
1237 getSelectedFeeds: function() {
1238 return getSelectedTableRowIds("prefInactiveFeedList");
1240 removeSelected: function() {
1241 var sel_rows = this.getSelectedFeeds();
1243 console.log(sel_rows);
1245 if (sel_rows.length > 0) {
1246 var ok = confirm(__("Remove selected feeds?"));
1249 notify_progress("Removing selected feeds...", true);
1251 var query = "?op=pref-feeds&method=remove&ids="+
1252 param_escape(sel_rows.toString());
1254 new Ajax.Request("backend.php", {
1256 onComplete: function(transport) {
1264 alert(__("No feeds are selected."));
1267 execute: function() {
1268 if (this.validate()) {
1276 exception_error("showInactiveFeeds", e);
1281 function opmlRegenKey() {
1284 var ok = confirm(__("Replace current OPML publishing address with a new one?"));
1288 notify_progress("Trying to change address...", true);
1290 var query = "?op=rpc&method=regenOPMLKey";
1292 new Ajax.Request("backend.php", {
1294 onComplete: function(transport) {
1295 var reply = JSON.parse(transport.responseText);
1297 var new_link = reply.link;
1299 var e = $('pub_opml_url');
1303 e.innerHTML = new_link;
1305 new Effect.Highlight(e);
1310 notify_error("Could not change feed URL.");
1315 exception_error("opmlRegenKey", e);
1320 function feedActionChange() {
1322 var chooser = $("feedActionChooser");
1323 var opid = chooser[chooser.selectedIndex].value;
1325 chooser.selectedIndex = 0;
1328 exception_error("feedActionChange", e);
1332 function feedActionGo(op) {
1334 if (op == "facEdit") {
1336 var rows = getSelectedFeeds();
1338 if (rows.length > 1) {
1339 editSelectedFeeds();
1345 if (op == "facClear") {
1346 clearSelectedFeeds();
1349 if (op == "facPurge") {
1350 purgeSelectedFeeds();
1353 if (op == "facEditCats") {
1357 if (op == "facRescore") {
1358 rescoreSelectedFeeds();
1361 if (op == "facUnsubscribe") {
1362 removeSelectedFeeds();
1366 exception_error("feedActionGo", e);
1371 function clearFeedArticles(feed_id) {
1373 notify_progress("Clearing feed...");
1375 var query = "?op=pref-feeds&quiet=1&method=clear&id=" + feed_id;
1377 new Ajax.Request("backend.php", {
1379 onComplete: function(transport) {
1386 function rescoreSelectedFeeds() {
1388 var sel_rows = getSelectedFeeds();
1390 if (sel_rows.length > 0) {
1392 //var ok = confirm(__("Rescore last 100 articles in selected feeds?"));
1393 var ok = confirm(__("Rescore articles in selected feeds?"));
1396 notify_progress("Rescoring selected feeds...", true);
1398 var query = "?op=pref-feeds&method=rescore&quiet=1&ids="+
1399 param_escape(sel_rows.toString());
1401 new Ajax.Request("backend.php", {
1403 onComplete: function(transport) {
1404 notify_callback2(transport);
1409 alert(__("No feeds are selected."));
1415 function rescore_all_feeds() {
1416 var ok = confirm(__("Rescore all articles? This operation may take a lot of time."));
1419 notify_progress("Rescoring feeds...", true);
1421 var query = "?op=pref-feeds&method=rescoreAll&quiet=1";
1423 new Ajax.Request("backend.php", {
1425 onComplete: function(transport) {
1426 notify_callback2(transport);
1431 function labelColorReset() {
1433 var labels = getSelectedLabels();
1435 if (labels.length > 0) {
1436 var ok = confirm(__("Reset selected labels to default colors?"));
1439 var query = "?op=pref-labels&method=colorreset&ids="+
1440 param_escape(labels.toString());
1442 new Ajax.Request("backend.php", {
1444 onComplete: function(transport) {
1450 alert(__("No labels are selected."));
1454 exception_error("labelColorReset", e);
1459 function inPreferences() {
1463 function editProfiles() {
1466 if (dijit.byId("profileEditDlg"))
1467 dijit.byId("profileEditDlg").destroyRecursive();
1469 var query = "backend.php?op=dlg&method=editPrefProfiles";
1471 dialog = new dijit.Dialog({
1472 id: "profileEditDlg",
1473 title: __("Settings Profiles"),
1474 style: "width: 600px",
1475 getSelectedProfiles: function() {
1476 return getSelectedTableRowIds("prefFeedProfileList");
1478 removeSelected: function() {
1479 var sel_rows = this.getSelectedProfiles();
1481 if (sel_rows.length > 0) {
1482 var ok = confirm(__("Remove selected profiles? Active and default profiles will not be removed."));
1485 notify_progress("Removing selected profiles...", true);
1487 var query = "?op=rpc&method=remprofiles&ids="+
1488 param_escape(sel_rows.toString());
1490 new Ajax.Request("backend.php", {
1492 onComplete: function(transport) {
1500 alert(__("No profiles are selected."));
1503 activateProfile: function() {
1504 var sel_rows = this.getSelectedProfiles();
1506 if (sel_rows.length == 1) {
1508 var ok = confirm(__("Activate selected profile?"));
1511 notify_progress("Loading, please wait...");
1513 var query = "?op=rpc&method=setprofile&id="+
1514 param_escape(sel_rows.toString());
1516 new Ajax.Request("backend.php", {
1518 onComplete: function(transport) {
1519 window.location.reload();
1524 alert(__("Please choose a profile to activate."));
1527 addProfile: function() {
1528 if (this.validate()) {
1529 notify_progress("Creating profile...", true);
1531 var query = "?op=rpc&method=addprofile&title=" +
1532 param_escape(dialog.attr('value').newprofile);
1534 new Ajax.Request("backend.php", {
1536 onComplete: function(transport) {
1543 execute: function() {
1544 if (this.validate()) {
1551 exception_error("editProfiles", e);
1555 function activatePrefProfile() {
1557 var sel_rows = getSelectedFeedCats();
1559 if (sel_rows.length == 1) {
1561 var ok = confirm(__("Activate selected profile?"));
1564 notify_progress("Loading, please wait...");
1566 var query = "?op=rpc&method=setprofile&id="+
1567 param_escape(sel_rows.toString());
1569 new Ajax.Request("backend.php", {
1571 onComplete: function(transport) {
1572 window.location.reload();
1577 alert(__("Please choose a profile to activate."));
1583 function clearFeedAccessKeys() {
1585 var ok = confirm(__("This will invalidate all previously generated feed URLs. Continue?"));
1588 notify_progress("Clearing URLs...");
1590 var query = "?op=rpc&method=clearKeys";
1592 new Ajax.Request("backend.php", {
1594 onComplete: function(transport) {
1595 notify_info("Generated URLs cleared.");
1602 function clearArticleAccessKeys() {
1604 var ok = confirm(__("This will invalidate all previously shared article URLs. Continue?"));
1607 notify_progress("Clearing URLs...");
1609 var query = "?op=rpc&method=clearArticleKeys";
1611 new Ajax.Request("backend.php", {
1613 onComplete: function(transport) {
1614 notify_info("Shared URLs cleared.");
1620 function resetFeedOrder() {
1622 notify_progress("Loading, please wait...");
1624 new Ajax.Request("backend.php", {
1625 parameters: "?op=pref-feeds&method=feedsortreset",
1626 onComplete: function(transport) {
1632 exception_error("resetFeedOrder");
1636 function resetCatOrder() {
1638 notify_progress("Loading, please wait...");
1640 new Ajax.Request("backend.php", {
1641 parameters: "?op=pref-feeds&method=catsortreset",
1642 onComplete: function(transport) {
1648 exception_error("resetCatOrder");
1652 function toggleHiddenFeedCats() {
1654 notify_progress("Loading, please wait...");
1656 new Ajax.Request("backend.php", {
1657 parameters: "?op=pref-feeds&method=togglehiddenfeedcats",
1658 onComplete: function(transport) {
1663 exception_error("toggleHiddenFeedCats");
1667 function editCat(id, item, event) {
1669 var new_name = prompt(__('Rename category to:'), item.name);
1671 if (new_name && new_name != item.name) {
1673 notify_progress("Loading, please wait...");
1675 new Ajax.Request("backend.php", {
1678 method: 'renamecat',
1682 onComplete: function(transport) {
1688 exception_error("editCat", e);
1692 function editLabel(id, event) {
1694 var query = "backend.php?op=pref-labels&method=edit&id=" +
1697 if (dijit.byId("labelEditDlg"))
1698 dijit.byId("labelEditDlg").destroyRecursive();
1700 dialog = new dijit.Dialog({
1702 title: __("Label Editor"),
1703 style: "width: 600px",
1704 setLabelColor: function(id, fg, bg) {
1719 var query = "?op=pref-labels&method=colorset&kind="+kind+
1720 "&ids=" + param_escape(id) + "&fg=" + param_escape(fg) +
1721 "&bg=" + param_escape(bg) + "&color=" + param_escape(color);
1723 // console.log(query);
1725 var e = $("LICID-" + id);
1728 if (fg) e.style.color = fg;
1729 if (bg) e.style.backgroundColor = bg;
1732 new Ajax.Request("backend.php", { parameters: query });
1736 execute: function() {
1737 if (this.validate()) {
1738 var caption = this.attr('value').caption;
1739 var fg_color = this.attr('value').fg_color;
1740 var bg_color = this.attr('value').bg_color;
1741 var query = dojo.objectToQuery(this.attr('value'));
1743 dijit.byId('labelTree').setNameById(id, caption);
1744 this.setLabelColor(id, fg_color, bg_color);
1747 new Ajax.Request("backend.php", {
1749 onComplete: function(transport) {
1759 exception_error("editLabel", e);
1763 function clearTwitterCredentials() {
1765 var ok = confirm(__("This will clear your stored authentication information for Twitter. Continue?"));
1768 notify_progress("Clearing credentials...");
1770 var query = "?op=pref-feeds&method=remtwitterinfo";
1772 new Ajax.Request("backend.php", {
1774 onComplete: function(transport) {
1775 notify_info("Twitter credentials have been cleared.");
1781 exception_error("clearTwitterCredentials", e);
1785 function customizeCSS() {
1787 var query = "backend.php?op=dlg&method=customizeCSS";
1789 if (dijit.byId("cssEditDlg"))
1790 dijit.byId("cssEditDlg").destroyRecursive();
1792 dialog = new dijit.Dialog({
1794 title: __("Customize stylesheet"),
1795 style: "width: 600px",
1796 execute: function() {
1797 notify_progress('Saving data...', true);
1798 new Ajax.Request("backend.php", {
1799 parameters: dojo.objectToQuery(this.attr('value')),
1800 onComplete: function(transport) {
1802 window.location.reload();
1811 exception_error("customizeCSS", e);
1815 function insertSSLserial(value) {
1817 dijit.byId("SSL_CERT_SERIAL").attr('value', value);
1819 exception_error("insertSSLcerial", e);
1823 function getSelectedInstances() {
1824 return getSelectedTableRowIds("prefInstanceList");
1827 function addInstance() {
1829 var query = "backend.php?op=dlg&method=addInstance";
1831 if (dijit.byId("instanceAddDlg"))
1832 dijit.byId("instanceAddDlg").destroyRecursive();
1834 dialog = new dijit.Dialog({
1835 id: "instanceAddDlg",
1836 title: __("Link Instance"),
1837 style: "width: 600px",
1838 regenKey: function() {
1839 new Ajax.Request("backend.php", {
1840 parameters: "?op=rpc&method=genHash",
1841 onComplete: function(transport) {
1842 var reply = JSON.parse(transport.responseText);
1844 dijit.byId('instance_add_key').attr('value', reply.hash);
1848 execute: function() {
1849 if (this.validate()) {
1850 console.warn(dojo.objectToQuery(this.attr('value')));
1852 notify_progress('Saving data...', true);
1853 new Ajax.Request("backend.php", {
1854 parameters: dojo.objectToQuery(this.attr('value')),
1855 onComplete: function(transport) {
1858 updateInstanceList();
1868 exception_error("addInstance", e);
1872 function editInstance(id, event) {
1874 if (!event || !event.ctrlKey) {
1876 selectTableRows('prefInstanceList', 'none');
1877 selectTableRowById('LIRR-'+id, 'LICHK-'+id, true);
1879 var query = "backend.php?op=pref-instances&method=edit&id=" +
1882 if (dijit.byId("instanceEditDlg"))
1883 dijit.byId("instanceEditDlg").destroyRecursive();
1885 dialog = new dijit.Dialog({
1886 id: "instanceEditDlg",
1887 title: __("Edit Instance"),
1888 style: "width: 600px",
1889 regenKey: function() {
1890 new Ajax.Request("backend.php", {
1891 parameters: "?op=rpc&method=genHash",
1892 onComplete: function(transport) {
1893 var reply = JSON.parse(transport.responseText);
1895 dijit.byId('instance_edit_key').attr('value', reply.hash);
1899 execute: function() {
1900 if (this.validate()) {
1901 // console.warn(dojo.objectToQuery(this.attr('value')));
1903 notify_progress('Saving data...', true);
1904 new Ajax.Request("backend.php", {
1905 parameters: dojo.objectToQuery(this.attr('value')),
1906 onComplete: function(transport) {
1909 updateInstanceList();
1918 } else if (event.ctrlKey) {
1919 var cb = $('LICHK-' + id);
1920 cb.checked = !cb.checked;
1921 toggleSelectRow(cb);
1926 exception_error("editInstance", e);
1930 function removeSelectedInstances() {
1932 var sel_rows = getSelectedInstances();
1934 if (sel_rows.length > 0) {
1936 var ok = confirm(__("Remove selected instances?"));
1939 notify_progress("Removing selected instances...");
1941 var query = "?op=pref-instances&method=remove&ids="+
1942 param_escape(sel_rows.toString());
1944 new Ajax.Request("backend.php", {
1946 onComplete: function(transport) {
1948 updateInstanceList();
1953 alert(__("No instances are selected."));
1957 exception_error("removeInstance", e);
1961 function editSelectedInstance() {
1962 var rows = getSelectedInstances();
1964 if (rows.length == 0) {
1965 alert(__("No instances are selected."));
1969 if (rows.length > 1) {
1970 alert(__("Please select only one instance."));
1976 editInstance(rows[0]);
1979 function showHelp() {
1981 new Ajax.Request("backend.php", {
1982 parameters: "?op=backend&method=help&topic=prefs",
1983 onComplete: function(transport) {
1984 $("hotkey_help_overlay").innerHTML = transport.responseText;
1985 Effect.Appear("hotkey_help_overlay", {duration : 0.3});
1989 exception_error("showHelp", e);
1993 function exportData() {
1996 var query = "backend.php?op=dlg&method=exportData";
1998 if (dijit.byId("dataExportDlg"))
1999 dijit.byId("dataExportDlg").destroyRecursive();
2003 dialog = new dijit.Dialog({
2004 id: "dataExportDlg",
2005 title: __("Export Data"),
2006 style: "width: 600px",
2007 prepare: function() {
2009 notify_progress("Loading, please wait...");
2011 new Ajax.Request("backend.php", {
2012 parameters: "?op=rpc&method=exportrun&offset=" + exported,
2013 onComplete: function(transport) {
2015 var rv = JSON.parse(transport.responseText);
2017 if (rv && rv.exported != undefined) {
2018 if (rv.exported > 0) {
2020 exported += rv.exported;
2022 $("export_status_message").innerHTML =
2023 "<img src='images/indicator_tiny.gif'> " +
2024 "Exported %d articles, please wait...".replace("%d",
2027 setTimeout('dijit.byId("dataExportDlg").prepare()', 2000);
2031 $("export_status_message").innerHTML =
2032 __("Finished, exported %d articles. You can download the data <a class='visibleLink' href='%u'>here</a>.")
2033 .replace("%d", exported)
2034 .replace("%u", "backend.php?op=rpc&subop=exportget");
2041 $("export_status_message").innerHTML =
2042 "Error occured, could not export data.";
2045 exception_error("exportData", e, transport.responseText);
2053 execute: function() {
2054 if (this.validate()) {
2066 exception_error("exportData", e);
2070 function dataImportComplete(iframe) {
2072 if (!iframe.contentDocument.body.innerHTML) return false;
2074 Element.hide(iframe);
2078 if (dijit.byId('dataImportDlg'))
2079 dijit.byId('dataImportDlg').destroyRecursive();
2081 var content = iframe.contentDocument.body.innerHTML;
2083 dialog = new dijit.Dialog({
2084 id: "dataImportDlg",
2085 title: __("Data Import"),
2086 style: "width: 600px",
2087 onCancel: function() {
2095 exception_error("dataImportComplete", e);
2099 function gotoExportOpml(filename, settings) {
2100 tmp = settings ? 1 : 0;
2101 document.location.href = "backend.php?op=opml&method=export&filename=" + filename + "&settings=" + tmp;
2105 function batchSubscribe() {
2107 var query = "backend.php?op=dlg&method=batchSubscribe";
2109 if (dijit.byId("batchSubDlg"))
2110 dijit.byId("batchSubDlg").destroyRecursive();
2112 var dialog = new dijit.Dialog({
2114 title: __("Batch subscribe"),
2115 style: "width: 600px",
2116 execute: function() {
2117 if (this.validate()) {
2118 console.log(dojo.objectToQuery(this.attr('value')));
2120 notify_progress(__("Subscribing to feeds..."), true);
2122 new Ajax.Request("backend.php", {
2123 parameters: dojo.objectToQuery(this.attr('value')),
2124 onComplete: function(transport) {
2135 exception_error("batchSubscribe", e);
2139 function updateSelf() {
2141 var query = "backend.php?op=pref-prefs&method=updateSelf";
2143 if (dijit.byId("updateSelfDlg"))
2144 dijit.byId("updateSelfDlg").destroyRecursive();
2146 var dialog = new dijit.Dialog({
2147 id: "updateSelfDlg",
2148 title: __("Update Tiny Tiny RSS"),
2149 style: "width: 600px",
2151 performUpdate: function(step) {
2152 dijit.byId("self_update_start_btn").attr("disabled", true);
2153 dijit.byId("self_update_stop_btn").attr("disabled", true);
2155 notify_progress("Loading, please wait...", true);
2156 new Ajax.Request("backend.php", {
2157 parameters: "?op=pref-prefs&method=performUpdate&step=" + step +
2158 "¶ms=" + param_escape(JSON.stringify(dialog.attr("update-params"))),
2159 onComplete: function(transport) {
2161 rv = JSON.parse(transport.responseText);
2165 rv['log'].each(function(line) {
2166 $("self_update_log").innerHTML += "<li>" + line + "</li>";
2169 dialog.attr("update-params", rv['params']);
2172 window.setTimeout("dijit.byId('updateSelfDlg').performUpdate("+(step+1)+")", 500);
2174 dijit.byId("self_update_stop_btn").attr("disabled", false);
2178 console.log(transport.responseText);
2179 notify_error("Received invalid data from server.");
2182 dialog.attr("updated", true);
2184 exception_error("updateSelf/inner", e);
2189 if (dialog.attr("updated")) {
2190 window.location.reload();
2196 if (prompt(__("Live updating is considered experimental. Backup your tt-rss directory before continuing. Please type 'yes' to continue.")) == 'yes') {
2197 dialog.performUpdate(0);
2204 exception_error("batchSubscribe", e);
2208 function toggleAdvancedPrefs() {
2210 notify_progress("Loading, please wait...");
2212 new Ajax.Request("backend.php", {
2213 parameters: "?op=pref-prefs&method=toggleadvanced",
2214 onComplete: function(transport) {
2219 exception_error("toggleAdvancedPrefs", e);